@@ -22,7 +22,6 @@ import Distribution.Nixpkgs.Haskell.Constraint
22import Distribution.Nixpkgs.Haskell.FromCabal ( fromGenericPackageDescription )
22import Distribution.Nixpkgs.Haskell.FromCabal ( fromGenericPackageDescription )
23import Distribution.Nixpkgs.Haskell.FromCabal.Configuration
23import Distribution.Nixpkgs.Haskell.FromCabal.Configuration
24import Distribution.Nixpkgs.Haskell.FromCabal.Flags
24import Distribution.Nixpkgs.Haskell.FromCabal.Flags
25−import Distribution.Nixpkgs.Haskell.HackageGit ( readHackage, Hackage )
26import Distribution.Nixpkgs.Haskell.PackageSourceSpec
25import Distribution.Nixpkgs.Haskell.PackageSourceSpec
27import Distribution.Nixpkgs.Meta
26import Distribution.Nixpkgs.Meta
28import Distribution.Nixpkgs.PackageMap
27import Distribution.Nixpkgs.PackageMap
@@ -31,6 +30,7 @@ import Distribution.PackageDescription hiding ( options, buildDepends, extraLibs
31import Distribution.System
30import Distribution.System
32import Distribution.Text
31import Distribution.Text
33import Distribution.Version
32import Distribution.Version
33+import HackageGit ( readHackage, Hackage )
34import Language.Nix
34import Language.Nix
35import Options.Applicative
35import Options.Applicative
36import Paths_hackage2nix
36import Paths_hackage2nix
@@ -199,3 +199,327 @@ parsePreferredVersionsLine :: String -> Maybe Constraint
199parsePreferredVersionsLine [] = Nothing
199parsePreferredVersionsLine [] = Nothing
200parsePreferredVersionsLine ('-':'-':_) = Nothing
200parsePreferredVersionsLine ('-':'-':_) = Nothing
201parsePreferredVersionsLine l = simpleParse l `mplus` error ("invalid preferred-versions line: " ++ show l)
201parsePreferredVersionsLine l = simpleParse l `mplus` error ("invalid preferred-versions line: " ++ show l)
205+-- {-# LANGUAGE OverloadedStrings #-}
206+-- {-# LANGUAGE RecordWildCards #-}
208+-- module Main ( main ) where
210+-- import Control.Lens
211+-- -- import Control.Exception
212+-- import Control.Monad
213+-- import Control.Monad.Par.Combinator
214+-- import Control.Monad.Par.IO as ParIO
215+-- import Control.Monad.Par as Par
216+-- -- import Control.Monad.Trans ( liftIO )
217+-- -- import Data.List
218+-- import Data.Map.Strict ( Map )
219+-- import qualified Data.Map.Strict as Map
221+-- import Data.Monoid
222+-- import Data.Set ( Set )
223+-- import qualified Data.Set as Set
224+-- import Data.String
225+-- import Distribution.Compiler
226+-- import Distribution.Nixpkgs.Fetch
227+-- import Distribution.Nixpkgs.Haskell
228+-- -- import Distribution.Nixpkgs.Haskell.Constraint
229+-- import Distribution.Nixpkgs.Haskell.FromCabal ( fromGenericPackageDescription )
230+-- -- import Distribution.Nixpkgs.Haskell.FromCabal.Configuration
231+-- -- import Distribution.Nixpkgs.Haskell.FromCabal.Flags
232+-- import Distribution.Nixpkgs.Haskell.HackageGit ( readHackage, Hackage )
233+-- -- import Distribution.Nixpkgs.Haskell.PackageSourceSpec
234+-- -- import Distribution.Nixpkgs.Meta
235+-- import Distribution.Nixpkgs.PackageMap
236+-- import Distribution.Package
237+-- import Distribution.PackageDescription hiding ( options, buildDepends, extraLibs, buildTools )
238+-- import Distribution.System
239+-- import Distribution.Text
240+-- import Distribution.Version
241+-- import Language.Nix
242+-- import Options.Applicative
243+-- import qualified Paths_hackage2nix as Main
244+-- import System.FilePath
245+-- import Text.PrettyPrint.HughesPJClass hiding ( (<>) )
249+-- -- type Nixpkgs = PackageMap -- Map String (Set [String])
250+-- -- type PackageSet = Map PackageName Version
251+-- -- type PackageMultiSet = Map String (Set Version)
253+-- -- resolveConstraint :: Constraint -> Hackage -> Version
254+-- -- resolveConstraint c = fromMaybe (error msg) . resolveConstraint' c
255+-- -- where msg = "constraint " ++ display c ++ " cannot be resolved in Hackage"
257+-- -- resolveConstraint' :: Constraint -> Hackage -> Maybe Version
258+-- -- resolveConstraint' (Dependency (PackageName name) vrange) hackage
259+-- -- | Just vset' <- Map.lookup name hackage
260+-- -- , vset <- Set.filter (`withinRange` vrange) (Map.keysSet vset')
261+-- -- , not (Set.null vset) = Just (Set.findMax vset)
262+-- -- | otherwise = Nothing
264+-- data Options = Options
265+-- { hackageRepository :: FilePath
266+-- , preferredVersionsFile :: Maybe FilePath
267+-- , nixpkgsRepository :: FilePath
268+-- , ltsHaskellRepository :: FilePath
269+-- , stackageNightlyRepository :: FilePath
270+-- , configFile :: FilePath
271+-- , targetPlatform :: Platform
275+-- options :: Parser Options
277+-- <$> strOption (long "hackage" <> help "path to Hackage git repository" <> value "hackage" <> showDefaultWith id <> metavar "PATH")
278+-- <*> optional (strOption (long "preferred-versions" <> help "path to Hackage preferred-versions file" <> value "hackage/preferred-versions" <> showDefault <> metavar "PATH"))
279+-- <*> strOption (long "nixpkgs" <> help "path to Nixpkgs repository" <> value "/home/simons/src/cabal2nix/hackage2nix/nixpkgs" <> showDefaultWith id <> metavar "PATH")
280+-- <*> strOption (long "lts-haskell" <> help "path to LTS Haskell repository" <> value "lts-haskell" <> showDefaultWith id <> metavar "PATH")
281+-- <*> strOption (long "stackage-nightly" <> help "path to Stackage Nightly repository" <> value "stackage-nightly" <> showDefaultWith id <> metavar "PATH")
282+-- <*> strOption (long "config" <> help "path to configuration file" <> value "nixpkgs/pkgs/development/haskell-modules/configuration-hackage2nix.yaml" <> showDefaultWith id <> metavar "PATH")
283+-- <*> option (fmap fromString str) (long "platform" <> help "target platform to generate package set for" <> value "x86_64-linux" <> showDefaultWith display <> metavar "PLATFORM")
285+-- pinfo :: ParserInfo Options
288+-- <*> infoOption ("hackage2nix " ++ display Main.version) (long "version" <> help "Show version number")
292+-- <> header "hackage2nix converts a Hackage database into a hackage-packages.nix file."
297+-- Options {..} <- execParser pinfo
299+-- -- defaultConfiguration <- readConfiguration configFile
300+-- nixpkgs <- readNixpkgPackageMap "/home/simons/src/cabal2nix/hackage2nix/nixpkgs" Nothing
301+-- -- preferredVersions <- readPreferredVersions (fromMaybe (hackageRepository </> "preferred-versions") preferredVersionsFile)
302+-- let fixup = Map.delete "acme-everything" -- TODO: https://github.com/NixOS/cabal2nix/issues/164
303+-- . Map.delete "som" -- TODO: https://github.com/NixOS/cabal2nix/issues/164
304+-- . Map.delete "type" -- TODO: https://github.com/NixOS/cabal2nix/issues/163
305+-- . Map.delete "dictionary-sharing" -- TODO: https://github.com/NixOS/cabal2nix/issues/175
306+-- -- . Map.filter (/= Map.empty)
307+-- -- . Map.mapWithKey (enforcePreferredVersions preferredVersions)
308+-- hackage <- fixup <$> readHackage hackageRepository
309+-- snapshots <- ParIO.runParIO (readStackage ltsHaskellRepository)
312+-- allStackagePackages :: Map PackageName (Set Spec)
313+-- allStackagePackages = Map.unionsWith Set.union (map (Map.map Set.singleton . packages) snapshots)
315+-- notInStackage :: String -> Map Version GenericPackageDescription -> Bool
316+-- notInStackage n _ = isNothing (Map.lookup (PackageName n) allStackagePackages)
318+-- nonStackagePackages :: Map String Version
319+-- nonStackagePackages = Map.map (Set.findMax . Map.keysSet) (Map.filterWithKey notInStackage hackage)
321+-- allPackages :: Map PackageName (Set Spec)
322+-- allPackages = Map.union allStackagePackages
323+-- (Map.fromList [ (PackageName n, Set.singleton (Spec v Map.empty True True True)) | (n,v) <- Map.toList nonStackagePackages ])
325+-- hackagePackagesFile :: FilePath
326+-- hackagePackagesFile = nixpkgsRepository </> "pkgs/development/haskell-modules/hackage-packages.nix"
328+-- drvs :: Map PackageIdentifier Derivation
329+-- drvs = Map.unions (runPar (parMap (uncurry (formatPackages hackage nixpkgs targetPlatform)) (Map.toList allPackages)))
331+-- withFile hackagePackagesFile WriteMode $ \h -> do
332+-- hPutStrLn h "{ stdenv }:\n\nself: {"
333+-- forM_ (Map.toList drvs) $ \(pkgId, drv) -> do
334+-- hPutStrLn h $ render $ nest 2 $ hang (doubleQuotes (text (mangle pkgId)) <+> equals) 2 (pPrint drv <> semi)
338+-- mapM_ (formatSnapshot drvs nixpkgsRepository) snapshots
340+-- mangle :: PackageIdentifier -> String
341+-- mangle (PackageIdentifier (PackageName n) v) = n ++ '_' : [ if c == '.' then '_' else c | c <- display v ]
343+-- formatSnapshot :: Map PackageIdentifier Derivation -> FilePath -> Snapshot -> IO ()
344+-- formatSnapshot drvs nixpkgsRepository (Snapshot {..}) = do
346+-- snapshotId :: String
347+-- snapshotId = show (pPrint snapshot)
349+-- compilerId :: String
350+-- compilerId = filter (`notElem` ['.','-']) (display compiler)
352+-- ltsConfigFile :: FilePath
353+-- ltsConfigFile = nixpkgsRepository </> "pkgs/development/haskell-modules/configuration-" ++ snapshotId ++ ".nix"
355+-- withFile ltsConfigFile WriteMode $ \h -> do
356+-- hPutStrLn h "{ pkgs }:"
358+-- hPutStrLn h "self: super: {"
359+-- hPutStrLn h " # our compiler"
360+-- hPutStrLn h (" ghc = pkgs.haskell.compiler." ++ compilerId ++ ";")
362+-- hPutStrLn h " # core packaged provided by the compiler"
363+-- forM_ (Set.toAscList (Map.keysSet corePackages)) $ \(PackageName n) ->
364+-- unless (n == "ghc") (hPutStrLn h (" " ++ n ++ " = null;"))
366+-- hPutStrLn h " # Stackage"
367+-- forM_ (Map.toAscList packages) $ \(PackageName n, spec) -> do
368+-- let pkgId = PackageIdentifier (PackageName n) (version spec)
369+-- drv = drvs Map.! pkgId
370+-- hPutStrLn h (" \"" ++ n ++ "\" = self.callPackage self.\"" ++ mangle pkgId ++ "\" " ++ render (braces (overrides drv) <> semi))
374+-- formatPackages :: Hackage -> Map Identifier (Set Path) -> Platform -> PackageName -> Set Spec -> Map PackageIdentifier Derivation
375+-- formatPackages hackage nixpkgs targetPlatform pname specs = Map.fromList
376+-- [ (PackageIdentifier pname (version spec), formatPackage hackage nixpkgs targetPlatform pname spec) | spec <- Set.toList specs ]
378+-- formatPackage :: Hackage -> Map Identifier (Set Path) -> Platform -> PackageName -> Spec -> Derivation
379+-- formatPackage hackage nixpkgs targetPlatform pname spec =
381+-- pkgId :: PackageIdentifier
382+-- pkgId = PackageIdentifier pname (version spec)
384+-- abort :: String -> a
385+-- abort msg = error (display pkgId ++ ": " ++ msg)
387+-- nixpkgsResolver :: Identifier -> Maybe Binding
388+-- nixpkgsResolver = resolve (Map.map (Set.map (over path ("pkgs":))) nixpkgs)
390+-- pkgDescr :: GenericPackageDescription
391+-- pkgDescr | Just x <- Map.lookup (unPackageName pname) hackage >>= Map.lookup (version spec) = x
392+-- | otherwise = abort "not on hackage"
395+-- sha256 | Just x <- lookup "X-Package-SHA256" (customFieldsPD (packageDescription pkgDescr)) = x
396+-- | otherwise = abort "cannot find hash"
399+-- drv = fromGenericPackageDescription
403+-- (unknownCompilerInfo (CompilerId GHC (Version [7,10] [])) NoAbiTag)
404+-- (Map.toList (flagOverrides spec))
407+-- & src .~ DerivationSource "url" ("mirror://hackage/" ++ display pkgId ++ ".tar.gz") "" sha256
408+-- & doCheck .~ runTests spec
409+-- & Distribution.Nixpkgs.Haskell.runHaddock .~ Stackage.runHaddock spec
414+-- -- generatePackageSet :: Platform -> Configuration -> Hackage -> Nixpkgs -> ParIO ()
415+-- -- generatePackageSet targetPlatform config hackage nixpkgs = do
417+-- -- corePackageSet :: PackageSet
418+-- -- corePackageSet = Map.fromList [ (name, v) | PackageIdentifier (PackageName name) v <- Set.toList (corePackages config) ]
420+-- -- latestVersionSet :: PackageSet
421+-- -- latestVersionSet = Map.map (Set.findMax . Map.keysSet) hackage
423+-- -- defaultPackageOverridesSet :: PackageSet
424+-- -- defaultPackageOverridesSet = Map.fromList [ (name, resolveConstraint c hackage) | c@(Dependency (PackageName name) _) <- defaultPackageOverrides config ]
426+-- -- generatedDefaultPackageSet :: PackageSet
427+-- -- generatedDefaultPackageSet = (defaultPackageOverridesSet `Map.union` latestVersionSet) `Map.difference` corePackageSet
429+-- -- latestCorePackageSet :: PackageSet
430+-- -- latestCorePackageSet = latestVersionSet `Map.intersection` corePackageSet
432+-- -- latestOverridePackageSet :: PackageSet
433+-- -- latestOverridePackageSet = latestVersionSet `Map.intersection` defaultPackageOverridesSet
435+-- -- extraPackageSet :: PackageMultiSet
436+-- -- extraPackageSet = Map.unionsWith Set.union
437+-- -- [ Map.singleton name (Set.singleton (resolveConstraint c hackage)) | c@(Dependency (PackageName name) _) <- extraPackages config ]
439+-- -- db :: PackageMultiSet
440+-- -- db = Map.unionsWith Set.union [ Map.map Set.singleton generatedDefaultPackageSet
441+-- -- , Map.map Set.singleton latestCorePackageSet
442+-- -- , Map.map Set.singleton latestOverridePackageSet
443+-- -- , extraPackageSet
446+-- -- haskellResolver :: Dependency -> Bool
447+-- -- haskellResolver (Dependency (PackageName name) vrange)
448+-- -- | Just v <- Map.lookup name corePackageSet = v `withinRange` vrange
449+-- -- | Just v <- Map.lookup name generatedDefaultPackageSet = v `withinRange` vrange
450+-- -- | otherwise = False
452+-- -- nixpkgsResolver :: Identifier -> Maybe Binding
453+-- -- nixpkgsResolver = resolve (Map.map (Set.map (over path ("pkgs":))) nixpkgs)
455+-- -- globalPackageMaintainers :: Map PackageName (Set Identifier)
456+-- -- globalPackageMaintainers = Map.unionsWith Set.union [ Map.singleton p (Set.singleton m) | (m,ps) <- Map.toList (packageMaintainers config), p <- Set.toList ps ]
458+-- -- liftIO $ do putStrLn "/* hackage-packages.nix is an auto-generated file -- DO NOT EDIT! */"
460+-- -- putStrLn "{ pkgs, stdenv, callPackage }:"
462+-- -- putStrLn "self: {"
464+-- -- pkgs <- flip parMapM (Map.toAscList db) $ \(name, vs) -> do
465+-- -- defs <- forM (Set.toAscList vs) $ \pkgversion -> do
466+-- -- let -- TODO: Include list of broken dependencies in the generated output.
467+-- -- descr = hackage Map.! name Map.! pkgversion
469+-- -- flagAssignment :: FlagAssignment
470+-- -- flagAssignment = configureCabalFlags (packageId descr)
472+-- -- drv' :: Derivation
473+-- -- drv' = fromGenericPackageDescription haskellResolver nixpkgsResolver targetPlatform (compilerInfo config) flagAssignment [] descr
475+-- -- isInDefaultPackageSet :: Bool
476+-- -- isInDefaultPackageSet = maybe False (== pkgversion) (Map.lookup name generatedDefaultPackageSet)
479+-- -- attr = name ++ if isInDefaultPackageSet then [] else '_' : [ if c == '.' then '_' else c | c <- display pkgversion ]
481+-- -- sha256 :: String
482+-- -- sha256 | Just x <- lookup "X-Package-SHA256" (customFieldsPD (packageDescription descr)) = x
483+-- -- | otherwise = error $ display (packageId descr) ++ " has no hash"
485+-- -- srcSpec <- liftIO $ sourceFromHackage (Certain sha256) (name ++ "-" ++ display pkgversion)
487+-- -- let drv = drv' & src .~ srcSpec
488+-- -- & metaSection.hydraPlatforms %~ (`Set.difference` fromMaybe Set.empty (Map.lookup (PackageName name) (dontDistributePackages config)))
489+-- -- & metaSection.hydraPlatforms %~ (if isInDefaultPackageSet then id else const Set.empty)
490+-- -- & metaSection.maintainers .~ fromMaybe Set.empty (Map.lookup (PackageName name) globalPackageMaintainers)
492+-- -- isFromHackage :: Binding -> Bool
493+-- -- isFromHackage b = case view (reference . path) b of
494+-- -- ["self",_] -> True
497+-- -- overrides :: Doc
498+-- -- overrides = fcat $ punctuate space
499+-- -- [ pPrint b | b <- Set.toList (view (dependencies . each) drv), not (isFromHackage b) ]
501+-- -- return $ nest 2 $ hang (doubleQuotes (text attr) <+> equals <+> text "callPackage") 2 (parens (pPrint drv)) <+> (braces overrides <> semi)
502+-- -- return (intercalate "\n\n" (map render defs))
504+-- -- liftIO $ mapM_ (\pkg -> putStrLn pkg >> putStrLn "") pkgs
505+-- -- liftIO $ putStrLn "}"
507+-- -- readPreferredVersions :: FilePath -> IO [Constraint]
508+-- -- readPreferredVersions p = mapMaybe parsePreferredVersionsLine . lines <$> readFile p
510+-- -- parsePreferredVersionsLine :: String -> Maybe Constraint
511+-- -- parsePreferredVersionsLine [] = Nothing
512+-- -- parsePreferredVersionsLine ('-':'-':_) = Nothing
513+-- -- parsePreferredVersionsLine l = simpleParse l `mplus` error ("invalid preferred-versions line: " ++ show l)
515+-- -- enforcePreferredVersions :: [Constraint] -> String -> Map Version GenericPackageDescription
516+-- -- -> Map Version GenericPackageDescription
517+-- -- enforcePreferredVersions cs pkg = Map.filterWithKey (\v _ -> PackageIdentifier (PackageName pkg) v `satisfiesConstraints` cs)
519+-- overrides :: Derivation -> Doc
520+-- overrides drv = fcat $ punctuate space [ pPrint b | b <- Set.toList (view (dependencies . each) drv), not (isFromHackage b) ]
522+-- isFromHackage :: Binding -> Bool
523+-- isFromHackage b = case view (reference . path) b of
524+-- ["self",_] -> True