packages feed

cabal2nix 1.12 → 1.13

raw patch · 8 files changed

+116/−202 lines, 8 filesdep +hackage-dbdep ~Cabaldep ~nixos-types

Dependencies added: hackage-db

Dependency ranges changed: Cabal, nixos-types

Files

cabal2nix.cabal view
@@ -1,5 +1,5 @@ Name:                   cabal2nix-Version:                1.12+Version:                1.13 Copyright:              Peter Simons, Andres Loeh License:                BSD3 License-File:           LICENSE@@ -12,7 +12,7 @@ Build-Type:             Simple Tested-With:            GHC == 6.12.3, GHC == 7.0.4, GHC == 7.2.1 Description:-  The cabal2nix utility converts Cabal files into Nix build instructions. The+  The @cabal2nix@ utility converts Cabal files into Nix build instructions. The   commandline syntax is:   .   > Usage: cabal2nix [options] url-to-cabal-file@@ -30,8 +30,8 @@   .   The only required argument is the path to the cabal file. For example:   .-  > cabal2nix http://hackage.haskell.org/packages/archive/cabal2nix/1.9/cabal2nix.cabal-  > cabal2nix cabal://cabal2nix-1.9+  > cabal2nix http://hackage.haskell.org/packages/archive/cabal2nix/1.13/cabal2nix.cabal+  > cabal2nix cabal://cabal2nix-1.13   .   If the @--sha256@ option has not been specified, cabal2nix calls   @nix-prefetch-url@ to determine the hash automatically. This causes@@ -50,31 +50,25 @@   Ghc-Options:          -Wall   other-modules:        Cabal2Nix.CorePackages                         Cabal2Nix.Flags+                        Cabal2Nix.Generate                         Cabal2Nix.Hackage                         Cabal2Nix.License                         Cabal2Nix.Name                         Cabal2Nix.Normalize-                        Cabal2Nix.Package                         Cabal2Nix.PostProcess  Executable hackage4nix   main-is:              Hackage4Nix.hs   hs-source-dirs:       src   Build-Depends:        base >= 3 && < 5, regex-posix, pretty, Cabal >= 1.8,-                        mtl, containers, directory, filepath, nixos-types+                        mtl, containers, directory, filepath, nixos-types >= 1.1,+                        hackage-db   Extensions:           PatternGuards, RecordWildCards, CPP   Ghc-Options:          -Wall   other-modules:        Cabal2Nix.CorePackages                         Cabal2Nix.Flags+                        Cabal2Nix.Generate                         Cabal2Nix.License                         Cabal2Nix.Name                         Cabal2Nix.Normalize-                        Cabal2Nix.Package                         Cabal2Nix.PostProcess--Executable packagelist-  main-is:              PackageList.hs-  hs-source-dirs:       src-  Build-Depends:        base >= 3 && < 5, regex-posix, process, Cabal,-                        filepath, directory-  Ghc-Options:          -Wall
src/Cabal2Nix.hs view
@@ -1,7 +1,7 @@ module Main ( main ) where  import Cabal2Nix.Hackage ( hashPackage, readCabalFile )-import Cabal2Nix.Package ( cabal2nix )+import Cabal2Nix.Generate ( cabal2nix ) import Cabal2Nix.Normalize ( normalize ) import Distribution.NixOS.Derivation.Cabal import Distribution.NixOS.Derivation.Meta
src/Cabal2Nix/Flags.hs view
@@ -1,15 +1,19 @@-module Cabal2Nix.Flags ( configureFlags ) where+module Cabal2Nix.Flags ( pkgConfigureFlags ) where  import Distribution.Package import Distribution.PackageDescription -configureFlags :: PackageIdentifier -> FlagAssignment-configureFlags (PackageIdentifier (PackageName name) _)- | name == "pandoc"     = [enable "highlighting", enable "threaded"]- | otherwise            = []+pkgConfigureFlags :: PackageIdentifier -> (FlagAssignment,[String])+pkgConfigureFlags (PackageIdentifier (PackageName name) _)+ | name == "pandoc"      = ([enable "highlighting", enable "threaded"],[])+ | name == "threadscope" = ([], ["--ghc-options=-rtsopts"])+ | name == "X11-xft"     = ([], ["--extra-include-dirs=${freetype}/include/freetype2"])+ | otherwise             = ([],[])  enable :: String -> (FlagName,Bool) enable name = (FlagName name, True) -disable :: String -> (FlagName,Bool)-disable name = (FlagName name, False)+-- Uncommend this function when it's actually used.+--+-- disable :: String -> (FlagName,Bool)+-- disable name = (FlagName name, False)
+ src/Cabal2Nix/Generate.hs view
@@ -0,0 +1,54 @@+module Cabal2Nix.Generate ( cabal2nix ) where++import Cabal2Nix.License+import Cabal2Nix.PostProcess+import Cabal2Nix.Normalize+import Cabal2Nix.Flags+import Data.Maybe+import Distribution.Compiler+import qualified Distribution.Package as Cabal+import qualified Distribution.PackageDescription as Cabal+import Distribution.PackageDescription.Configuration+import Distribution.System+import Distribution.Version+import Distribution.NixOS.Derivation.Cabal++cabal2nix :: Cabal.GenericPackageDescription -> Derivation+cabal2nix cabal = normalize $ postProcess $ MkDerivation+  { pname          = let Cabal.PackageName x = Cabal.pkgName pkg in x+  , version        = Cabal.pkgVersion pkg+  , sha256         = "cabal2nix left the she256 field undefined"+  , isLibrary      = isJust (Cabal.library tpkg)+  , isExecutable   = not (null (Cabal.executables tpkg))+  , buildDepends   = map unDep deps+  , buildTools     = map unDep tools+  , extraLibs      = libs+  , pkgConfDeps    = pcs+  , configureFlags = pkgConfigureFlags pkg+  , runHaddock     = True+  , metaSection    = Meta+                   { homepage    = Cabal.homepage descr+                   , description = Cabal.synopsis descr+                   , license     = fromCabalLicense (Cabal.license descr)+                   , platforms   = []+                   , maintainers = []+                   }+  }+  where+    descr   = Cabal.packageDescription cabal+    pkg     = Cabal.package descr+    deps    = Cabal.buildDepends tpkg+    libDeps = map Cabal.libBuildInfo (maybeToList (Cabal.library tpkg))+    exeDeps = map Cabal.buildInfo (Cabal.executables tpkg)+    tools   = concatMap Cabal.buildTools (libDeps ++ exeDeps)+    libs    = concatMap Cabal.extraLibs (libDeps ++ exeDeps)+    pcs     = map unDep (concatMap Cabal.pkgconfigDepends (libDeps ++ exeDeps))+    Right (tpkg, _) = finalizePackageDescription+                        (fst (pkgConfigureFlags pkg))+                        (const True)+                        (Platform I386 Linux)                   -- shouldn't be hardcoded+                        (CompilerId GHC (Version [7,0,4] []))   -- dito+                        [] cabal++unDep :: Cabal.Dependency -> String+unDep (Cabal.Dependency (Cabal.PackageName x) _) = x
− src/Cabal2Nix/Package.hs
@@ -1,53 +0,0 @@-module Cabal2Nix.Package ( cabal2nix ) where--import Cabal2Nix.License-import Cabal2Nix.PostProcess-import Cabal2Nix.Normalize-import Cabal2Nix.Flags-import Data.Maybe-import Distribution.Compiler-import qualified Distribution.Package as Cabal-import qualified Distribution.PackageDescription as Cabal-import Distribution.PackageDescription.Configuration-import Distribution.System-import Distribution.Version-import Distribution.NixOS.Derivation.Cabal--cabal2nix :: Cabal.GenericPackageDescription -> Derivation-cabal2nix cabal = normalize $ postProcess $ MkDerivation-  { pname        = let Cabal.PackageName x = Cabal.pkgName pkg in x-  , version      = Cabal.pkgVersion pkg-  , sha256       = "cabal2nix left the she256 field undefined"-  , isLibrary    = isJust (Cabal.library tpkg)-  , isExecutable = not (null (Cabal.executables tpkg))-  , buildDepends = map unDep deps-  , buildTools   = map unDep tools-  , extraLibs    = libs-  , pkgConfDeps  = pcs-  , runHaddock   = True-  , metaSection  = Meta-                   { homepage    = Cabal.homepage descr-                   , description = Cabal.synopsis descr-                   , license     = fromCabalLicense (Cabal.license descr)-                   , platforms   = []-                   , maintainers = []-                   }-  }-  where-    descr = Cabal.packageDescription cabal-    pkg   = Cabal.package descr-    deps    = Cabal.buildDepends tpkg-    libDeps = map Cabal.libBuildInfo (maybeToList (Cabal.library tpkg))-    exeDeps = map Cabal.buildInfo (Cabal.executables tpkg)-    tools   = concatMap Cabal.buildTools (libDeps ++ exeDeps)-    libs    = concatMap Cabal.extraLibs (libDeps ++ exeDeps)-    pcs     = map unDep (concatMap Cabal.pkgconfigDepends (libDeps ++ exeDeps))-    Right (tpkg, _) = finalizePackageDescription-                        (configureFlags pkg)-                        (const True)-                        (Platform I386 Linux)                   -- shouldn't be hardcoded-                        (CompilerId GHC (Version [7,0,4] []))   -- dito-                        [] cabal--unDep :: Cabal.Dependency -> String-unDep (Cabal.Dependency (Cabal.PackageName x) _) = x
src/Cabal2Nix/PostProcess.hs view
@@ -30,6 +30,7 @@   | pname == "terminfo"         = deriv { extraLibs = "ncurses":extraLibs }   | pname == "vacuum"           = deriv { extraLibs = "ghcPaths":extraLibs }   | pname == "wxcore"           = deriv { extraLibs = "wxGTK":"mesa":"libX11":extraLibs }+  | pname == "X11-xft"          = deriv { extraLibs = "pkgconfig":"freetype":"fontconfig":extraLibs }   | pname == "xmonad"           = deriv { extraLibs = delete "libmpd" extraLibs }   | pname == "xmonad-extras"    = deriv { buildDepends = delete "libmpd" buildDepends }   | otherwise                   = deriv
src/Hackage4Nix.hs view
@@ -1,25 +1,26 @@ module Main ( main ) where -import System.IO-import System.FilePath-import System.Directory-import System.Environment-import System.Exit+import Cabal2Nix.Normalize+import Cabal2Nix.Generate+import Control.Exception ( bracket )+import Control.Monad.RWS import Data.List+import Data.Maybe import qualified Data.Set as Set-import Control.Monad.State-import Control.Exception ( bracket )-import Text.Regex.Posix import Data.Version-import Distribution.PackageDescription.Parse ( parsePackageDescription, ParseResult(..) )+import qualified Distribution.Hackage.DB as DB+import Distribution.NixOS.Derivation.Cabal+import Distribution.NixOS.Derivation.Meta import Distribution.Package import Distribution.PackageDescription ( GenericPackageDescription() ) import Distribution.Text import System.Console.GetOpt ( OptDescr(..), ArgDescr(..), ArgOrder(..), usageInfo, getOpt )-import Cabal2Nix.Package-import Cabal2Nix.Normalize-import Distribution.NixOS.Derivation.Cabal-import Distribution.NixOS.Derivation.Meta+import System.Directory+import System.Environment+import System.Exit+import System.FilePath+import System.IO+import Text.Regex.Posix  data Pkg = Pkg Derivation FilePath Bool   deriving (Show, Eq, Ord)@@ -29,19 +30,17 @@ data Configuration = Configuration   { _msgDebug  :: String -> IO ()   , _msgInfo   :: String -> IO ()-  , _hackageDb :: FilePath-  , _pkgset    :: PkgSet+  , _hackageDb :: DB.Hackage   }  defaultConfiguration :: Configuration defaultConfiguration = Configuration   { _msgDebug  = hPutStrLn stderr   , _msgInfo   = hPutStrLn stderr-  , _hackageDb = "/dev/shm/hackage"-  , _pkgset    = Set.empty+  , _hackageDb = DB.empty   } -type Hackage4Nix a = StateT Configuration IO a+type Hackage4Nix a = RWST Configuration () PkgSet IO a  io :: (MonadIO m) => IO a -> m a io = liftIO@@ -52,18 +51,17 @@   return [ x | x <- entries, x /= ".", x /= ".." ]  msgDebug, msgInfo :: String -> Hackage4Nix ()-msgDebug msg = get >>= \s -> io (_msgDebug s msg)-msgInfo msg = get >>= \s -> io (_msgInfo s msg)+msgDebug msg = ask >>= \s -> io (_msgDebug s msg)+msgInfo msg = ask >>= \s -> io (_msgInfo s msg) -readCabalFile :: String -> String -> Hackage4Nix GenericPackageDescription-readCabalFile name vers = do-  hackageDir <- gets _hackageDb-  let cabal = hackageDir </> name </> vers </> name <.> "cabal"-  pkg' <- fmap parsePackageDescription (io (readFile cabal))-  pkg <- case pkg' of-           ParseOk _ a -> return a-           ParseFailed err -> fail ("cannot parse cabal file " ++ cabal ++ ": " ++ show err)-  return pkg+getCabalPackage :: String -> Version -> Hackage4Nix GenericPackageDescription+getCabalPackage name vers = do+  db <- asks _hackageDb+  case DB.lookup name db of+    Just db' -> case DB.lookup vers db' of+                  Just pkg -> return pkg+                  Nothing  -> fail ("hackage doesn't know about " ++ name ++ " version " ++ display vers)+    Nothing  -> fail ("hackage doesn't know about " ++ show name)  discoverNixFiles :: (FilePath -> Hackage4Nix ()) -> FilePath -> Hackage4Nix () discoverNixFiles yield dirOrFile = do@@ -75,10 +73,7 @@  regenerateDerivation :: Derivation -> String -> Bool regenerateDerivation deriv buf = not (pname deriv `elem` patchedPackages) &&-                                 not (buf =~ "(pre|post)Configure|configureFlags|(pre|post)Install|patchPhase")--readVersion :: String -> Version-readVersion str = maybe (error $ "cannot parse version " ++ show str) id (simpleParse str)+                                 not (buf =~ "(pre|post)Configure|(pre|post)Install|patchPhase")  parseNixFile :: FilePath -> String -> Hackage4Nix (Maybe Pkg) parseNixFile path buf@@ -100,12 +95,11 @@       | otherwise                        = compare (pname deriv1) (pname deriv2)     f2 (Pkg deriv1 _ _) (Pkg deriv2 _ _) = pname deriv1 == pname deriv2 -discoverUpdates :: String -> String -> Hackage4Nix [String]+discoverUpdates :: String -> Version -> Hackage4Nix [Version] discoverUpdates name vers = do-  hackage <- gets _hackageDb-  versionStrings <- io $ readDirectory (hackage </> name)-  let versions = map readVersion versionStrings-  return [ showVersion v | v <- versions, v > readVersion vers ]+  db <- asks _hackageDb+  let versions = DB.keys (fromJust (DB.lookup name db))+  return (filter (>vers) versions)  updateNixPkgs :: [FilePath] -> Hackage4Nix () updateNixPkgs paths = do@@ -117,10 +111,10 @@         let Pkg deriv path regenerate = nix             maints = maintainers (metaSection deriv)             plats  = platforms (metaSection deriv)-        modify $ \cfg -> cfg { _pkgset = Set.insert nix (_pkgset cfg) }+        modify (Set.insert nix)         when regenerate $ do           msgDebug ("re-generate " ++ path)-          pkg <- readCabalFile (pname deriv) (display (version deriv))+          pkg <- getCabalPackage (pname deriv) (version deriv)           let deriv'  = (cabal2nix pkg) { sha256 = sha256 deriv, runHaddock = runHaddock deriv }               meta    = metaSection deriv'               plats'  = if null plats then platforms meta else plats@@ -130,10 +124,10 @@                                                }                                }           io $ writeFile path (show (disp (normalize (deriv''))))-  pkgset <- gets (selectLatestVersions . _pkgset)+  pkgset <- gets selectLatestVersions   updates' <- flip mapM (Set.elems pkgset) $ \pkg -> do     let Pkg deriv _ _ = pkg-    updates <- discoverUpdates (pname deriv) (display (version deriv))+    updates <- discoverUpdates (pname deriv) (version deriv)     return (pkg,updates)   let updates = [ u | u@(_,(_:_)) <- updates' ]   when (not (null updates)) $ do@@ -143,7 +137,7 @@       msgInfo ""       msgInfo $ (display (packageId deriv)) ++ ":"       flip mapM_ versions $ \newVersion -> do-        let deriv' = deriv { version = readVersion newVersion }+        let deriv' = deriv { version = newVersion }         msgInfo $ "  " ++ genCabal2NixCmdline (Pkg deriv' path regenerate)   return () @@ -185,15 +179,6 @@               , "repository packages up-to-date. It scans a checked-out copy of"               , "Nixpkgs for expressions that use 'cabal.mkDerivation', and"               , "re-generates them in-place with cabal2nix."-              , ""-              , "Because we don't want to generate a barrage of HTTP requests during"-              , "that procedure, the tool expects a copy of the Hackage database"-              , "available at some local path, i.e. \"/dev/shm/hackage\" by default."-              , "That directory can be set up as follows:"-              , ""-              , "  cabal update"-              , "  mkdir -p /dev/shm/hackage"-              , "  tar xf ~/.cabal/packages/hackage.haskell.org/00-index.tar -C /dev/shm/hackage\n"               ]        cmdlineError :: String -> IO a@@ -207,11 +192,13 @@    when (PrintHelp `elem` opts) (cmdlineError "") +  hackage <- DB.readHackage   let cfg = defaultConfiguration             { _msgDebug  = if Verbose `elem` opts then _msgDebug defaultConfiguration else const (return ())-            , _hackageDb = last $ _hackageDb defaultConfiguration : [ p | HackageDB p <- opts ]+            , _hackageDb = hackage             }-  flip evalStateT cfg (updateNixPkgs args)+  ((),_,()) <- runRWST (updateNixPkgs args) cfg Set.empty+  return ()   -- Packages that we cannot parse.
− src/PackageList.hs
@@ -1,73 +0,0 @@-module Main ( main ) where--import Control.Exception ( assert )-import Control.Monad ( when, filterM )-import Data.Char ( toLower )-import Data.List ( nubBy, sortBy )-import Data.Ord ( comparing )-import Data.Version ( Version(..) )-import Distribution.Package ( PackageIdentifier(..), PackageName(..) )-import Distribution.Text ( simpleParse, display )-import System.Directory ( doesDirectoryExist, doesFileExist )-import System.FilePath ( (</>), (<.>) )-import System.Process ( readProcess )-import Text.Regex.Posix ( (=~), match, makeRegexOpts, compExtended, execBlank )--type Pkg    = (String,Version,String) -- (Name, Version, Attribute)-type Pkgset = [Pkg]--comparePkgByVersion :: Pkg -> Pkg -> Ordering  -- prefers the latest version-comparePkgByVersion (n1,v1,a1) (n2,v2,a2)-  | a1 == a2    = assert (n1 == n2) (compare v2 v1)-  | otherwise   = compare a2 a1--comparePkgByName :: Pkg -> Pkg-> Ordering-comparePkgByName (n1,_,_) (n2,_,_) = comparing (map toLower) n1 n2--parseHaskellPackageName :: String -> Maybe Pkg-parseHaskellPackageName name =-  case name `regsubmatch` "^(haskellPackages[^ \t]+)[ \t]+(.+)$" of-    [attr,name'] -> case name' `regsubmatch` "^haskell-(.+)-ghc[0-9.]+-(.+)$" of-                      [name'',version] -> case simpleParse version of-                                            Just version' -> Just (name'',version',attr)-                                            _             -> error ("cannot parse " ++ show name)-                      _                -> case simpleParse name' of-                                            Just (PackageIdentifier (PackageName n) v) -> Just (n,v,attr)-                                            _                                          -> error ("cannot parse " ++ show name)-    _            -> Nothing--getHaskellPackageList :: IO Pkgset-getHaskellPackageList = do-  allPkgs <- fmap lines (readProcess "bash" ["-c", "exec nix-env -qaP \\* 2>/dev/tty"] "")-  return [ p | Just p <- map parseHaskellPackageName allPkgs ]--stripProfilingVersions :: Pkgset -> Pkgset-stripProfilingVersions pkgs = [ p | p@(_,_,attr) <- pkgs , not (attr =~ "ghc[0-9.]+_profiling") ]--stripGhc721Versions :: Pkgset -> Pkgset-stripGhc721Versions pkgs = [ p | p@(_,_,attr) <- pkgs , not (attr =~ "ghc721") ]--selectLatestVersions :: Pkgset -> Pkgset-selectLatestVersions = nubBy (\x y -> comparePkgByName x y == EQ) . sortBy comparePkgByVersion--isHackagePackage :: Pkg -> IO Bool-isHackagePackage (name,version,_) = doesFileExist path-  where path = "/dev/shm/hackage/" </> name </> display version </> name <.> "cabal"--formatPackageLine :: Pkg -> String-formatPackageLine (name,version,attr) = show (name, display version, Just url)-  where-    url = "http://hydra.nixos.org/job/nixpkgs/trunk/" ++ attr--regsubmatch :: String -> String -> [String]-regsubmatch buf patt = let (_,_,_,x) = f in x-  where f :: (String,String,String,[String])-        f = match (makeRegexOpts compExtended execBlank patt) buf--main :: IO ()-main = do-  haveHackage <- doesDirectoryExist "/dev/shm/hackage"-  when (not haveHackage) (fail "cannot find hackage database at /dev/shm/hackage")-  pkgset' <- fmap (selectLatestVersions . stripGhc721Versions . stripProfilingVersions) getHaskellPackageList-  pkgset <- filterM isHackagePackage pkgset'-  mapM_ (putStrLn . formatPackageLine) (sortBy comparePkgByName pkgset)