git.iko.soy/typeable/cabal2nix
on 1663fb8 help sign in
typeable/cabal2nix/src/cabal2nix.hs
126 lines 6.3 kB history raw
1module Main ( main ) where
3import Cabal2Nix.Generate ( cabal2nix )
4import Cabal2Nix.Normalize ( normalize )
5import Cabal2Nix.Package
6import Cabal2Nix.Version
7import Control.Exception ( bracket )
8import Data.Maybe ( fromMaybe )
9import qualified Data.Set as Set
10import Distribution.Nixpkgs.Fetch
11import Distribution.Nixpkgs.Haskell hiding ( version )
12import Distribution.Nixpkgs.Util.PrettyPrinting hiding ( (<>) )
13import Distribution.PackageDescription ( FlagName(..), FlagAssignment )
14import Distribution.Simple.Utils ( lowercase )
15import Options.Applicative
16import System.IO ( hFlush, stdout, stderr )
17import qualified Text.PrettyPrint.ANSI.Leijen as P2 hiding ( (<$>), (<>) )
19data Options = Options
20 { optSha256 :: Maybe String
21 , optMaintainer :: [String]
22 , optPlatform :: [String]
23 , optHaddock :: Bool
24 , optDoCheck :: Bool
25 , optJailbreak :: Bool
26 , optRevision :: Maybe String
27 , optHyperlinkSource :: Bool
28 , optHackageDb :: Maybe FilePath
29 , optNixShellOutput :: Bool
30 , optFlags :: [String]
31 , optUrl :: String
32 }
33 deriving (Show)
35options :: Parser Options
36options = Options
37 <$> optional (strOption $ long "sha256" <> metavar "HASH" <> help "sha256 hash of source tarball")
38 <*> many (strOption $ long "maintainer" <> metavar "MAINTAINER" <> help "maintainer of this package (may be specified multiple times)")
39 <*> many (strOption $ long "platform" <> metavar "PLATFORM" <> help "supported build platforms (may be specified multiple times)")
40 <*> flag True False (long "no-haddock" <> help "don't run Haddock when building this package")
41 <*> flag True False (long "no-check" <> help "don't run regression test suites of this package")
42 <*> switch (long "jailbreak" <> help "disregard version restrictions on build inputs")
43 <*> optional (strOption $ long "revision" <> help "revision to use when fetching from VCS")
44 <*> flag True False (long "no-hyperlink-source" <> help "don't generate pretty-printed source code for the documentation")
45 <*> optional (strOption $ long "hackage-db" <> metavar "PATH" <> help "path to the local hackage db in tar format")
46 <*> switch (long "shell" <> help "generate output suitable for nix-shell")
47 <*> many (strOption $ short 'f' <> long "flag" <> help "Cabal flag (may be specified multiple times)")
48 <*> strArgument (metavar "URI")
50pinfo :: ParserInfo Options
51pinfo = info
52 ( helper
53 <*> infoOption ("cabal2nix " ++ version) (long "version" <> help "Show version number")
54 <*> options
55 )
56 ( fullDesc
57 <> header "cabal2nix converts Cabal files into build instructions for Nix."
58 <> progDescDoc (Just (P2.vcat
59 [ P2.text ""
60 , P2.text "Recognized URI schemes:"
61 , P2.text ""
62 , P2.text " cabal://pkgname-pkgversion download the specified package from Hackage"
63 , P2.text " cabal://pkgname download latest version of this package from Hackage"
64 , P2.text " file:///local/path load the Cabal file from the local disk"
65 , P2.text " /local/path abbreviated version of file URI"
66 , P2.text " <git/svn/bzr/hg URL> download the source from the specified repository"
67 , P2.text ""
68 , P2.fillSep (map P2.text (words ( "If the URI refers to a cabal file, information for building the package "
69 ++ "will be retrieved from that file, but hackage will be used as a source "
70 ++ "for the derivation. Otherwise, the supplied URI will be used to as the "
71 ++ "souce for the derivation and the information is taken from the cabal file "
72 ++ "at the root of the downloaded source."
73 )))
74 ]))
75 )
77main :: IO ()
78main = bracket (return ()) (\() -> hFlush stdout >> hFlush stderr) $ \() -> do
79 cfg <- execParser pinfo
81 pkg <- getPackage (optHackageDb cfg) $ Source (optUrl cfg) (fromMaybe "" (optRevision cfg)) (optSha256 cfg)
83 let flags = readFlagList (optFlags cfg)
85 deriv = (cabal2nix flags $ pkgCabal pkg) { src = pkgSource pkg
86 , runHaddock = optHaddock cfg
87 , jailbreak = optJailbreak cfg
88 , hyperlinkSource = optHyperlinkSource cfg
89 }
90 deriv' = deriv { metaSection = (metaSection deriv)
91 { maintainers = Set.fromList (optMaintainer cfg)
92 , platforms = Set.fromList (optPlatform cfg)
93 }
94 , doCheck = doCheck deriv && optDoCheck cfg
95 , extraFunctionArgs = Set.insert "stdenv" (extraFunctionArgs deriv)
96 }
98 deriv'' :: Doc
99 deriv'' = pPrint (normalize deriv')
101 shell :: Doc -> Doc
102 shell expr = vcat
103 [ text "{ nixpkgs ? import <nixpkgs> {}, compiler ? \"ghc7101\" }:"
104 , text ""
105 , text "let"
106 , text ""
107 , text " inherit (nixpkgs) pkgs;"
108 , text ""
109 , hcat [ text " f = ", expr, semi ]
110 , text ""
111 , text " drv = pkgs.haskell.packages.${compiler}.callPackage f {};"
112 , text ""
113 , text "in"
114 , text ""
115 , text " if pkgs.lib.inNixShell then drv.env else drv"
116 ]
118 deriv''' | optNixShellOutput cfg = shell deriv''
119 | otherwise = deriv''
121 print deriv'''
123readFlagList :: [String] -> FlagAssignment
124readFlagList = map tagWithValue
125 where tagWithValue ('-':fname) = (FlagName (lowercase fname), False)
126 tagWithValue fname = (FlagName (lowercase fname), True)