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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
#!/usr/bin/env runhaskell
{-# LANGUAGE CPP #-}
{-# LANGUAGE RecordWildCards #-}
import Control.Monad
import Data.Maybe
import System.Console.GetOpt
import System.Directory
import System.Environment
import System.Exit
import System.FilePath
import System.IO
import System.Process
baseDir, rootDir :: FilePath
baseDir = takeDirectory __FILE__
rootDir = baseDir </> ".."
srcDir, refDir, outDir :: FilePath
srcDir = baseDir </> "src"
refDir = baseDir </> "ref"
outDir = baseDir </> "out"
resDir :: FilePath
resDir = rootDir </> "resources"
data Config = Config
{ cfgHaddockPath :: FilePath
, cfgFiles :: [FilePath]
}
main :: IO ()
main = do
Config { .. } <- parseArgs =<< getArgs
env <- Just . (:) ("haddock_datadir", resDir) <$> getEnvironment
handle <- runProcess' cfgHaddockPath $ processConfig
{ pcEnv = env
, pcArgs = ["--version"]
}
waitForSuccess "Failed to run `haddock --version`" handle
handle <- runProcess' cfgHaddockPath $ processConfig
{ pcEnv = env
, pcArgs = ["--ghc-version"]
}
waitForSuccess "Failed to run `haddock --ghc-version`" handle
putStrLn $ "Files to test: " ++ show cfgFiles
parseArgs :: [String] -> IO Config
parseArgs args = do
let (flags, files, errors) = getOpt Permute options args
when (not $ null errors) $ do
hPutStr stderr $ concat errors
exitFailure
when (FlagHelp `elem` flags) $ do
hPutStrLn stderr $ usageInfo "" options
exitSuccess
cfgFiles <- processFileArgs files
let cfgHaddockPath = haddockPath flags
return $ Config { .. }
processFileArgs :: [String] -> IO [FilePath]
processFileArgs [] = filter isSourceFile <$> getDirectoryContents srcDir
processFileArgs args = pure $ map processFileArg args
processFileArg :: String -> FilePath
processFileArg arg
| isSourceFile arg = arg
| otherwise = srcDir </> arg <.> "hs"
isSourceFile :: FilePath -> Bool
isSourceFile path = takeExtension path `elem` [".hs", ".lhs"]
data Flag
= FlagHaddockPath FilePath
| FlagHelp
deriving Eq
options :: [OptDescr Flag]
options =
[ Option [] ["haddock-path"] (ReqArg FlagHaddockPath "FILE")
"path to Haddock executable to exectue tests with"
, Option ['h'] ["help"] (NoArg FlagHelp)
"display this help end exit"
]
haddockPath :: [Flag] -> FilePath
haddockPath flags = case mlast [ path | FlagHaddockPath path <- flags ] of
Just path -> path
Nothing -> rootDir </> "dist" </> "build" </> "haddock" </> "haddock"
mlast :: [a] -> Maybe a
mlast = listToMaybe . reverse
data ProcessConfig = ProcessConfig
{ pcArgs :: [String]
, pcWorkDir :: Maybe FilePath
, pcEnv :: Maybe [(String, String)]
, pcStdIn :: Maybe Handle
, pcStdOut :: Maybe Handle
, pcStdErr :: Maybe Handle
}
processConfig :: ProcessConfig
processConfig = ProcessConfig
{ pcArgs = []
, pcWorkDir = Nothing
, pcEnv = Nothing
, pcStdIn = Nothing
, pcStdOut = Nothing
, pcStdErr = Nothing
}
runProcess' :: FilePath -> ProcessConfig -> IO ProcessHandle
runProcess' path (ProcessConfig { .. }) = runProcess
path pcArgs pcWorkDir pcEnv pcStdIn pcStdOut pcStdErr
waitForSuccess :: String -> ProcessHandle -> IO ()
waitForSuccess msg handle = do
result <- waitForProcess handle
unless (result == ExitSuccess) $ do
hPutStrLn stderr $ msg
exitFailure
|