git.iko.soy/typeable/cabal2nix
on master help sign in
Cabal2Nix.hs: simplified the command line parser logic
18fb5f8Peter Simons
src/Cabal2Nix.hs+60−46
@@ -7,63 +7,77 @@ import Distribution.NixOS.Derivation.Meta
7
7
8import Control.Exception ( bracket )
8import Control.Exception ( bracket )
9import Control.Monad ( when )
9import Control.Monad ( when )
10+import Data.List ( nub, sort )
10import Distribution.PackageDescription ( package, packageDescription )
11import Distribution.PackageDescription ( package, packageDescription )
11import Distribution.PackageDescription.Parse ( parsePackageDescription, ParseResult(..) )
12import Distribution.PackageDescription.Parse ( parsePackageDescription, ParseResult(..) )
12import Distribution.Text ( disp )
13import Distribution.Text ( disp )
13import System.Console.GetOpt ( OptDescr(..), ArgDescr(..), ArgOrder(..), usageInfo, getOpt )
14import System.Console.GetOpt ( OptDescr(..), ArgDescr(..), ArgOrder(..), usageInfo, getOpt )
14import System.Environment ( getArgs )
15import System.Environment ( getArgs )
15−import System.Exit ( exitFailure )
16+import System.Exit ( exitFailure, exitSuccess )
16import System.IO ( hPutStrLn, hFlush, stdout, stderr )
17import System.IO ( hPutStrLn, hFlush, stdout, stderr )
17
18
18−data CliOption = PrintHelp | SHA256 String | Maintainer String | Platform String | NoHaddock
19+data Configuration = Configuration
20+ { optPrintHelp :: Bool
21+ , optPrintVersion :: Bool
22+ , optSha256 :: String
23+ , optMaintainer :: [String]
24+ , optPlatform :: [String]
25+ , optHaddock :: Bool
26+ }
19− deriving (Eq)
27+ deriving (Show)
20
28
21−main :: IO ()
29+defaultConfiguration :: Configuration
22−main = bracket (return ()) (\() -> hFlush stdout >> hFlush stderr) $ \() -> do
30+defaultConfiguration = Configuration
31+ { optPrintHelp = False
32+ , optPrintVersion = False
33+ , optSha256 = ""
34+ , optMaintainer = []
35+ , optPlatform = []
36+ , optHaddock = True
37+ }
38+
23− let options :: [OptDescr CliOption]
39+options :: [OptDescr (Configuration -> Configuration)]
24− options =
40+options =
25− [ Option ['h'] ["help"] (NoArg PrintHelp) "show this help text"
41+ [ Option ['h'] ["help"] (NoArg (\o -> o { optPrintHelp = True })) "show this help text"
26− , Option [] ["sha256"] (ReqArg SHA256 "HASH") "sha256 hash of source tarball"
42+ , Option [] ["sha256"] (ReqArg (\x o -> o { optSha256 = x }) "HASH") "sha256 hash of source tarball"
27− , Option ['m'] ["maintainer"] (ReqArg Maintainer "MAINTAINER") "maintainer of this package (may be specified multiple times)"
43+ , Option ['m'] ["maintainer"] (ReqArg (\x o -> o { optMaintainer = x : optMaintainer o }) "MAINTAINER") "maintainer of this package (may be specified multiple times)"
28− , Option ['p'] ["platform"] (ReqArg Platform "PLATFORM") "supported build platforms (may be specified multiple times)"
44+ , Option ['p'] ["platform"] (ReqArg (\x o -> o { optPlatform = x : optPlatform o }) "PLATFORM") "supported build platforms (may be specified multiple times)"
29− , Option [] ["no-haddock"] (NoArg NoHaddock) "don't run Haddock when building this package"
45+ , Option [] ["no-haddock"] (NoArg (\o -> o { optHaddock = False })) "don't run Haddock when building this package"
30− ]
46+ ]
31
47
32− usage :: String
48+usage :: String
33− usage = usageInfo "Usage: cabal2nix [options] url-to-cabal-file" options ++ unlines
49+usage = usageInfo "Usage: cabal2nix [options] url-to-cabal-file" options ++ unlines
34− [ ""
50+ [ ""
35− , "Recognized URI schemes:"
51+ , "Recognized URI schemes:"
36− , ""
52+ , ""
37− , " cabal://pkgname-pkgversion download the specified package from Hackage"
53+ , " cabal://pkgname-pkgversion download the specified package from Hackage"
38− , " http://host/path fetch the Cabel file via HTTP"
54+ , " http://host/path fetch the Cabel file via HTTP"
39− , " file:///local/path load the Cabal file from the local disk"
55+ , " file:///local/path load the Cabal file from the local disk"
40− , " /local/path abbreviated version of file URI"
56+ , " /local/path abbreviated version of file URI"
41− ]
57+ ]
42
58
43− cmdlineError :: String -> IO a
59+cmdlineError :: String -> IO a
44− cmdlineError "" = hPutStrLn stderr usage >> exitFailure
60+cmdlineError "" = hPutStrLn stderr usage >> exitFailure
45− cmdlineError errMsg = hPutStrLn stderr errMsg >> cmdlineError ""
61+cmdlineError errMsg = hPutStrLn stderr errMsg >> cmdlineError ""
46
62
63+main :: IO ()
64+main = bracket (return ()) (\() -> hFlush stdout >> hFlush stderr) $ \() -> do
47 args' <- getArgs
65 args' <- getArgs
48− (opts,args) <- case getOpt Permute options args' of
66+ (cfg',args) <- case getOpt Permute options args' of
49− (o,n,[] ) -> return (o,n)
67+ (o,n,[] ) -> return (foldl (flip ($)) defaultConfiguration o,n)
50− (_,_,errs) -> cmdlineError (concatMap (\e -> '*':'*':'*':' ':e) errs)
68+ (_,_,errs) -> cmdlineError (concatMap ("*** "++) errs)
51−
52− when (PrintHelp `elem` opts) (cmdlineError "")
53
69
54− let uri = args
70+ when (optPrintHelp cfg') (putStr usage >> exitSuccess)
55− hash = [ h | SHA256 h <- opts ]
71+ when (length args /= 1) (cmdlineError "*** exactly one url-to-cabal-file must be specified\n")
56− noHaddock = NoHaddock `elem` opts
57− maints = [ if '.' `elem` m then m else "self.stdenv.lib.maintainers." ++ m | Maintainer m <- opts ]
58− plats' = [ if '.' `elem` p then p else "self.stdenv.lib.platforms." ++ p | Platform p <- opts ]
59− plats
60− | null plats' = if not (null maints) then ["self.ghc.meta.platforms"] else []
61− | otherwise = plats'
62
72
63− when (length uri /= 1) (cmdlineError "*** exactly one URI must be specified")
73+ let maints = [ if '.' `elem` m then m else "self.stdenv.lib.maintainers." ++ m | m <- optMaintainer cfg' ]
64− when (length hash > 1) (cmdlineError "*** the --sha256 option may be specified only once")
74+ plats = [ if '.' `elem` p then p else "self.stdenv.lib.platforms." ++ p | p <- optPlatform cfg' ]
75+ cfg = cfg'
76+ { optMaintainer = nub (sort maints)
77+ , optPlatform = nub (sort (if null plats then ["self.ghc.meta.platforms"] else plats))
78+ }
65
79
66− cabal' <- fmap parsePackageDescription (readCabalFile (head uri))
80+ cabal' <- fmap parsePackageDescription (readCabalFile (head args))
67 cabal <- case cabal' of
81 cabal <- case cabal' of
68 ParseOk _ a -> return a
82 ParseOk _ a -> return a
69 ParseFailed err -> do
83 ParseFailed err -> do
@@ -72,12 +86,12 @@ main = bracket (return ()) (\() -> hFlush stdout >> hFlush stderr) $ \() -> do
72
86
73 let packageId = package (packageDescription cabal)
87 let packageId = package (packageDescription cabal)
74
88
75− sha <- if null hash then hashPackage packageId else return (head hash)
89+ sha <- if null (optSha256 cfg) then hashPackage packageId else return (optSha256 cfg)
76
90
77− let deriv = (cabal2nix cabal) { sha256 = sha, runHaddock = not noHaddock }
91+ let deriv = (cabal2nix cabal) { sha256 = sha, runHaddock = optHaddock cfg }
78 deriv' = deriv { metaSection = (metaSection deriv)
92 deriv' = deriv { metaSection = (metaSection deriv)
79− { maintainers = maints
93+ { maintainers = optMaintainer cfg
80− , platforms = plats
94+ , platforms = optPlatform cfg
81 }
95 }
82 }
96 }
83
97