import Data.List ( isPrefixOf ) import Distribution.Compat.Exception ( tryIO ) import Distribution.PackageDescription ( PackageDescription(..) ) import Distribution.Simple ( UserHooks(..), defaultMainWithHooks, simpleUserHooks ) import Distribution.Simple.LocalBuildInfo ( LocalBuildInfo(..) ) import Distribution.Simple.Program.Run ( getProgramInvocationOutput, simpleProgramInvocation ) import Distribution.Simple.Utils ( createDirectoryIfMissingVerbose ) import Distribution.Verbosity ( Verbosity, silent ) main :: IO () main = defaultMainWithHooks $ simpleUserHooks { buildHook = \pkgDesc lbi hooks flags -> do git_version <- gitDescribe git_branch <- gitBranch let git_full_version = fmap (maybe "" (++":") git_branch ++) git_version createDirectoryIfMissingVerbose silent False (buildDir lbi ++ "/autogen") writeFileIfChanged (buildDir lbi ++ "/autogen/GitVersion.hs") $ unlines [ "module GitVersion (gitVersion,gitBranch,gitFullVersion) where" , "import Prelude" , "gitVersion :: Maybe String" , "gitVersion = " ++ show git_version , "{-# NOINLINE gitVersion #-}" , "gitBranch :: Maybe String" , "gitBranch = " ++ show git_branch , "{-# NOINLINE gitBranch #-}" , "gitFullVersion :: Maybe String" , "gitFullVersion = " ++ show git_full_version , "{-# NOINLINE gitFullVersion #-}" ] buildHook simpleUserHooks pkgDesc lbi hooks flags } writeFileIfChanged :: FilePath -> String -> IO () writeFileIfChanged fp new = do old <- tryIO $ do s <- readFile fp ; length s `seq` return s if old == Right new then return () else writeFile fp new gitDescribe :: IO (Maybe String) gitDescribe = fmap (either (const Nothing) (Just . unwords . lines)) $ tryIO $ getProgramInvocationOutput silent $ simpleProgramInvocation "git" ["describe", "--always", "--long"] gitBranch :: IO (Maybe String) gitBranch = fmap (either (const Nothing) get_branch) $ tryIO $ getProgramInvocationOutput silent $ simpleProgramInvocation "git" ["branch"] where get_branch s = case map words . filter ("*" `isPrefixOf`) $ lines s of [_:b:_] -> Just b _ -> Nothing