@@ -1,4 +1,4 @@
1−-- Run: cabal build -j hackage2nix && dist/build/hackage2nix/hackage2nix >hackage-packages.nix && mv hackage-packages.nix ~/.nix-defexpr/pkgs/development/haskell-modules/hackage-packages.nix && nix-env -qaP | tail -1
1+-- Run: cabal build -j hackage2nix && time dist/build/hackage2nix/hackage2nix >hackage-packages.nix && mv hackage-packages.nix ~/.nix-defexpr/pkgs/development/haskell-modules/hackage-packages.nix && nix-env -qaP | tail -1
3module Main ( main ) where
3module Main ( main ) where
@@ -7,6 +7,7 @@ import Cabal2Nix.Generate ( cabal2nix' )
7import Cabal2Nix.Hackage ( readHashedHackage, Hackage )
7import Cabal2Nix.Hackage ( readHashedHackage, Hackage )
8import Cabal2Nix.Package
8import Cabal2Nix.Package
9import Data.List
9import Data.List
10import Control.Monad
11import Control.Monad
11import Control.Monad.Par.Combinator
12import Control.Monad.Par.Combinator
12import Control.Monad.Par.IO
13import Control.Monad.Par.IO
@@ -19,7 +20,7 @@ import Data.Set ( Set )
19import qualified Data.Set as Set
20import qualified Data.Set as Set
20import Distribution.Compiler
21import Distribution.Compiler
21import Distribution.NixOS.Derivation.Cabal
22import Distribution.NixOS.Derivation.Cabal
22−import Distribution.NixOS.PackageMap ( PackageMap, readNixpkgPackageMap )
23+import Distribution.NixOS.PackageMap
23import Distribution.NixOS.PrettyPrinting hiding ( attr, (<>) )
24import Distribution.NixOS.PrettyPrinting hiding ( attr, (<>) )
24import Distribution.Package
25import Distribution.Package
25import Distribution.PackageDescription hiding ( buildDepends, extraLibs, buildTools )
26import Distribution.PackageDescription hiding ( buildDepends, extraLibs, buildTools )
@@ -104,26 +105,32 @@ generatePackageSet hackage nixpkgs = do
104 -- TODO: Include list of broken dependencies in the generated output.
105 -- TODO: Include list of broken dependencies in the generated output.
105 descr = hackage Map.! name Map.! version
106 descr = hackage Map.! name Map.! version
106 (_, _, drv') = cabal2nix resolver descr
107 (_, _, drv') = cabal2nix resolver descr
107− drv = drv' { src = srcSpec, editedCabalFile = if revision drv == 0 then "" else cabalFileHash }
108+ drv = drv' { src = srcSpec, editedCabalFile = if revision drv == 0 then "" else cabalFileHash
109+ , metaSection = (metaSection drv') { broken = not (Set.null missing) } -- Missing Haskell dependencies!
109 missing :: Set String
112 missing :: Set String
110− missing = Set.fromList $
111− filter (not . isKnownNixpkgAttribute nixpkgs hackage) (extraLibs drv ++ pkgConfDeps drv ++ buildTools drv) ++
112− filter (flip Set.notMember knownAttributesSet) (buildDepends drv ++ testDepends drv)
113+ missing = Set.fromList $ filter (`Set.notMember` knownAttributesSet) (buildDepends drv ++ testDepends drv)
114− missingOverrides :: Doc
115+ buildInputs :: Map Attribute (Maybe Path)
115− missingOverrides | Set.null missing = empty
116+ buildInputs = Map.unions
116− | otherwise = fcat [ text (' ':dep++" = null;") | dep <- Set.toAscList missing ] <> space
117+ [ Map.fromList [ (n, Nothing) | n <- Set.toList missing ]
118+ , Map.fromList [ (n, resolveNixpkgsAttribute nixpkgs n) | n <- Set.toAscList (Set.fromList (extraLibs drv ++ pkgConfDeps drv)) ]
119+ , Map.fromList [ (n, resolveNixpkgsOrHackageAttribute nixpkgs hackage n) | n <- Set.toAscList (Set.fromList (buildTools drv)) ]
118− conflicts :: Set String
122+ systemOverrides :: Doc
119− conflicts = Set.intersection knownAttributesSet (Set.fromList (extraLibs drv ++ pkgConfDeps drv))
123+ systemOverrides = fsep (map (uncurry formatOverride) (Map.toAscList buildInputs))
121− conflictOverrides :: Doc
125+ formatOverride :: Attribute -> Maybe Path -> Doc
122− conflictOverrides | Set.null conflicts = empty
126+ formatOverride n Nothing = space <> text n <> text " = null;" -- missing attribute
123− | otherwise = text " inherit (pkgs) " <> hsep (map text (Set.toAscList conflicts)) <> text "; "
127+ formatOverride n (Just []) -- Haskell package:
128+ | n == name = formatOverride n Nothing -- refers to a missing system library
129+ | otherwise = empty -- found by callPackage
130+ formatOverride n (Just p) = (text " inherit" <+> parens (text (intercalate "." p)) <+> text n) <> semi
125 overrides :: Doc
132 overrides :: Doc
126− overrides = conflictOverrides $+$ missingOverrides
133+ overrides = systemOverrides
128 attr | Just v <- Map.lookup name generatedDefaultPackageSet, v == version = name
135 attr | Just v <- Map.lookup name generatedDefaultPackageSet, v == version = name
129 | otherwise = name ++ '_' : [ if c == '.' then '_' else c | c <- display version ]
136 | otherwise = name ++ '_' : [ if c == '.' then '_' else c | c <- display version ]
@@ -134,13 +141,23 @@ generatePackageSet hackage nixpkgs = do
134 liftIO $ mapM_ (\pkg -> putStrLn pkg >> putStrLn "") pkgs
141 liftIO $ mapM_ (\pkg -> putStrLn pkg >> putStrLn "") pkgs
135 liftIO $ putStrLn "}"
142 liftIO $ putStrLn "}"
137−isKnownNixpkgAttribute :: Nixpkgs -> Hackage -> String -> Bool
144+resolveNixpkgsOrHackageAttribute :: Nixpkgs -> Hackage -> Attribute -> Maybe Path
138−isKnownNixpkgAttribute nixpkgs hackage name
145+resolveNixpkgsOrHackageAttribute nixpkgs hackage name
139− | Just _ <- Map.lookup name hackage = True
146+ | p@(Just _) <- resolveNixpkgsAttribute nixpkgs name = p
140− | otherwise = maybe False goodScope (Map.lookup name nixpkgs)
147+ | Just _ <- Map.lookup name hackage = Just []
148+ | otherwise = Nothing
150+resolveNixpkgsAttribute :: Nixpkgs -> Attribute -> Maybe Path
151+resolveNixpkgsAttribute nixpkgs name
152+ | Just paths <- Map.lookup name nixpkgs = getShortestPath (Set.toList (paths `Set.intersection` goodScopes))
153+ | otherwise = Nothing
142− goodScope :: Set [String] -> Bool
155+ goodScopes :: Set Path
143− goodScope = not . Set.null . Set.intersection (Set.fromList [[], ["xlibs"], ["gnome"]])
156+ goodScopes = Set.fromList [[], ["xlibs"], ["gnome"], ["gnome3"], ["kde4"]]
158+ getShortestPath :: [Path] -> Maybe Path
159+ getShortestPath [] = Nothing
160+ getShortestPath ps = Just ("pkgs" : minimumBy (on compare length) ps)
145-- These packages replace the latest respective version during dependency resolution.
162-- These packages replace the latest respective version during dependency resolution.
146defaultPackageOverrides :: [Constraint]
163defaultPackageOverrides :: [Constraint]