packages feed

cabal2nix 1.10 → 1.11

raw patch · 10 files changed

+400/−281 lines, 10 filesdep ~Cabal

Dependency ranges changed: Cabal

Files

cabal2nix.cabal view
@@ -1,5 +1,5 @@ Name:                   cabal2nix-Version:                1.10+Version:                1.11 Copyright:              (c) 2011 Peter Simons and Andres Loeh License:                BSD3 License-File:           LICENSE@@ -41,28 +41,43 @@   Type:                 git   Location:             git://github.com/haskell4nix/cabal2nix.git +Library+  Build-Depends:        base >= 3 && < 5, regex-posix, pretty, Cabal+  hs-source-dirs:       src+  Extensions:           PatternGuards+  Ghc-Options:          -Wall+  Exposed-Modules:      Distribution.NixOS.Derivation.Cabal+                        Distribution.NixOS.Derivation.License+                        Distribution.NixOS.Derivation.Meta+  other-modules:        Distribution.NixOS.Derivation.PrettyPrinting+ Executable cabal2nix   main-is:              Cabal2Nix.hs   hs-source-dirs:       src-  Build-Depends:        base >= 3 && < 5, Cabal, process, HTTP, pretty, filepath, directory+  Build-Depends:        base >= 3 && < 5, regex-posix, pretty, Cabal,+                        filepath, directory, process, HTTP+  Extensions:           PatternGuards   Ghc-Options:          -Wall-  other-modules:        Cabal2Nix.Pretty-                        Cabal2Nix.License+  other-modules:        Cabal2Nix.CorePackages+                        Cabal2Nix.Hackage                         Cabal2Nix.Name-                        Cabal2Nix.CorePackages                         Cabal2Nix.Package-                        Cabal2Nix.Hackage+                        Distribution.NixOS.Derivation.Cabal+                        Distribution.NixOS.Derivation.License+                        Distribution.NixOS.Derivation.Meta+                        Distribution.NixOS.Derivation.PrettyPrinting  Executable hackage4nix   main-is:              Hackage4Nix.hs   hs-source-dirs:       src-  Build-Depends:        base >= 3 && < 5, Cabal >= 1.8, pretty, filepath, directory,-                        regex-posix, mtl, containers+  Build-Depends:        base >= 3 && < 5, regex-posix, pretty, Cabal,+                        mtl, containers, directory, filepath   Extensions:           PatternGuards-  other-modules:        Cabal2Nix.Pretty-                        Cabal2Nix.License+  Ghc-Options:          -Wall+  other-modules:        Cabal2Nix.CorePackages                         Cabal2Nix.Name-                        Cabal2Nix.CorePackages                         Cabal2Nix.Package-                        Cabal2Nix.Hackage-+                        Distribution.NixOS.Derivation.Cabal+                        Distribution.NixOS.Derivation.License+                        Distribution.NixOS.Derivation.Meta+                        Distribution.NixOS.Derivation.PrettyPrinting
src/Cabal2Nix.hs view
@@ -1,19 +1,21 @@ module Main ( main ) where  import System.IO ( hPutStrLn, hFlush, stdout, stderr )-import System.Environment ( getArgs )+import System.Environment -- ( getArgs ) import Control.Exception ( bracket ) import System.Exit ( exitFailure ) import Distribution.PackageDescription.Parse ( parsePackageDescription, ParseResult(..) ) import Distribution.PackageDescription ( package, packageDescription )-import Distribution.Text ( simpleParse )+import Distribution.Text import Data.List ( isPrefixOf ) import Control.Monad ( when ) import Network.HTTP ( simpleHTTP, getRequest, getResponseBody ) import System.Console.GetOpt ( OptDescr(..), ArgDescr(..), ArgOrder(..), usageInfo, getOpt ) -import Cabal2Nix.Package ( showNixPkg, cabal2nix )+import Cabal2Nix.Package ( cabal2nix ) import Cabal2Nix.Hackage ( hackagePath, Ext(..), hashPackage )+import Distribution.NixOS.Derivation.Cabal+import Distribution.NixOS.Derivation.Meta  readCabalFile :: FilePath -> IO String readCabalFile path@@ -60,11 +62,11 @@   let uri         = args       hash        = [ h | SHA256 h <- opts ]       noHaddock   = NoHaddock `elem` opts-      maintainers = [ m | Maintainer m <- opts ]-      platforms'  = [ p | Platform p <- opts ]-      platforms-        | null platforms' = if not (null maintainers) then ["self.ghc.meta.platforms"] else []-        | otherwise       = platforms'+      maints      = [ if '.' `elem` m then m else "self.stdenv.lib.maintainers." ++ m | Maintainer m <- opts ]+      plats'      = [ if '.' `elem` p then p else "self.stdenv.lib.platforms." ++ p | Platform p <- opts ]+      plats+        | null plats' = if not (null maints) then ["self.ghc.meta.platforms"] else []+        | otherwise   = plats'    when (length uri /= 1) (cmdlineError "*** exactly one URI must be specified")   when (length hash > 1) (cmdlineError "*** the --sha256 option may be specified only once")@@ -78,6 +80,13 @@    let packageId = package (packageDescription cabal) -  sha256 <- if null hash then hashPackage packageId else return (head hash)+  sha <- if null hash then hashPackage packageId else return (head hash) -  putStr (showNixPkg (cabal2nix cabal sha256 noHaddock platforms maintainers))+  let deriv  = (cabal2nix cabal) { sha256 = sha, runHaddock = not noHaddock }+      deriv' = deriv { metaSection = (metaSection deriv)+                                     { maintainers = maints+                                     , platforms   = plats+                                     }+                     }++  putStr (show (disp deriv'))
− src/Cabal2Nix/License.hs
@@ -1,21 +0,0 @@-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                 = "self.stdenv.lib.licenses.proprietary"-showLic OtherLicense                      = show "unknown"-showLic l                                 = error $ "unknown license: " ++ show l
src/Cabal2Nix/Package.hs view
@@ -1,145 +1,55 @@-module Cabal2Nix.Package-  ( cabal2nix, showNixPkg-  , PkgName, PkgVersion, PkgSHA256, PkgURL, PkgDescription, PkgLicense-  , PkgIsLib, PkgIsExe, PkgDependencies, PkgBuildTools, PkgExtraLibs-  , PkgPkgconfigDeps, PkgPlatforms, PkgMaintainers, PkgNoHaddock, Pkg(..)-  )-  where+module Cabal2Nix.Package ( cabal2nix ) where -import Data.List import Data.Maybe import Distribution.Compiler-import Distribution.Package-import Distribution.PackageDescription+import qualified Distribution.Package as Cabal+import qualified Distribution.PackageDescription as Cabal import Distribution.PackageDescription.Configuration import Distribution.System import Distribution.Version-import Text.PrettyPrint-import Data.Version ( showVersion )--import Cabal2Nix.License+import Distribution.NixOS.Derivation.Cabal 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       = String-type PkgIsLib         = Bool-type PkgIsExe         = Bool-type PkgDependencies  = [Dependency] -- [CondTree ConfVar [Dependency] ()]-type PkgBuildTools    = [Dependency]-type PkgExtraLibs     = [String]-type PkgPkgconfigDeps = [String]-type PkgNoHaddock     = Bool-type PkgPlatforms     = [String]-type PkgMaintainers   = [String]--data Pkg = Pkg PkgName-               PkgVersion-               PkgSHA256-               PkgURL-               PkgDescription-               PkgLicense-               PkgIsLib-               PkgIsExe-               PkgDependencies-               PkgBuildTools-               PkgExtraLibs-               PkgPkgconfigDeps-               PkgNoHaddock-               PkgPlatforms-               PkgMaintainers-  deriving (Show)--showNixPkg :: Pkg -> String-showNixPkg (Pkg name ver sha256 url desc lic isLib isExe deps-                tools libs pcs noHaddock 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,-              boolattr "noHaddock"        noHaddock noHaddock,-              vcat [-                text "meta" <+> equals <+> lbrace,-                nest 2 $ vcat [-                  onlyIf url  $ attr "homepage"    $ string url,-                  onlyIf desc $ attr "description" $ string desc,-                  attr "license" $ text 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-+import Data.List+import Data.Char -cabal2nix :: GenericPackageDescription -> PkgSHA256 -> PkgNoHaddock -> PkgPlatforms -> PkgMaintainers -> Pkg-cabal2nix cabal sha256 noHaddock platforms maintainers =-    Pkg pkgname pkgver sha256 url desc lic-      isLib isExe-      (buildDepends tpkg)-      tools-      libs-      pcs-      noHaddock-      [ 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 ]+cabal2nix :: Cabal.GenericPackageDescription -> Derivation+cabal2nix cabal = MkDerivation+  { pname        = Cabal.pkgName pkg+  , version      = Cabal.pkgVersion pkg+  , sha256       = "cabal2nix left the she256 field undefined"+  , isLibrary    = isJust (Cabal.library tpkg)+  , isExecutable = not (null (Cabal.executables tpkg))+  , buildDepends = normalizeNixNames (filter (`notElem` (name : corePackages)) $ map unDep deps)+  , buildTools   = normalizeNixNames (filter (`notElem` coreBuildTools) $ map unDep tools)+  , extraLibs    = normalizeNixLibs libs+  , pkgConfDeps  = normalizeNixLibs pcs+  , runHaddock   = True+  , metaSection  = Meta+                   { homepage    = Cabal.homepage descr+                   , description = normalizeDescription (Cabal.synopsis descr)+                   , license     = fromCabalLicense (Cabal.license descr)+                   , platforms   = []+                   , maintainers = []+                   }+  }   where-    pkg = packageDescription cabal-    PackageName pkgname = pkgName (package pkg)-    pkgver = showVersion (pkgVersion (package pkg))-    lic = showLic (license pkg)-    url = homepage pkg-    desc = normalizeDescription (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.+    descr = Cabal.packageDescription cabal+    pkg   = Cabal.package descr+    Cabal.PackageName name  = Cabal.pkgName pkg+    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 [] (const True)-                        (Platform I386 Linux) -- shouldn't be hardcoded-                        (CompilerId GHC (Version [7,0,4] [])) -- dito+                        (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+unDep :: Cabal.Dependency -> String+unDep (Cabal.Dependency (Cabal.PackageName x) _) = x  normalizeDescription :: String -> String normalizeDescription desc@@ -150,3 +60,12 @@ quote :: Char -> [Char] quote '"'  = "\\\"" quote c    = [c]++normalizeList :: [String] -> [String]+normalizeList = nub . sortBy (\x y -> compare (map toLower x) (map toLower y))++normalizeNixNames :: [String] -> [String]+normalizeNixNames = normalizeList . map toNixName++normalizeNixLibs :: [String] -> [String]+normalizeNixLibs = normalizeList . concatMap libNixName
− src/Cabal2Nix/Pretty.hs
@@ -1,42 +0,0 @@-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-             ]
+ src/Distribution/NixOS/Derivation/Cabal.hs view
@@ -0,0 +1,106 @@+{-# LANGUAGE PatternGuards #-}++module Distribution.NixOS.Derivation.Cabal+  ( Derivation(..)+  , parseDerivation+  , module Distribution.NixOS.Derivation.Meta+  , Version(..), PackageName(..)+  )+  where++import Distribution.NixOS.Derivation.PrettyPrinting+import Distribution.NixOS.Derivation.Meta+import Distribution.Package+import Distribution.Text+import Data.Version+import Data.List+import Data.Char+import Text.PrettyPrint+import Text.ParserCombinators.ReadP ( readP_to_S )+import Text.Regex.Posix++data Derivation = MkDerivation+  { pname        :: PackageName+  , version      :: Version+  , sha256       :: String+  , isLibrary    :: Bool+  , isExecutable :: Bool+  , buildDepends :: [String]+  , buildTools   :: [String]+  , extraLibs    :: [String]+  , pkgConfDeps  :: [String]+  , runHaddock   :: Bool+  , metaSection  :: Meta+  }+  deriving (Show, Eq, Ord)++instance Text Derivation where+  disp  = renderDerivation+  parse = error "parsing Distribution.NixOS.Derivation.Cabal.Derivation is not supported yet"++renderDerivation :: Derivation -> Doc+renderDerivation deriv = funargs (map text ("cabal" : inputs)) $$ vcat+  [ text ""+  , text "cabal.mkDerivation" <+> lparen <> text "self" <> colon <+> lbrace+  , nest 2 $ vcat+    [ attr "pname"   $ doubleQuotes (disp (pname deriv))+    , attr "version" $ doubleQuotes (disp (version deriv))+    , attr "sha256"  $ string (sha256 deriv)+    , boolattr "isLibrary" (not (isLibrary deriv) || (isExecutable deriv)) (isLibrary deriv)+    , boolattr "isExecutable" (not (isLibrary deriv) || (isExecutable deriv)) (isExecutable deriv)+    , listattr "buildDepends" (buildDepends deriv)+    , listattr "buildTools" (buildTools deriv)+    , listattr "extraLibraries" (extraLibs deriv)+    , listattr "pkgconfigDepends" (pkgConfDeps deriv)+    , boolattr "noHaddock" (not (runHaddock deriv)) (not (runHaddock deriv))+    , disp (metaSection deriv)+    ]+  , rbrace <> rparen+  , text ""+  ]+  where+    inputs = nub $ sortBy (\x y -> compare (map toLower x) (map toLower y)) $+              filter (/="cabal") $ filter (/="Cabal") $+                buildDepends deriv ++ buildTools deriv ++ extraLibs deriv ++ pkgConfDeps deriv++parseDerivation :: String -> Maybe Derivation+parseDerivation buf+  | buf =~ "cabal.mkDerivation"+  , [name]    <- buf `regsubmatch` "pname *= *\"([^\"]+)\""+  , [vers]    <- buf `regsubmatch` "version *= *\"([^\"]+)\""+  , [sha]     <- buf `regsubmatch` "sha256 *= *\"([^\"]+)\""+  , plats     <- buf `regsubmatch` "platforms *= *([^;]+);"+  , maint     <- buf `regsubmatch` "maintainers *= *\\[([^\"]+)]"+  , noHaddock <- buf `regsubmatch` "noHaddock *= *(true|false) *;"+              = Just $ MkDerivation+                  { pname        = PackageName name+                  , version      = readVersion vers+                  , sha256       = sha+                  , isLibrary    = False+                  , isExecutable = False+                  , buildDepends = []+                  , buildTools   = []+                  , extraLibs    = []+                  , pkgConfDeps  = []+                  , runHaddock   = case noHaddock of "true":[] -> False+                                                     _         -> True+                  , metaSection  = Meta+                                   { homepage    = ""+                                   , description = ""+                                   , license     = Unknown Nothing+                                   , maintainers = concatMap words maint+                                   , platforms   = concatMap words (map (map (\c -> if c == '+' then ' ' else c)) plats)+                                   }+                  }+  | otherwise = Nothing++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++readVersion :: String -> Version+readVersion str =+  case [ v | (v,[]) <- readP_to_S parseVersion str ] of+    [ v' ] -> v'+    _      -> error ("invalid version specifier " ++ show str)
+ src/Distribution/NixOS/Derivation/License.hs view
@@ -0,0 +1,54 @@+module Distribution.NixOS.Derivation.License+  ( License(..)+  , fromCabalLicense+  )+  where++import qualified Distribution.License as Cabal ( License(..) )+import Data.Version ( Version(..) )+import Distribution.Text+import Text.PrettyPrint++data License+  = GPL2+  | GPL3+  | LGPL21+  | LGPL3+  | BSD3+  | BSD4+  | MIT+  | PublicDomain+  | Proprietary+  | Unknown (Maybe String)+  deriving (Eq, Ord)++instance Show License where+  show GPL2                     = "self.stdenv.lib.licenses.gpl2"+  show GPL3                     = "self.stdenv.lib.licenses.gpl3"+  show LGPL21                   = "self.stdenv.lib.licenses.lgpl21"+  show LGPL3                    = "self.stdenv.lib.licenses.gpl3"+  show BSD3                     = "self.stdenv.lib.licenses.bsd3"+  show BSD4                     = "self.stdenv.lib.licenses.bsd4"+  show MIT                      = "self.stdenv.lib.licenses.mit"+  show PublicDomain             = "self.stdenv.lib.licenses.publicDomain"+  show Proprietary              = "self.stdenv.lib.licenses.proprietary"+  show (Unknown lic)            = show (maybe "unknown" id lic)++instance Text License where+  disp = text . show+  parse = error "parsing Distribution.NixOS.Derivation.License is not supported yet"++fromCabalLicense :: Cabal.License -> License+fromCabalLicense (Cabal.GPL Nothing)                     = Unknown (Just "GPL")+fromCabalLicense (Cabal.GPL (Just (Version [2] [])))     = GPL2+fromCabalLicense (Cabal.GPL (Just (Version [3] [])))     = GPL3+fromCabalLicense (Cabal.LGPL Nothing)                    = Unknown (Just "LGPL")+fromCabalLicense (Cabal.LGPL (Just (Version [2,1] [])))  = LGPL21+fromCabalLicense (Cabal.LGPL (Just (Version [3] [])))    = LGPL3+fromCabalLicense Cabal.BSD3                              = BSD3+fromCabalLicense Cabal.BSD4                              = BSD4+fromCabalLicense Cabal.MIT                               = MIT+fromCabalLicense Cabal.PublicDomain                      = PublicDomain+fromCabalLicense Cabal.AllRightsReserved                 = Proprietary+fromCabalLicense Cabal.OtherLicense                      = Unknown Nothing+fromCabalLicense l                                       = error $ "Distribution.NixOS.Derivation.License.fromCabalLicense: unknown license " ++ show l
+ src/Distribution/NixOS/Derivation/Meta.hs view
@@ -0,0 +1,39 @@+module Distribution.NixOS.Derivation.Meta+  ( Meta(..)+  , module Distribution.NixOS.Derivation.License+  )+  where++import Distribution.NixOS.Derivation.PrettyPrinting+import Distribution.NixOS.Derivation.License+import Distribution.Text+import Text.PrettyPrint++data Meta = Meta+  { homepage    :: String+  , description :: String+  , license     :: License+  , platforms   :: [String]+  , maintainers :: [String]+  }+  deriving (Show, Eq, Ord)++instance Text Meta where+  disp  = renderMeta+  parse = error "parsing Distribution.NixOS.Derivation.Cabal.Meta is not supported yet"++renderMeta :: Meta -> Doc+renderMeta meta = vcat+  [ text "meta" <+> equals <+> lbrace+  , nest 2 $ vcat+    [ onlyIf (homepage meta) $ attr "homepage" $ string (homepage meta)+    , onlyIf (description meta) $ attr "description" $ string (description meta)+    , attr "license" $ disp (license meta)+    , onlyIf (platforms meta) $ sep+      [ text "platforms" <+> equals+      , nest 2 ((fsep $ punctuate (text " ++") $ map text (platforms meta))) <> semi+      ]+    , listattr "maintainers" (maintainers meta)+    ]+  , rbrace <> semi+  ]
+ src/Distribution/NixOS/Derivation/PrettyPrinting.hs view
@@ -0,0 +1,47 @@+module Distribution.NixOS.Derivation.PrettyPrinting+  ( onlyIf+  , listattr+  , boolattr+  , attr+  , string+  , funargs+  )+  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++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+             ]
src/Hackage4Nix.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE PatternGuards #-}- module Main ( main ) where  import System.IO@@ -16,9 +14,15 @@ import Text.ParserCombinators.ReadP ( readP_to_S ) import Distribution.PackageDescription.Parse ( parsePackageDescription, ParseResult(..) ) import Distribution.PackageDescription ( GenericPackageDescription() )+import Distribution.Text import System.Console.GetOpt ( OptDescr(..), ArgDescr(..), ArgOrder(..), usageInfo, getOpt )-import Cabal2Nix.Package ( cabal2nix, showNixPkg, PkgName, PkgVersion, PkgSHA256, PkgPlatforms, PkgMaintainers, PkgNoHaddock )+import Cabal2Nix.Package+import Distribution.NixOS.Derivation.Cabal+import Distribution.NixOS.Derivation.Meta +data Pkg = Pkg Derivation FilePath Bool+  deriving (Show, Eq, Ord)+ type PkgSet = Set.Set Pkg  data Configuration = Configuration@@ -70,19 +74,15 @@        (True,_)     -> return ()        (False,_)    -> io (readDirectory dirOrFile) >>= mapM_ (discoverNixFiles yield . (dirOrFile </>)) -type Regenerate = Bool-data Pkg = Pkg PkgName PkgVersion PkgSHA256 PkgNoHaddock PkgPlatforms PkgMaintainers FilePath Regenerate-  deriving (Show, Eq, Ord)--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+regenerateDerivation :: Derivation -> String -> Bool+regenerateDerivation deriv buf = not (display (pname deriv) `elem` patchedPackages) &&+                                 not (buf =~ "preConfigure|configureFlags|postInstall|patchPhase") -normalizeMaintainer :: String -> String-normalizeMaintainer x-  | "self.stdenv.lib.maintainers." `isPrefixOf` x = drop 28 x-  | otherwise                                     = x+readVersion :: String -> Version+readVersion str =+  case [ v | (v,[]) <- readP_to_S parseVersion str ] of+    [ v' ] -> v'+    _      -> error ("invalid version specifier " ++ show str)  parseNixFile :: FilePath -> String -> Hackage4Nix (Maybe Pkg) parseNixFile path buf@@ -92,46 +92,24 @@                = msgDebug ("ignore known bad package " ++ path) >> return Nothing   | buf =~ "src = (fetchurl|fetchgit|sourceFromHead)"                = msgDebug ("ignore non-hackage package " ++ path) >> return Nothing-  | [name]  <- buf `regsubmatch` "name *= *\"([^\"]+)\""-  , [vers]  <- buf `regsubmatch` "version *= *\"([^\"]+)\""-  , [sha]   <- buf `regsubmatch` "sha256 *= *\"([^\"]+)\""-  , plats   <- buf `regsubmatch` "platforms *= *([^;]+);"-  , maint   <- buf `regsubmatch` "maintainers *= *\\[([^\"]+)]"-  , haddock <- buf `regsubmatch` "noHaddock *= *(true|false) *;"-              = let plats' = concatMap words (map (map (\c -> if c == '+' then ' ' else c)) plats)-                    maint' = concatMap words maint-                    noHaddock-                      | "true":[] <- haddock = True-                      | otherwise            = False-                    regenerate = not (name `elem` patchedPackages) &&-                                 not (buf =~ "preConfigure|configureFlags|postInstall|patchPhase")-                in-                  return $ Just $ Pkg name vers sha noHaddock plats'-                                      (map normalizeMaintainer maint')-                                      path regenerate+  | Just deriv <- parseDerivation buf+               = return (Just (Pkg deriv path (regenerateDerivation deriv buf)))   | otherwise = msgInfo ("failed to parse file " ++ path) >> return Nothing -readVersion :: String -> Version-readVersion str =-  case [ v | (v,[]) <- readP_to_S parseVersion str ] of-    [ v' ] -> v'-    _      -> error ("invalid version specifier " ++ show str)- selectLatestVersions :: PkgSet -> PkgSet selectLatestVersions = Set.fromList . nubBy f2 . sortBy f1 . Set.toList   where-    f1 (Pkg n1 v1 _ _ _ _ _ _) (Pkg n2 v2 _ _ _ _ _ _)-      | n1 == n2  = compare v2 v1-      | otherwise = compare n1 n2-    f2 (Pkg n1 _ _ _ _ _ _ _) (Pkg n2 _ _ _ _ _ _ _)-      = n1 == n2+    f1 (Pkg deriv1 _ _) (Pkg deriv2 _ _)+      | pname deriv1 == pname deriv2     = compare (version deriv2) (version deriv1)+      | otherwise                        = compare (pname deriv1) (pname deriv2)+    f2 (Pkg deriv1 _ _) (Pkg deriv2 _ _) = pname deriv1 == pname deriv2 -discoverUpdates :: PkgName -> PkgVersion -> Hackage4Nix [PkgVersion]+discoverUpdates :: String -> String -> Hackage4Nix [String] discoverUpdates name vers = do   hackage <- gets _hackageDb   versionStrings <- io $ readDirectory (hackage </> name)   let versions = map readVersion versionStrings-  return (sort [ showVersion v | v <- versions, v > readVersion vers ])+  return [ showVersion v | v <- versions, v > readVersion vers ]  updateNixPkgs :: [FilePath] -> Hackage4Nix () updateNixPkgs paths = do@@ -140,45 +118,60 @@     flip discoverNixFiles fileOrDir $ \file -> do       nix' <- io (readFile file) >>= parseNixFile file       flip (maybe (return ())) nix' $ \nix -> do-        let Pkg name vers sha noHaddock plats maints path regenerate = nix+        let Pkg deriv path regenerate = nix+            maints = maintainers (metaSection deriv)+            plats  = platforms (metaSection deriv)+        when (null maints) (msgInfo ("no maintainers configured for " ++ path))         modify $ \cfg -> cfg { _pkgset = Set.insert nix (_pkgset cfg) }         when regenerate $ do           msgDebug ("re-generate " ++ path)-          let maints' = nub (sort (maints ++ ["andres","simons"]))+          let maints' = nub (sort (maints ++ ["self.stdenv.lib.maintainers.andres","self.stdenv.lib.maintainers.simons"]))               plats'                 | null plats && not (null maints) = ["self.ghc.meta.platforms"]                 | otherwise                       = plats-          when (null maints) (msgInfo ("no maintainers configured for " ++ path))-          pkg <- readCabalFile name vers-          io $ writeFile path (showNixPkg (cabal2nix pkg sha noHaddock plats' maints'))+          pkg <- readCabalFile (display (pname deriv)) (display (version deriv))+          let deriv'  = (cabal2nix pkg) { sha256 = sha256 deriv, runHaddock = runHaddock deriv }+              deriv'' = deriv' { metaSection = (metaSection deriv')+                                               { maintainers = maints'+                                               , platforms   = plats'+                                               }+                               }+          io $ writeFile path (show (disp deriv''))   pkgset <- gets (selectLatestVersions . _pkgset)   updates' <- flip mapM (Set.elems pkgset) $ \pkg -> do-    let Pkg name vers _ _ _ _ _ _ = pkg-    updates <- discoverUpdates name vers+    let Pkg deriv _ _ = pkg+    updates <- discoverUpdates (display (pname deriv)) (display (version deriv))     return (pkg,updates)   let updates = [ u | u@(_,(_:_)) <- updates' ]   when (not (null updates)) $ do     msgInfo "The following updates are available:"     flip mapM_ updates $ \(pkg,versions) -> do-      let Pkg name vers _ noHaddock plats maints path regenerate = pkg+      let Pkg deriv path regenerate = pkg       msgInfo ""-      msgInfo $ name ++ "-" ++ vers ++ ":"+      msgInfo $ (display (pname deriv)) ++ "-" ++ (display (version deriv)) ++ ":"       flip mapM_ versions $ \newVersion -> do-        msgInfo $ "  " ++ genCabal2NixCmdline (Pkg name newVersion undefined noHaddock plats maints path regenerate)+        let deriv' = deriv { version = readVersion newVersion }+        msgInfo $ "  " ++ genCabal2NixCmdline (Pkg deriv' path regenerate)   return ()  genCabal2NixCmdline :: Pkg -> String-genCabal2NixCmdline (Pkg name vers _ noHaddock plats maints path _) = unwords $ ["cabal2nix"] ++ opts ++ [">"++path']-    where-      opts = [cabal] ++ maints' ++ plats' ++ if noHaddock then ["--no-haddock"] else []-      cabal = "cabal://" ++ name ++ "-" ++ vers-      maints' = [ "--maintainer=" ++ m | m <- maints ]-      plats'-        | ["self.ghc.meta.platforms"] == plats = []-        | otherwise                            =  [ "--platform=" ++ p | p <- plats ]-      path'-        | path =~ "/[0-9\\.]+\\.nix$" = replaceFileName path (vers <.> "nix")-        | otherwise                   = path+genCabal2NixCmdline (Pkg deriv path _) = unwords $ ["cabal2nix"] ++ opts ++ [">"++path']+  where+    meta = metaSection deriv+    opts = [cabal] ++ maints' ++ plats' ++ if runHaddock deriv then [] else ["--no-haddock"]+    cabal = "cabal://" ++ display (pname deriv) ++ "-" ++ display (version deriv)+    maints' = [ "--maintainer=" ++ normalizeMaintainer m | m <- maintainers meta ]+    plats'+      | ["self.ghc.meta.platforms"] == platforms meta = []+      | otherwise                                     =  [ "--platform=" ++ p | p <- platforms meta ]+    path'+      | path =~ "/[0-9\\.]+\\.nix$" = replaceFileName path (display (version deriv) <.> "nix")+      | otherwise                   = path++normalizeMaintainer :: String -> String+normalizeMaintainer x+  | "self.stdenv.lib.maintainers." `isPrefixOf` x = drop 28 x+  | otherwise                                     = x  data CliOption = PrintHelp | Verbose | HackageDB FilePath   deriving (Eq)