-
Notifications
You must be signed in to change notification settings - Fork 6
/
Setup.hs
106 lines (97 loc) · 4.31 KB
/
Setup.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#!/usr/bin/env runhaskell
import Data.Char (isDigit, toLower)
import Data.Function (on)
import Data.List (intercalate, sortBy)
import Data.Monoid ((<>))
import Data.Version (showVersion)
import Distribution.InstalledPackageInfo
import Distribution.PackageDescription
import Distribution.Simple
import Distribution.Simple.Setup (BuildFlags(..), ReplFlags(..), TestFlags(..), fromFlag)
import Distribution.Simple.LocalBuildInfo
import Distribution.Simple.PackageIndex
import Distribution.Simple.BuildPaths (autogenModulesDir)
import Distribution.Simple.Utils (createDirectoryIfMissingVerbose, rewriteFile, rawSystemStdout)
import Distribution.Verbosity
main :: IO ()
main =
let hooks = simpleUserHooks
in defaultMainWithHooks hooks {
preConf = \args flags -> do
createDirectoryIfMissingVerbose silent True "gen"
(preConf hooks) args flags
, sDistHook = \pd mlbi uh flags -> do
genBuildInfo silent pd
(sDistHook hooks) pd mlbi uh flags
, buildHook = \pd lbi uh flags -> do
genBuildInfo (fromFlag $ buildVerbosity flags) pd
genDependencyInfo (fromFlag $ buildVerbosity flags) pd lbi
(buildHook hooks) pd lbi uh flags
, replHook = \pd lbi uh flags args -> do
genBuildInfo (fromFlag $ replVerbosity flags) pd
genDependencyInfo (fromFlag $ replVerbosity flags) pd lbi
(replHook hooks) pd lbi uh flags args
, testHook = \args pd lbi uh flags -> do
genBuildInfo (fromFlag $ testVerbosity flags) pd
genDependencyInfo (fromFlag $ testVerbosity flags) pd lbi
(testHook hooks) args pd lbi uh flags
}
genBuildInfo :: Verbosity -> PackageDescription -> IO ()
genBuildInfo verbosity pkg = do
createDirectoryIfMissingVerbose verbosity True "gen"
let (PackageName pname) = pkgName . package $ pkg
version = pkgVersion . package $ pkg
name = "BuildInfo_" ++ (map (\c -> if c == '-' then '_' else c) pname)
targetHs = "gen/" ++ name ++ ".hs"
targetText = "gen/version.txt"
t <- timestamp verbosity
gv <- gitVersion verbosity
let v = showVersion version
let buildVersion = intercalate "-" [v, t, gv]
rewriteFile targetHs $ unlines [
"module " ++ name ++ " where"
, "import Prelude"
, "data RuntimeBuildInfo = RuntimeBuildInfo { buildVersion :: String, timestamp :: String, gitVersion :: String }"
, "buildInfo :: RuntimeBuildInfo"
, "buildInfo = RuntimeBuildInfo \"" ++ v ++ "\" \"" ++ t ++ "\" \"" ++ gv ++ "\""
, "buildInfoVersion :: String"
, "buildInfoVersion = \"" ++ buildVersion ++ "\""
]
rewriteFile targetText buildVersion
genDependencyInfo :: Verbosity -> PackageDescription -> LocalBuildInfo -> IO ()
genDependencyInfo verbosity pkg info = do
let
(PackageName pname) = pkgName . package $ pkg
name = "DependencyInfo_" ++ (map (\c -> if c == '-' then '_' else c) pname)
targetHs = autogenModulesDir info ++ "/" ++ name ++ ".hs"
render p =
let
n = unPackageName $ pkgName p
v = intercalate "." . fmap show . versionBranch $ pkgVersion p
in
n ++ "-" ++ v
deps = fmap (render . sourcePackageId) . allPackages $ installedPkgs info
sdeps = sortBy (compare `on` fmap toLower) deps
strs = flip fmap sdeps $ \d -> "\"" ++ d ++ "\""
createDirectoryIfMissingVerbose verbosity True (autogenModulesDir info)
rewriteFile targetHs $ unlines [
"module " ++ name ++ " where"
, "import Prelude"
, "dependencyInfo :: [String]"
, "dependencyInfo = [\n " ++ intercalate "\n , " strs ++ "\n ]"
]
gitVersion :: Verbosity -> IO String
gitVersion verbosity = do
ver <- rawSystemStdout verbosity "git" ["log", "--pretty=format:%h", "-n", "1"]
notModified <- ((>) 1 . length) `fmap` rawSystemStdout verbosity "git" ["status", "--porcelain"]
return $ ver ++ if notModified then "" else "-M"
timestamp :: Verbosity -> IO String
timestamp verbosity =
rawSystemStdout verbosity "date" ["+%Y%m%d%H%M%S"] >>= \s ->
case splitAt 14 s of
(d, n : []) ->
if (length d == 14 && filter isDigit d == d)
then return d
else fail $ "date has failed to produce the correct format [" <> s <> "]."
_ ->
fail $ "date has failed to produce a date long enough [" <> s <> "]."