git.iko.soy/typeable/cabal2nix
on master help sign in
Use 'finalizePackageDescription' to detect packages that are broken because of missing dependencies.
5db389aPeter Simons
src/Cabal2Nix/Generate.hs+17−14
@@ -1,4 +1,4 @@
1−module Cabal2Nix.Generate ( cabal2nix ) where
1+module Cabal2Nix.Generate ( cabal2nix, cabal2nix' ) where
2
2
3import Cabal2Nix.Flags
3import Cabal2Nix.Flags
4import Cabal2Nix.License
4import Cabal2Nix.License
@@ -13,7 +13,17 @@ import Distribution.PackageDescription.Configuration
13import Distribution.System
13import Distribution.System
14
14
15cabal2nix :: Cabal.GenericPackageDescription -> Derivation
15cabal2nix :: Cabal.GenericPackageDescription -> Derivation
16+cabal2nix cabal = cabal2nix' descr
17+ where Right (descr, _) = finalizePackageDescription
18+ (configureCabalFlags (Cabal.package (Cabal.packageDescription cabal)))
19+ (const True)
20+ (Platform X86_64 Linux) -- shouldn't be hardcoded
21+ (CompilerId GHC (Version [7,8,4] [])) -- dito
22+ []
23+ cabal
24+
25+cabal2nix' :: Cabal.PackageDescription -> Derivation
16−cabal2nix cabal = normalize $ postProcess MkDerivation
26+cabal2nix' tpkg = normalize $ postProcess MkDerivation
17 { pname = let Cabal.PackageName x = Cabal.pkgName pkg in x
27 { pname = let Cabal.PackageName x = Cabal.pkgName pkg in x
18 , version = Cabal.pkgVersion pkg
28 , version = Cabal.pkgVersion pkg
19 , revision = maybe 0 read (lookup "x-revision" xfields)
29 , revision = maybe 0 read (lookup "x-revision" xfields)
@@ -37,9 +47,9 @@ cabal2nix cabal = normalize $ postProcess MkDerivation
37 , phaseOverrides = ""
47 , phaseOverrides = ""
38 , editedCabalFile= if isJust (lookup "x-revision" xfields) then fromJust (lookup "x-cabal-file-hash" xfields) else ""
48 , editedCabalFile= if isJust (lookup "x-revision" xfields) then fromJust (lookup "x-cabal-file-hash" xfields) else ""
39 , metaSection = Meta
49 , metaSection = Meta
40− { homepage = Cabal.homepage descr
50+ { homepage = Cabal.homepage tpkg
41− , description = Cabal.synopsis descr
51+ , description = Cabal.synopsis tpkg
42− , license = fromCabalLicense (Cabal.license descr)
52+ , license = fromCabalLicense (Cabal.license tpkg)
43 , platforms = []
53 , platforms = []
44 , hydraPlatforms = []
54 , hydraPlatforms = []
45 , maintainers = []
55 , maintainers = []
@@ -47,9 +57,8 @@ cabal2nix cabal = normalize $ postProcess MkDerivation
47 }
57 }
48 }
58 }
49 where
59 where
50− descr = Cabal.packageDescription cabal
51− xfields = Cabal.customFieldsPD descr
60+ xfields = Cabal.customFieldsPD tpkg
52− pkg = Cabal.package descr
61+ pkg = Cabal.package tpkg
53 deps = Cabal.buildDepends tpkg
62 deps = Cabal.buildDepends tpkg
54 tests = map Cabal.testBuildInfo (Cabal.testSuites tpkg)
63 tests = map Cabal.testBuildInfo (Cabal.testSuites tpkg)
55 libDeps = map Cabal.libBuildInfo (maybeToList (Cabal.library tpkg))
64 libDeps = map Cabal.libBuildInfo (maybeToList (Cabal.library tpkg))
@@ -59,12 +68,6 @@ cabal2nix cabal = normalize $ postProcess MkDerivation
59 tools = concatMap Cabal.buildTools (libDeps ++ exeDeps)
68 tools = concatMap Cabal.buildTools (libDeps ++ exeDeps)
60 libs = concatMap Cabal.extraLibs (libDeps ++ exeDeps)
69 libs = concatMap Cabal.extraLibs (libDeps ++ exeDeps)
61 pcs = map unDep (concatMap Cabal.pkgconfigDepends (libDeps ++ exeDeps))
70 pcs = map unDep (concatMap Cabal.pkgconfigDepends (libDeps ++ exeDeps))
62− Right (tpkg, _) = finalizePackageDescription
63− (configureCabalFlags pkg)
64− (const True)
65− (Platform X86_64 Linux) -- shouldn't be hardcoded
66− (CompilerId GHC (Version [7,8,3] [])) -- dito
67− [] cabal
68
71
69unDep :: Cabal.Dependency -> String
72unDep :: Cabal.Dependency -> String
70unDep (Cabal.Dependency (Cabal.PackageName x) _) = x
73unDep (Cabal.Dependency (Cabal.PackageName x) _) = x
src/hackage2nix.hs+71−6
@@ -2,10 +2,11 @@
2
2
3module Main ( main ) where
3module Main ( main ) where
4
4
5−import Cabal2Nix.Generate
5+import Cabal2Nix.Generate ( cabal2nix' )
6import Cabal2Nix.Hackage ( readHashedHackage, Hackage )
6import Cabal2Nix.Hackage ( readHashedHackage, Hackage )
7-- import Cabal2Nix.Name
7-- import Cabal2Nix.Name
8import Cabal2Nix.Package
8import Cabal2Nix.Package
9+import Cabal2Nix.Flags ( configureCabalFlags )
9import Control.Monad
10import Control.Monad
10import Control.Monad.Par.Combinator
11import Control.Monad.Par.Combinator
11import Control.Monad.Par.IO
12import Control.Monad.Par.IO
@@ -26,6 +27,9 @@ import Distribution.PackageDescription hiding ( buildDepends, extraLibs, buildTo
26import Distribution.Text
27import Distribution.Text
27import Distribution.Version
28import Distribution.Version
28-- import Options.Applicative hiding ( empty )
29-- import Options.Applicative hiding ( empty )
30+import Distribution.PackageDescription.Configuration
31+import Distribution.System
32+import Distribution.Compiler
29
33
30main :: IO ()
34main :: IO ()
31main = do
35main = do
@@ -71,6 +75,24 @@ generatePackage hackage nixpkgs name version descr = do
71 srcSpec <- liftIO $ sourceFromHackage Nothing (name ++ "-" ++ display version)
75 srcSpec <- liftIO $ sourceFromHackage Nothing (name ++ "-" ++ display version)
72 let Just cabalFileHash = lookup "x-cabal-file-hash" (customFieldsPD (packageDescription descr))
76 let Just cabalFileHash = lookup "x-cabal-file-hash" (customFieldsPD (packageDescription descr))
73
77
78+ matches :: PackageIdentifier -> Dependency -> Bool
79+ matches (PackageIdentifier pn v) (Dependency dn vr) = pn == dn && v `withinRange` vr
80+
81+ resolver :: Dependency -> Bool
82+ resolver dep@(Dependency (PackageName pkg) vrange) =
83+ any (`matches` dep) corePackages ||
84+ maybe False (not . Map.null . Map.filterWithKey (\k _ -> k `withinRange` vrange)) (Map.lookup pkg hackage)
85+
86+ -- TODO: Include list of broken dependencies in the generated output.
87+ (missingDeps,drv') <- case cabal2nix resolver descr of
88+ Left ds -> do let Right x = cabal2nix (const True) descr
89+ return (ds,x)
90+ Right x -> return ([],x)
91+
92+ let drv = drv' { src = srcSpec
93+ , editedCabalFile = if revision drv == 0 then "" else cabalFileHash
94+ }
95+
74 selectHackageNames :: Set String -> Set String
96 selectHackageNames :: Set String -> Set String
75 selectHackageNames = Set.intersection (Map.keysSet hackage)
97 selectHackageNames = Set.intersection (Map.keysSet hackage)
76
98
@@ -95,11 +117,7 @@ generatePackage hackage nixpkgs name version descr = do
95 overrides :: Doc
117 overrides :: Doc
96 overrides = conflictOverrides $+$ missingOverrides
118 overrides = conflictOverrides $+$ missingOverrides
97
119
98− drv = (cabal2nix descr) { src = srcSpec
99− , editedCabalFile = if revision drv == 0 then "" else cabalFileHash
100− }
101−
102− return $ (drv { metaSection = (metaSection drv) { broken = not (Set.null missing) } }, overrides)
120+ return $ (drv { metaSection = (metaSection drv) { broken = not (Set.null missing) || not (null missingDeps) } }, overrides)
103
121
104isKnownNixpkgAttribute :: PackageMap -> Hackage -> String -> Bool
122isKnownNixpkgAttribute :: PackageMap -> Hackage -> String -> Bool
105isKnownNixpkgAttribute nixpkgs hackage name
123isKnownNixpkgAttribute nixpkgs hackage name
@@ -170,3 +188,50 @@ selectors = map (\s -> maybe (error (show s ++ " is not a valid package selector
170-- ( fullDesc
188-- ( fullDesc
171-- <> header "hackage2nix -- convert the Hackage database into Nix build instructions"
189-- <> header "hackage2nix -- convert the Hackage database into Nix build instructions"
172-- )
190-- )
191+
192+cabal2nix :: (Dependency -> Bool) -> GenericPackageDescription -> Either [Dependency] Derivation
193+cabal2nix resolver cabal = case finalize of
194+ Left ds -> Left ds
195+ Right (descr, flags) -> Right (cabal2nix' descr) { configureFlags = [ "-f" ++ (if b then "" else "-") ++ n | (FlagName n, b) <- flags ] }
196+ where
197+ finalize :: Either [Dependency] (PackageDescription, FlagAssignment)
198+ finalize = finalizePackageDescription
199+ (configureCabalFlags (package (packageDescription cabal)))
200+ resolver
201+ (Platform X86_64 Linux) -- shouldn't be hardcoded
202+ (CompilerId GHC (Version [7,8,4] [])) -- dito
203+ []
204+ cabal
205+
206+corePackages :: [PackageIdentifier]
207+corePackages = map (\s -> maybe (error (show s ++ " is not a valid core package")) id (simpleParse s))
208+ [ "Cabal-1.18.1.5"
209+ , "array-0.5.0.0"
210+ , "base-4.7.0.2"
211+ , "bin-package-db-0.0.0.0"
212+ , "binary-0.7.1.0"
213+ , "bytestring-0.10.4.0"
214+ , "containers-0.5.5.1"
215+ , "deepseq-1.3.0.2"
216+ , "directory-1.2.1.0"
217+ , "filepath-1.3.0.2"
218+ , "ghc-7.8.4"
219+ , "ghc-prim-0.3.1.0"
220+ , "haskeline-0.7.1.2"
221+ , "haskell2010-1.1.2.0"
222+ , "haskell98-2.0.0.3"
223+ , "hoopl-3.10.0.1"
224+ , "hpc-0.6.0.1"
225+ , "integer-gmp-0.5.1.0"
226+ , "old-locale-1.0.0.6"
227+ , "old-time-1.1.0.2"
228+ , "pretty-1.1.1.1"
229+ , "process-1.2.0.0"
230+ , "rts-1.0"
231+ , "template-haskell-2.9.0.0"
232+ , "terminfo-0.4.0.0"
233+ , "time-1.4.2"
234+ , "transformers-0.3.0.0"
235+ , "unix-2.7.0.1"
236+ , "xhtml-3000.2.1"
237+ ]