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
|
--------------------------------------------------------------------------------
module Main
( main
) where
--------------------------------------------------------------------------------
import Control.Arrow (first)
import Control.Monad (forM_)
import Data.Char (isAlphaNum, isNumber)
import Data.List (intercalate)
import Data.Version (Version(..))
import System.Directory (copyFile, canonicalizePath)
import System.Environment (getArgs, getProgName)
import System.Exit (exitFailure)
import System.FilePath ((</>), splitDirectories)
--------------------------------------------------------------------------------
import Hakyll.Core.Util.File
import Paths_hakyll
--------------------------------------------------------------------------------
main :: IO ()
main = do
progName <- getProgName
args <- getArgs
srcDir <- getDataFileName "example"
files <- getRecursiveContents (const $ return False) srcDir
case args of
[dstDir] -> do
forM_ files $ \file -> do
let dst = dstDir </> file
src = srcDir </> file
putStrLn $ "Creating " ++ dst
makeDirectories dst
copyFile src dst
-- canonicalizePath is safe because the destination
-- directory should exist at this point
canonicalizePath dstDir >>= createCabal
_ -> do
putStrLn $ "Usage: " ++ progName ++ " <directory>"
exitFailure
createCabal :: FilePath -> IO ()
createCabal dstDir = do
putStrLn $ "Creating " ++ name ++ ".cabal"
writeFile (dstDir </> name ++ ".cabal") $ unlines [
"name: " ++ name
, "version: 0.1.0.0"
, "build-type: Simple"
, "cabal-version: >= 1.10"
, ""
, "executable site"
, " main-is: site.hs"
, " build-depends: base == 4.*"
, " , hakyll == " ++ version' ++ ".*"
, " ghc-options: -threaded"
, " default-language: Haskell2010"
]
where
-- Major hakyll version
version' = intercalate "." . take 2 . map show $ versionBranch version
-- last is safe here as the path is canonicalised and "/" is just
-- a very rare but possible corner case
name = case last (splitDirectories dstDir) of
"/" -> fallbackName
x -> repair (fallbackName ++) id x
-- Package name repair code comes from
-- cabal-install.Distribution.Client.Init.Heuristics
repair invalid valid x = case dropWhile (not . isAlphaNum) x of
"" -> repairComponent ""
x' -> let (c, r) = first repairComponent $ break (not . isAlphaNum) x'
in c ++ repairRest r
where repairComponent c | all isNumber c = invalid c
| otherwise = valid c
repairRest = repair id ('-' :)
fallbackName = "site"
|