packages feed

ampersand-3.0.0: Setup.hs

{-# OPTIONS_GHC -Wall #-}  
import Distribution.Simple
import Distribution.Simple.LocalBuildInfo
import Distribution.Simple.Setup
import Distribution.PackageDescription
--import System.Time
import System.Process
import System.IO
import Control.Exception
import Data.List
import Data.Time.Clock
import Data.Time.Format
import System.Locale

main :: IO ()
main = defaultMainWithHooks (simpleUserHooks { buildHook = generateBuildInfoHook } )

-- Before each build, generate a BuildInfo_Generated module that exports the project version from cabal,
-- the current svn revision number and the build time.
--
-- Note that in order for this Setup.hs to be used by cabal, the build-type should be Custom.

generateBuildInfoHook :: PackageDescription -> LocalBuildInfo -> UserHooks -> BuildFlags -> IO ()
generateBuildInfoHook pd  lbi uh bf = 
 do { let cabalVersionStr = intercalate "." (map show . versionBranch . pkgVersion . package $ pd)

    ; svnRevisionStr <- do { r <- catch getSVNRevisionStr myHandler 
                           ; if r == "" 
                             then noSVNRevisionStr
                             else return r
                           }
    ; clockTime <- getCurrentTime 
    ; let buildTimeStr = formatTime defaultTimeLocale "%d-%b-%y %H:%M:%S %Z" clockTime
    ; writeFile "src/lib/DatabaseDesign/Ampersand/Basics/BuildInfo_Generated.hs" $
        buildInfoModule cabalVersionStr svnRevisionStr buildTimeStr

    ; (buildHook simpleUserHooks) pd lbi uh bf -- start the build
    }
 where myHandler :: IOException -> IO String
       myHandler err = do { print err
                          ; noSVNRevisionStr
                          }

buildInfoModule :: String -> String -> String -> String
buildInfoModule cabalVersion revision time = unlines
 [ "module DatabaseDesign.Ampersand.Basics.BuildInfo_Generated (cabalVersionStr, svnRevisionStr, buildTimeStr) where"
 , ""
 , "-- This module is generated automatically by Setup.hs before building. Do not edit!"
 , ""
 , "{-# NOINLINE cabalVersionStr #-}" -- disable inlining to prevent recompilation of dependent modules on each build
 , "cabalVersionStr :: String"
 , "cabalVersionStr = \"" ++ cabalVersion ++ "\""
 , ""
 , "{-# NOINLINE svnRevisionStr #-}"
 , "svnRevisionStr :: String"
 , "svnRevisionStr = \"" ++ revision ++ "\""
 , ""
 , "{-# NOINLINE buildTimeStr #-}"
 , "buildTimeStr :: String"
 , "buildTimeStr = \"" ++ time ++ "\""
 ]

getSVNRevisionStr :: IO String
getSVNRevisionStr = 
 do { (inh,outh,errh,proch) <- runInteractiveProcess "svnversion" ["."] Nothing Nothing
    ; hClose inh
    ; hClose errh
    ; version <- hGetContents outh
    ; _ <- seq version $ waitForProcess proch
    ; return (unwords . lines $ version)
    }

noSVNRevisionStr :: IO String
noSVNRevisionStr =
 do { putStrLn "\n\n\nWARNING: Execution of 'svnversion' command failed."
    ; putStrLn $ "BuildInfo_Generated.hs will not contain revision information, and therefore\nneither will fatal error messages.\n"++
                 "Please find out why the command  'svnversion .' does not work.\n"++
                 "Otherwise (re-)install a subversion client (e.g. 'Slik SVN') that supports\nthe command-line 'svnversion'-command without interfering with your other SVN-clients.\n"
    ; return "??"
    }