@@ -39,7 +39,22 @@ main = do
3939
4040generatePackageSet :: Hackage -> PackageMap -> ParIO ()
4141generatePackageSet hackage nixpkgs = do
42− let db = buildPackageSet hackage
42+ let defaultPackageSet = buildDefaultPackageSet hackage defaultPackageOverrides
43+ extendedPackageSet = buildExtendedPackageSet hackage extraPackages
44+ db = defaultPackageSet `mergePackageSet` extendedPackageSet
45+
46+ matches :: PackageIdentifier -> Dependency -> Bool
47+ matches (PackageIdentifier pn v) (Dependency dn vr) = pn == dn && v `withinRange` vr
48+
49+ resolver :: Dependency -> Bool
50+ resolver dep@(Dependency (PackageName pkg) vrange) =
51+ any (`matches` dep) corePackages ||
52+ maybe False (not . Map.null . Map.filterWithKey (\k _ -> k `withinRange` vrange)) (Map.lookup pkg defaultPackageSet)
53+
54+ forM_ (Map.assocs defaultPackageSet) $ \(name, vdb) ->
55+ when (Map.size vdb /= 1) $
56+ fail ("invalid defaut package set: " ++ show (name, Map.keys vdb))
57+
4358 liftIO $ do putStrLn "/* hackage-packages.nix is an auto-generated file -- DO NOT EDIT! */"
4459 putStrLn ""
4560 putStrLn "{ pkgs, stdenv, callPackage }:"
@@ -50,16 +65,16 @@ generatePackageSet hackage nixpkgs = do
5065 let multiVersionPackage :: Bool
5166 multiVersionPackage = Map.size versions > 1
5267
53− latestVersion :: Version
54− latestVersion = fst (Map.findMax versions)
68+ defaultVersion :: Version
69+ defaultVersion = fst $ Map.findMax $ (Map.!) defaultPackageSet name
5570
5671 pkg <- forM (Map.toList versions) $ \(version, descr) -> do
57− (drv, overrides) <- generatePackage db nixpkgs name version descr
72+ (drv, overrides) <- generatePackage db resolver nixpkgs name version descr
5873
5974 let nixAttr = name ++ if multiVersionPackage then "_" ++ [ if c == '.' then '_' else c | c <- display version ] else ""
6075
6176 let def = nest 2 $ hang ((string nixAttr) <+> equals <+> text "callPackage") 2 (parens (disp drv)) <+> (braces overrides <> semi)
62− let overr = if multiVersionPackage && version == latestVersion
77+ let overr = if multiVersionPackage && version == defaultVersion
6378 then nest 2 $ (string name <+> equals <+> text ("self." ++ show nixAttr)) <> semi
6479 else empty
6580
@@ -70,19 +85,11 @@ generatePackageSet hackage nixpkgs = do
7085 liftIO $ mapM_ putStrLn pkgs
7186 liftIO $ putStrLn "}"
7287
73−generatePackage :: Hackage -> PackageMap -> String -> Version -> GenericPackageDescription -> ParIO (Derivation, Doc)
74−generatePackage hackage nixpkgs name version descr = do
88+generatePackage :: Hackage -> (Dependency -> Bool) -> PackageMap -> String -> Version -> GenericPackageDescription -> ParIO (Derivation, Doc)
89+generatePackage hackage resolver nixpkgs name version descr = do
7590 srcSpec <- liftIO $ sourceFromHackage Nothing (name ++ "-" ++ display version)
7691 let Just cabalFileHash = lookup "x-cabal-file-hash" (customFieldsPD (packageDescription descr))
7792
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−
8693 -- TODO: Include list of broken dependencies in the generated output.
8794 (missingDeps,drv') <- case cabal2nix resolver descr of
8895 Left ds -> do let Right x = cabal2nix (const True) descr
@@ -128,10 +135,32 @@ isKnownNixpkgAttribute nixpkgs hackage name
128135 goodScope :: Set [String] -> Bool
129136 goodScope = not . Set.null . Set.intersection (Set.fromList [[], ["xlibs"], ["gnome"]])
130137
131−buildPackageSet :: Hackage -> Hackage
132−buildPackageSet db = Map.unionsWith Map.union $
133− [ selectLatestMatchingPackage (Dependency (PackageName n) anyVersion) db | n <- Map.keys db ] ++
134− [ selectLatestMatchingPackage d db | d <- selectors ]
138+buildDefaultPackageSet :: Hackage -> [Dependency] -> Hackage
139+buildDefaultPackageSet hackage overrides = Map.unions $ -- unions is left-biased, i.e. overrides trump the latest version
140+ [ selectLatestMatchingPackage p hackage | p <- overrides ] ++
141+ [ selectLatestMatchingPackage (Dependency (PackageName n) anyVersion) hackage | n <- Map.keys hackage ]
142+
143+buildExtendedPackageSet :: Hackage -> [Dependency] -> Hackage
144+buildExtendedPackageSet hackage extras = Map.unionsWith Map.union
145+ [ selectLatestMatchingPackage p hackage | p <- extras ]
146+
147+mergePackageSet :: Hackage -> Hackage -> Hackage
148+mergePackageSet = Map.unionWith Map.union
149+
150+-- These packages replace the latest respective version during dependency resolution.
151+defaultPackageOverrides :: [Dependency]
152+defaultPackageOverrides = map (\s -> maybe (error (show s ++ " is not a valid override selector")) id (simpleParse s))
153+ [ "mtl == 2.1.*"
154+ , "monad-control == 0.3.*"
155+ ]
156+
157+-- These packages are added to the generated set, but the play no role during dependency resolution.
158+extraPackages :: [Dependency]
159+extraPackages =
160+ map (\(Dependency name _) -> Dependency name anyVersion) defaultPackageOverrides ++
161+ map (\s -> maybe (error (show s ++ " is not a valid extra package selector")) id (simpleParse s))
162+ [
163+ ]
135164
136165selectLatestMatchingPackage :: Dependency -> Hackage -> Hackage
137166selectLatestMatchingPackage (Dependency (PackageName name) vrange) db =
@@ -140,11 +169,6 @@ selectLatestMatchingPackage (Dependency (PackageName name) vrange) db =
140169 Just vdb -> let (key,val) = Map.findMax (Map.filterWithKey (\k _ -> k `withinRange` vrange) vdb)
141170 in Map.singleton name (Map.singleton key val)
142171
143−selectors :: [Dependency]
144−selectors = map (\s -> maybe (error (show s ++ " is not a valid package selector")) id (simpleParse s))
145− [ "mtl == 2.1.*"
146− , "monad-control == 0.3.*"
147− ]
148172
149173-- data Options = Options
150174-- { verbose :: Bool