packages feed

cabal2nix 1.8 → 1.9

raw patch · 7 files changed

+341/−3 lines, 7 files

Files

cabal2nix.cabal view
@@ -1,5 +1,5 @@ Name:                   cabal2nix-Version:                1.8+Version:                1.9 Copyright:              (c) 2011 Peter Simons and Andres Loeh License:                BSD3 License-File:           LICENSE@@ -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.8/cabal2nix.cabal-  > cabal2nix cabal://cabal2nix-1.8+  > cabal2nix http://hackage.haskell.org/packages/archive/cabal2nix/1.9/cabal2nix.cabal+  > cabal2nix cabal://cabal2nix-1.9   .   If the @--sha256@ option has not been specified, cabal2nix calls   @nix-prefetch-url@ to determine the hash automatically. This causes@@ -46,6 +46,12 @@   hs-source-dirs:       src   Build-Depends:        base >= 3 && < 5, Cabal, process, HTTP, pretty, filepath, directory   Ghc-Options:          -Wall+  other-modules:        Cabal2Nix.Pretty+                        Cabal2Nix.License+                        Cabal2Nix.Name+                        Cabal2Nix.CorePackages+                        Cabal2Nix.Package+                        Cabal2Nix.Hackage  Executable hackage4nix   main-is:              Hackage4Nix.hs@@ -53,3 +59,9 @@   Build-Depends:        base >= 3 && < 5, Cabal, pretty, filepath, directory, bytestring,                         regex-posix, mtl, containers   Ghc-Options:          -Wall+  other-modules:        Cabal2Nix.Pretty+                        Cabal2Nix.License+                        Cabal2Nix.Name+                        Cabal2Nix.CorePackages+                        Cabal2Nix.Package+                        Cabal2Nix.Hackage
+ src/Cabal2Nix/CorePackages.hs view
@@ -0,0 +1,43 @@+module Cabal2Nix.CorePackages ( corePackages, coreBuildTools ) where++-- | List of packages shipped with ghc and therefore at the moment not in+-- nixpkgs. This should probably be configurable at first. Later, it might+-- be good to actually include them as dependencies, but set them to null+-- if GHC provides them (as different GHC versions vary).+--+-- The commented packages have previously been non-core, so we don't filter+-- them.+corePackages :: [String]+corePackages = [+    "array",+    "base",+    "bin-package-db",+    "bytestring",+    "Cabal",+    "containers",+    "directory",+    -- "extensible-exceptions",+    "ffi",+    "filepath",+    "ghc",+    "ghc-binary",+    "ghc-prim",+    "haskell2010", -- new as core, but doesn't work in older GHCs anyway+    "haskell98",+    "hpc",+    "integer-gmp",+    "old-locale",+    "old-time",+    "pretty",+    "process",+    "random",+    "template-haskell",+    -- "time",+    "unix"+  ]++coreBuildTools :: [String]+coreBuildTools = [+    "ghc",+    "hsc2hs"+  ]
+ src/Cabal2Nix/Hackage.hs view
@@ -0,0 +1,43 @@+module Cabal2Nix.Hackage ( hackagePath, Ext(..), hashPackage ) where++import Distribution.Package ( PackageIdentifier(..), PackageName(..) )+import System.Process ( readProcess )+import System.Directory ( doesFileExist, getHomeDirectory, createDirectoryIfMissing )+import System.FilePath ( dropFileName, (</>), (<.>) )+import Data.Version ( showVersion )+import Control.Monad ( when )++data Ext = TarGz | Cabal deriving Eq++showExt :: Ext -> String+showExt TarGz = ".tar.gz"+showExt Cabal = ".cabal"++hackagePath :: PackageIdentifier -> Ext -> String+hackagePath (PackageIdentifier (PackageName name) version') ext =+    "http://hackage.haskell.org/packages/archive/" +++    name ++ "/" ++ version ++ "/" ++ name +++    (if ext == TarGz then "-" ++ version else "") +++    showExt ext+  where+    version = showVersion version'++hashPackage :: PackageIdentifier -> IO String+hashPackage pkg = do+    cachePath <- hashCachePath pkg+    exists <- doesFileExist cachePath+    hash' <- case exists of+              True -> readFile cachePath+              False -> readProcess "bash" ["-c", "exec nix-prefetch-url 2>/dev/tty " ++ hackagePath pkg TarGz] ""+    let hash = reverse (dropWhile (=='\n') (reverse hash'))+    when (not exists) $ do+      createDirectoryIfMissing True (dropFileName cachePath)+      writeFile cachePath hash+    return hash++hashCachePath :: PackageIdentifier -> IO FilePath+hashCachePath (PackageIdentifier (PackageName name) version') = do+    home <- getHomeDirectory+    return $ home ++ "/.cache/cabal2nix" </> name ++ "-" ++ version <.> "sha256"+  where+    version = showVersion version'
+ src/Cabal2Nix/License.hs view
@@ -0,0 +1,21 @@+module Cabal2Nix.License+  (module Cabal2Nix.License, module Distribution.License)+  where++import Distribution.License+import Distribution.Version++showLic :: License -> String+showLic (GPL Nothing)                     = show "GPL"+showLic (GPL (Just (Version [2] [])))     = "self.stdenv.lib.licenses.gpl2"+showLic (GPL (Just (Version [3] [])))     = "self.stdenv.lib.licenses.gpl3"+showLic (LGPL Nothing)                    = show "LGPL"+showLic (LGPL (Just (Version [2,1] [])))  = "self.stdenv.lib.licenses.lgpl21"+showLic (LGPL (Just (Version [3] [])))    = "self.stdenv.lib.licenses.lgpl3"+showLic BSD3                              = "self.stdenv.lib.licenses.bsd3"+showLic BSD4                              = "self.stdenv.lib.licenses.bsd4"+showLic MIT                               = "self.stdenv.lib.licenses.mit"+showLic PublicDomain                      = "self.stdenv.lib.licenses.publicDomain"+showLic AllRightsReserved                 = show "unknown"+showLic OtherLicense                      = show "unknown"+showLic l                                 = error $ "unknown license: " ++ show l
+ src/Cabal2Nix/Name.hs view
@@ -0,0 +1,39 @@+module Cabal2Nix.Name ( toNixName, libNixName ) where++import Data.Char++toNixName :: String -> String+toNixName []      = error "toNixName: empty string is not a valid argument"+toNixName name    = f name+  where+    f []                            = []+    f ('-':c:cs) | c `notElem` "-"  = toUpper c : f cs+    f ('-':_)                       = error ("unexpected package name " ++ show name)+    f (c:cs)                        = c : f cs++-- | Map libraries to Nix packages.+-- TODO: This should probably be configurable. We also need to consider the+-- possibility of name clashes with Haskell libraries. I have included+-- identity mappings to incicate that I have verified their correctness.+libNixName :: String -> [String]+libNixName "adns"      = return "adns"+libNixName "cairo"     = return "cairo"+libNixName "cairo-pdf" = return "cairo"+libNixName "cairo-ps"  = return "cairo"+libNixName "cairo-svg" = return "cairo"+libNixName "crypto"    = return "openssl"+libNixName "gnome-keyring" = return "gnome_keyring"+libNixName "gnome-keyring-1" = return "gnome_keyring"+libNixName "idn"       = return "idn"+libNixName "libidn"    = return "idn"+libNixName "libzip"    = return "libzip"+libNixName "m"         = []  -- in stdenv+libNixName "pcre"      = return "pcre"+libNixName "pq"        = return "postgresql"+libNixName "sndfile"   = return "libsndfile"+libNixName "sqlite3"   = return "sqlite"+libNixName "stdc++"    = []  -- in stdenv+libNixName "xft"       = return "libXft"+libNixName "X11"       = return "libX11"+libNixName "z"         = return "zlib"+libNixName x           = return x
+ src/Cabal2Nix/Package.hs view
@@ -0,0 +1,138 @@+module Cabal2Nix.Package+  ( cabal2nix, showNixPkg+  , PkgName, PkgVersion, PkgSHA256, PkgURL, PkgDescription, PkgLicense+  , PkgIsLib, PkgIsExe, PkgDependencies, PkgBuildTools, PkgExtraLibs+  , PkgPkgconfigDeps, PkgPlatforms, PkgMaintainers+  )+  where++import Data.List+import Data.Maybe+import Distribution.Compiler+import Distribution.Package+import Distribution.PackageDescription+import Distribution.PackageDescription.Configuration+import Distribution.System+import Distribution.Version+import Text.PrettyPrint+import Data.Version ( showVersion )++import Cabal2Nix.License+import Cabal2Nix.Name+import Cabal2Nix.CorePackages+import Cabal2Nix.Pretty++type PkgName          = String+type PkgVersion       = String+type PkgSHA256        = String+type PkgURL           = String+type PkgDescription   = String+type PkgLicense       = License+type PkgIsLib         = Bool+type PkgIsExe         = Bool+type PkgDependencies  = [Dependency] -- [CondTree ConfVar [Dependency] ()]+type PkgBuildTools    = [Dependency]+type PkgExtraLibs     = [String]+type PkgPkgconfigDeps = [String]+type PkgPlatforms     = [String]+type PkgMaintainers   = [String]++data Pkg = Pkg PkgName+               PkgVersion+               PkgSHA256+               PkgURL+               PkgDescription+               PkgLicense+               PkgIsLib+               PkgIsExe+               PkgDependencies+               PkgBuildTools+               PkgExtraLibs+               PkgPkgconfigDeps+               PkgPlatforms+               PkgMaintainers+  deriving (Show)++showNixPkg :: Pkg -> String+showNixPkg (Pkg name ver sha256 url desc lic isLib isExe deps+                tools libs pcs platforms maintainers) =+    render doc+  where+    doc = funargs (map text ("cabal" : pkgInputs)) $$+          vcat [+            text "",+            text "cabal.mkDerivation" <+> lparen <> text "self" <>+              colon <+> lbrace,+            nest 2 $ vcat [+              attr "pname"   $ string name,+              attr "version" $ string ver,+              attr "sha256"  $ string sha256,+              boolattr "isLibrary"    (not isLib || isExe) isLib,+              boolattr "isExecutable" (not isLib || isExe) isExe,+              listattr "buildDepends"     pkgDeps,+              listattr "buildTools"       pkgBuildTools,+              listattr "extraLibraries"   pkgLibs,+              listattr "pkgconfigDepends" pkgPCs,+              vcat [+                text "meta" <+> equals <+> lbrace,+                nest 2 $ vcat [+                  onlyIf url  $ attr "homepage"    $ string url,+                  onlyIf desc $ attr "description" $ string desc,+                  attr "license" $ text (showLic lic),+                  onlyIf platforms $+                    sep [+                      text "platforms" <+> equals,+                      nest 2 ((fsep $ punctuate (text " ++") $ map text platforms)) <> semi+                    ],+                  listattr "maintainers" maintainers+                ],+                rbrace <> semi+              ]+            ],+            rbrace <> rparen,+            text ""+          ]+    pkgLibs       = nub $ sort $ concatMap libNixName libs+    pkgPCs        = nub $ sort $ concatMap libNixName pcs+    pkgDeps       = nub $ sort $ map toNixName $+                    filter (`notElem` (name : corePackages)) $ map unDep deps+    pkgBuildTools = nub $ sort $ map toNixName $+                    filter (`notElem` coreBuildTools) $ map unDep tools+    pkgInputs     = nub $ pkgLibs ++ pkgPCs ++ pkgBuildTools ++ pkgDeps+++cabal2nix :: GenericPackageDescription -> PkgSHA256 -> PkgPlatforms -> PkgMaintainers -> Pkg+cabal2nix cabal sha256 platforms maintainers =+    Pkg pkgname pkgver sha256 url desc lic+      isLib isExe+      (buildDepends tpkg)+      tools+      libs+      pcs+      [ if '.' `elem` p then p else "self.stdenv.lib.platforms." ++ p | p <- platforms ]+      [ if '.' `elem` m then m else "self.stdenv.lib.maintainers." ++ m | m <- maintainers ]+  where+    pkg = packageDescription cabal+    PackageName pkgname = pkgName (package pkg)+    pkgver = showVersion (pkgVersion (package pkg))+    lic = license pkg+    url = homepage pkg+    desc = synopsis pkg+    -- globalDeps = buildDepends pkg+    -- Potentially dangerous: determine a default flattening of the+    -- package description. Better approach: export the conditional+    -- structure and reflect it in the generated file.+    Right (tpkg, _) = finalizePackageDescription [] (const True)+                        (Platform I386 Linux) -- shouldn't be hardcoded+                        (CompilerId GHC (Version [7,0,4] [])) -- dito+                        [] cabal+    isLib   = isJust (library tpkg)+    isExe   = not (null (executables tpkg))+    libDeps = map libBuildInfo $ maybeToList (library tpkg)+    exeDeps = map    buildInfo $ executables tpkg+    libs    =             concatMap extraLibs        (libDeps ++ exeDeps)+    pcs     = map unDep $ concatMap pkgconfigDepends (libDeps ++ exeDeps)+    tools   =             concatMap buildTools       (libDeps ++ exeDeps)++unDep :: Dependency -> String+unDep (Dependency (PackageName x) _) = x
+ src/Cabal2Nix/Pretty.hs view
@@ -0,0 +1,42 @@+module Cabal2Nix.Pretty where++import Text.PrettyPrint++-- Pretty-printing helpers for Nix expressions.++attr :: String -> Doc -> Doc+attr n v = text n <+> equals <+> v <> semi++onlyIf :: [a] -> Doc -> Doc+onlyIf p d = if not (null p) then d else empty++boolattr :: String -> Bool -> Bool -> Doc+boolattr n p v = if p then attr n (bool v) else empty++listattr :: String -> [String] -> Doc+listattr n vs = onlyIf vs $+                sep [ text n <+> equals <+> lbrack,+                      nest 2 $ fsep $ map text vs,+                      rbrack <> semi+                    ]++bool :: Bool -> Doc+bool True  = text "true"+bool False = text "false"++string :: String -> Doc+string = doubleQuotes . text++version :: [Int] -> Doc+version = doubleQuotes . hcat . punctuate (text ".") . map int++prepunctuate :: Doc -> [Doc] -> [Doc]+prepunctuate _ []     = []+prepunctuate p (d:ds) = d : map (p <>) ds++funargs :: [Doc] -> Doc+funargs xs = sep [+               lbrace <+> (fcat $ prepunctuate (comma <> text " ") $+                           map (nest 2) xs),+               rbrace <> colon+             ]