cabal2nix 1.11 → 1.12
raw patch · 17 files changed
+400/−481 lines, 17 filesdep +nixos-typesdep ~Cabalsetup-changednew-component:exe:packagelist
Dependencies added: nixos-types
Dependency ranges changed: Cabal
Files
- Setup.hs +6/−0
- Setup.lhs +0/−8
- cabal2nix.cabal +25/−28
- src/Cabal2Nix.hs +63/−65
- src/Cabal2Nix/Flags.hs +15/−0
- src/Cabal2Nix/Hackage.hs +14/−4
- src/Cabal2Nix/License.hs +20/−0
- src/Cabal2Nix/Name.hs +39/−22
- src/Cabal2Nix/Normalize.hs +58/−0
- src/Cabal2Nix/Package.hs +14/−32
- src/Cabal2Nix/PostProcess.hs +35/−0
- src/Distribution/NixOS/Derivation/Cabal.hs +0/−106
- src/Distribution/NixOS/Derivation/License.hs +0/−54
- src/Distribution/NixOS/Derivation/Meta.hs +0/−39
- src/Distribution/NixOS/Derivation/PrettyPrinting.hs +0/−47
- src/Hackage4Nix.hs +38/−76
- src/PackageList.hs +73/−0
+ Setup.hs view
@@ -0,0 +1,6 @@+module Main (main) where++import Distribution.Simple++main :: IO ()+main = defaultMain
− Setup.lhs
@@ -1,8 +0,0 @@-#!/usr/bin/env runhaskell--> module Main (main) where->-> import Distribution.Simple->-> main :: IO ()-> main = defaultMain
cabal2nix.cabal view
@@ -1,6 +1,6 @@ Name: cabal2nix-Version: 1.11-Copyright: (c) 2011 Peter Simons and Andres Loeh+Version: 1.12+Copyright: Peter Simons, Andres Loeh License: BSD3 License-File: LICENSE Author: Peter Simons <simons@cryp.to>, Andres Loeh <mail@andres-loeh.de>@@ -8,9 +8,9 @@ Homepage: http://github.com/haskell4nix/cabal2nix Category: Distribution Synopsis: Convert Cabal files into Nix build instructions-Cabal-Version: >= 1.6+Cabal-Version: >= 1.8 Build-Type: Simple-Tested-With: GHC == 6.12.3, GHC == 7.0.4+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 commandline syntax is:@@ -41,43 +41,40 @@ 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, regex-posix, pretty, Cabal,- filepath, directory, process, HTTP- Extensions: PatternGuards+ Build-Depends: base >= 3 && < 5, regex-posix, pretty, Cabal >= 1.8,+ filepath, directory, process, HTTP, nixos-types+ Extensions: PatternGuards, RecordWildCards, CPP Ghc-Options: -Wall other-modules: Cabal2Nix.CorePackages+ Cabal2Nix.Flags Cabal2Nix.Hackage+ Cabal2Nix.License Cabal2Nix.Name+ Cabal2Nix.Normalize Cabal2Nix.Package- Distribution.NixOS.Derivation.Cabal- Distribution.NixOS.Derivation.License- Distribution.NixOS.Derivation.Meta- Distribution.NixOS.Derivation.PrettyPrinting+ Cabal2Nix.PostProcess Executable hackage4nix main-is: Hackage4Nix.hs hs-source-dirs: src- Build-Depends: base >= 3 && < 5, regex-posix, pretty, Cabal,- mtl, containers, directory, filepath- Extensions: PatternGuards+ Build-Depends: base >= 3 && < 5, regex-posix, pretty, Cabal >= 1.8,+ mtl, containers, directory, filepath, nixos-types+ Extensions: PatternGuards, RecordWildCards, CPP Ghc-Options: -Wall other-modules: Cabal2Nix.CorePackages+ Cabal2Nix.Flags+ Cabal2Nix.License Cabal2Nix.Name+ Cabal2Nix.Normalize Cabal2Nix.Package- Distribution.NixOS.Derivation.Cabal- Distribution.NixOS.Derivation.License- Distribution.NixOS.Derivation.Meta- Distribution.NixOS.Derivation.PrettyPrinting+ 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,77 +1,76 @@ module Main ( main ) where -import System.IO ( hPutStrLn, hFlush, stdout, stderr )-import System.Environment -- ( getArgs )+import Cabal2Nix.Hackage ( hashPackage, readCabalFile )+import Cabal2Nix.Package ( cabal2nix )+import Cabal2Nix.Normalize ( normalize )+import Distribution.NixOS.Derivation.Cabal+import Distribution.NixOS.Derivation.Meta+ import Control.Exception ( bracket )-import System.Exit ( exitFailure )-import Distribution.PackageDescription.Parse ( parsePackageDescription, ParseResult(..) )-import Distribution.PackageDescription ( package, packageDescription )-import Distribution.Text-import Data.List ( isPrefixOf ) import Control.Monad ( when )-import Network.HTTP ( simpleHTTP, getRequest, getResponseBody )+import Distribution.PackageDescription ( package, packageDescription )+import Distribution.PackageDescription.Parse ( parsePackageDescription, ParseResult(..) )+import Distribution.Text ( disp ) import System.Console.GetOpt ( OptDescr(..), ArgDescr(..), ArgOrder(..), usageInfo, getOpt )+import System.Environment ( getArgs )+import System.Exit ( exitFailure, exitSuccess )+import System.IO ( hPutStrLn, hFlush, stdout, stderr ) -import Cabal2Nix.Package ( cabal2nix )-import Cabal2Nix.Hackage ( hackagePath, Ext(..), hashPackage )-import Distribution.NixOS.Derivation.Cabal-import Distribution.NixOS.Derivation.Meta+data Configuration = Configuration+ { optPrintHelp :: Bool+ , optPrintVersion :: Bool+ , optSha256 :: String+ , optMaintainer :: [String]+ , optPlatform :: [String]+ , optHaddock :: Bool+ }+ deriving (Show) -readCabalFile :: FilePath -> IO String-readCabalFile path- | "cabal://" `isPrefixOf` path = let Just pid = simpleParse (drop 8 path) in readCabalFile (hackagePath pid Cabal)- | "http://" `isPrefixOf` path = simpleHTTP (getRequest path) >>= getResponseBody- | "file://" `isPrefixOf` path = readCabalFile (drop 7 path)- | otherwise = readFile path+defaultConfiguration :: Configuration+defaultConfiguration = Configuration+ { optPrintHelp = False+ , optPrintVersion = False+ , optSha256 = ""+ , optMaintainer = []+ , optPlatform = []+ , optHaddock = True+ } -data CliOption = PrintHelp | SHA256 String | Maintainer String | Platform String | NoHaddock- deriving (Eq)+options :: [OptDescr (Configuration -> Configuration)]+options =+ [ Option ['h'] ["help"] (NoArg (\o -> o { optPrintHelp = True })) "show this help text"+ , Option [] ["sha256"] (ReqArg (\x o -> o { optSha256 = x }) "HASH") "sha256 hash of source tarball"+ , Option ['m'] ["maintainer"] (ReqArg (\x o -> o { optMaintainer = x : optMaintainer o }) "MAINTAINER") "maintainer of this package (may be specified multiple times)"+ , Option ['p'] ["platform"] (ReqArg (\x o -> o { optPlatform = x : optPlatform o }) "PLATFORM") "supported build platforms (may be specified multiple times)"+ , Option [] ["no-haddock"] (NoArg (\o -> o { optHaddock = False })) "don't run Haddock when building this package"+ ] -main :: IO ()-main = bracket (return ()) (\() -> hFlush stdout >> hFlush stderr) $ \() -> do- let options :: [OptDescr CliOption]- options =- [ Option ['h'] ["help"] (NoArg PrintHelp) "show this help text"- , Option [] ["sha256"] (ReqArg SHA256 "HASH") "sha256 hash of source tarball"- , Option ['m'] ["maintainer"] (ReqArg Maintainer "MAINTAINER") "maintainer of this package (may be specified multiple times)"- , Option ['p'] ["platform"] (ReqArg Platform "PLATFORM") "supported build platforms (may be specified multiple times)"- , Option [] ["no-haddock"] (NoArg NoHaddock) "don't run Haddock when building this package"+usage :: String+usage = usageInfo "Usage: cabal2nix [options] url-to-cabal-file" options ++ unlines+ [ ""+ , "Recognized URI schemes:"+ , ""+ , " cabal://pkgname-pkgversion download the specified package from Hackage"+ , " http://host/path fetch the Cabel file via HTTP"+ , " file:///local/path load the Cabal file from the local disk"+ , " /local/path abbreviated version of file URI" ] - usage :: String- usage = usageInfo "Usage: cabal2nix [options] url-to-cabal-file" options ++- "\n\- \Recognized URI schemes:\n\- \\n\- \ cabal://pkgname-pkgversion download the specified package from Hackage\n\- \ http://host/path fetch the Cabel file via HTTP\n\- \ file:///local/path load the Cabal file from the local disk\n\- \ /local/path abbreviated version of file URI\n"-- cmdlineError :: String -> IO a- cmdlineError "" = hPutStrLn stderr usage >> exitFailure- cmdlineError errMsg = hPutStrLn stderr errMsg >> cmdlineError ""+cmdlineError :: String -> IO a+cmdlineError "" = hPutStrLn stderr usage >> exitFailure+cmdlineError errMsg = hPutStrLn stderr errMsg >> cmdlineError "" +main :: IO ()+main = bracket (return ()) (\() -> hFlush stdout >> hFlush stderr) $ \() -> do args' <- getArgs- (opts,args) <- case getOpt Permute options args' of- (o,n,[] ) -> return (o,n)- (_,_,errs) -> cmdlineError (concatMap (\e -> '*':'*':'*':' ':e) errs)-- when (PrintHelp `elem` opts) (cmdlineError "")-- let uri = args- hash = [ h | SHA256 h <- opts ]- noHaddock = NoHaddock `elem` opts- 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'+ (cfg,args) <- case getOpt Permute options args' of+ (o,n,[] ) -> return (foldl (flip ($)) defaultConfiguration o,n)+ (_,_,errs) -> cmdlineError (concatMap ("*** "++) errs) - when (length uri /= 1) (cmdlineError "*** exactly one URI must be specified")- when (length hash > 1) (cmdlineError "*** the --sha256 option may be specified only once")+ when (optPrintHelp cfg) (putStr usage >> exitSuccess)+ when (length args /= 1) (cmdlineError "*** exactly one url-to-cabal-file must be specified\n") - cabal' <- fmap parsePackageDescription (readCabalFile (head uri))+ cabal' <- fmap parsePackageDescription (readCabalFile (head args)) cabal <- case cabal' of ParseOk _ a -> return a ParseFailed err -> do@@ -79,14 +78,13 @@ exitFailure let packageId = package (packageDescription cabal)-- sha <- if null hash then hashPackage packageId else return (head hash)+ sha <- if null (optSha256 cfg) then hashPackage packageId else return (optSha256 cfg) - let deriv = (cabal2nix cabal) { sha256 = sha, runHaddock = not noHaddock }+ let deriv = (cabal2nix cabal) { sha256 = sha, runHaddock = optHaddock cfg } deriv' = deriv { metaSection = (metaSection deriv)- { maintainers = maints- , platforms = plats+ { maintainers = optMaintainer cfg+ , platforms = optPlatform cfg } } - putStr (show (disp deriv'))+ putStr (show (disp (normalize (deriv'))))
+ src/Cabal2Nix/Flags.hs view
@@ -0,0 +1,15 @@+module Cabal2Nix.Flags ( configureFlags ) where++import Distribution.Package+import Distribution.PackageDescription++configureFlags :: PackageIdentifier -> FlagAssignment+configureFlags (PackageIdentifier (PackageName name) _)+ | name == "pandoc" = [enable "highlighting", enable "threaded"]+ | otherwise = []++enable :: String -> (FlagName,Bool)+enable name = (FlagName name, True)++disable :: String -> (FlagName,Bool)+disable name = (FlagName name, False)
src/Cabal2Nix/Hackage.hs view
@@ -1,11 +1,14 @@-module Cabal2Nix.Hackage ( hackagePath, Ext(..), hashPackage ) where+module Cabal2Nix.Hackage ( hashPackage, readCabalFile ) where +import Control.Monad ( when )+import Data.List ( isPrefixOf )+import Data.Version ( showVersion ) import Distribution.Package ( PackageIdentifier(..), PackageName(..) )-import System.Process ( readProcess )+import Distribution.Text+import Network.HTTP ( simpleHTTP, getRequest, getResponseBody ) import System.Directory ( doesFileExist, getHomeDirectory, createDirectoryIfMissing ) import System.FilePath ( dropFileName, (</>), (<.>) )-import Data.Version ( showVersion )-import Control.Monad ( when )+import System.Process ( readProcess ) data Ext = TarGz | Cabal deriving Eq @@ -41,3 +44,10 @@ return $ home ++ "/.cache/cabal2nix" </> name ++ "-" ++ version <.> "sha256" where version = showVersion version'++readCabalFile :: FilePath -> IO String+readCabalFile path+ | "cabal://" `isPrefixOf` path = let Just pid = simpleParse (drop 8 path) in readCabalFile (hackagePath pid Cabal)+ | "http://" `isPrefixOf` path = simpleHTTP (getRequest path) >>= getResponseBody+ | "file://" `isPrefixOf` path = readCabalFile (drop 7 path)+ | otherwise = readFile path
+ src/Cabal2Nix/License.hs view
@@ -0,0 +1,20 @@+module Cabal2Nix.License ( fromCabalLicense ) where++import Distribution.NixOS.Derivation.License+import Distribution.License ( License(..) )+import Data.Version++fromCabalLicense :: Distribution.License.License -> Distribution.NixOS.Derivation.License.License+fromCabalLicense (GPL Nothing) = Unknown (Just "GPL")+fromCabalLicense (GPL (Just (Version [2] []))) = Known "self.stdenv.lib.licenses.gpl2"+fromCabalLicense (GPL (Just (Version [3] []))) = Known "self.stdenv.lib.licenses.gpl3"+fromCabalLicense (LGPL Nothing) = Unknown (Just "LGPL")+fromCabalLicense (LGPL (Just (Version [2,1] []))) = Known "self.stdenv.lib.licenses.lgpl21"+fromCabalLicense (LGPL (Just (Version [3] []))) = Known "self.stdenv.lib.licenses.gpl3"+fromCabalLicense BSD3 = Known "self.stdenv.lib.licenses.bsd3"+fromCabalLicense BSD4 = Known "self.stdenv.lib.licenses.bsd4"+fromCabalLicense MIT = Known "self.stdenv.lib.licenses.mit"+fromCabalLicense PublicDomain = Known "self.stdenv.lib.licenses.publicDomain"+fromCabalLicense AllRightsReserved = Known "self.stdenv.lib.licenses.proprietary"+fromCabalLicense OtherLicense = Unknown Nothing+fromCabalLicense l = error $ "Cabal2Nix.License.fromCabalLicense: unknown license " ++ show l
src/Cabal2Nix/Name.hs view
@@ -1,7 +1,8 @@-module Cabal2Nix.Name ( toNixName, libNixName ) where+module Cabal2Nix.Name ( toNixName, libNixName, buildToolNixName ) where import Data.Char +-- | Map Cabal names to Nix attribute names. toNixName :: String -> String toNixName [] = error "toNixName: empty string is not a valid argument" toNixName name = f name@@ -16,24 +17,40 @@ -- 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+libNixName "adns" = return "adns"+libNixName "cairo-pdf" = return "cairo"+libNixName "cairo-ps" = return "cairo"+libNixName "cairo" = return "cairo"+libNixName "cairo-svg" = return "cairo"+libNixName "crypto" = return "openssl"+libNixName "glib-2.0" = return "glib"+libNixName "gnome-keyring-1" = return "gnome_keyring"+libNixName "gnome-keyring" = return "gnome_keyring"+libNixName "gobject-2.0" = return "glib"+libNixName "gthread-2.0" = return "glib"+libNixName "gtk+-2.0" = return "gtk"+libNixName "gtksourceview-2.0" = return "gtksourceview"+libNixName "idn" = return "idn"+libNixName "libglade-2.0" = return "libglade"+libNixName "libidn" = return "idn"+libNixName "librsvg-2.0" = return "librsvg"+libNixName "libzip" = return "libzip"+libNixName "m" = [] -- in stdenv+libNixName "pangocairo" = return "pango"+libNixName "pcre" = return "pcre"+libNixName "pq" = return "postgresql"+libNixName "sndfile" = return "libsndfile"+libNixName "sqlite3" = return "sqlite"+libNixName "stdc++" = [] -- in stdenv+libNixName "X11" = return "libX11"+libNixName "xft" = return "libXft"+libNixName "z" = return "zlib"+libNixName x = return x++-- | Map build tool names to Nix attribute names.+buildToolNixName :: String -> [String]+buildToolNixName "cabal" = return "cabalInstall"+buildToolNixName "gtk2hsC2hs" = return "gtk2hsBuildtools"+buildToolNixName "gtk2hsHookGenerator" = return "gtk2hsBuildtools"+buildToolNixName "gtk2hsTypeGen" = return "gtk2hsBuildtools"+buildToolNixName x = return (toNixName x)
+ src/Cabal2Nix/Normalize.hs view
@@ -0,0 +1,58 @@+{-# LANGUAGE RecordWildCards #-}++module Cabal2Nix.Normalize ( normalize ) where++import Distribution.NixOS.Derivation.Cabal+import Cabal2Nix.Name+import Cabal2Nix.CorePackages+import Data.List+import Data.Char++normalize :: Derivation -> Derivation+normalize deriv@(MkDerivation {..}) = deriv+ { buildDepends = normalizeNixNames (filter (`notElem` (pname : corePackages)) $ buildDepends)+ , buildTools = normalizeNixBuildTools (filter (`notElem` coreBuildTools) $ buildTools)+ , extraLibs = normalizeNixLibs extraLibs+ , pkgConfDeps = normalizeNixLibs pkgConfDeps+ , metaSection = normalizeMeta metaSection+ }++normalizeMeta :: Meta -> Meta+normalizeMeta meta@(Meta {..}) = meta+ { description = normalizeDescription description+ , maintainers = normalizeMaintainers maintainers+ , platforms = normalizePlatforms platforms+ }++normalizeDescription :: String -> String+normalizeDescription desc+ | null desc = []+ | last desc == '.' && length (filter ('.'==) desc) == 1 = normalizeDescription (reverse (tail (reverse desc)))+ | otherwise = quote (unwords (words desc))++quote :: String -> String+quote ('\\':c:cs) = '\\' : c : quote cs+quote ('"':cs) = '\\' : '"' : quote cs+quote (c:cs) = c : quote cs+quote [] = []++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++normalizeNixBuildTools :: [String] -> [String]+normalizeNixBuildTools = normalizeList . concatMap buildToolNixName++normalizeMaintainers :: [String] -> [String]+normalizeMaintainers maints = normalizeList+ [ if '.' `elem` m then m else "self.stdenv.lib.maintainers." ++ m | m <- maints ]++normalizePlatforms :: [String] -> [String]+normalizePlatforms [] = ["self.ghc.meta.platforms"]+normalizePlatforms plats = normalizeList+ [ if '.' `elem` p then p else "self.stdenv.lib.platforms." ++ p | p <- plats ]
src/Cabal2Nix/Package.hs view
@@ -1,5 +1,9 @@ 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@@ -8,26 +12,22 @@ import Distribution.System import Distribution.Version import Distribution.NixOS.Derivation.Cabal-import Cabal2Nix.Name-import Cabal2Nix.CorePackages-import Data.List-import Data.Char cabal2nix :: Cabal.GenericPackageDescription -> Derivation-cabal2nix cabal = MkDerivation- { pname = Cabal.pkgName pkg+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 = normalizeNixNames (filter (`notElem` (name : corePackages)) $ map unDep deps)- , buildTools = normalizeNixNames (filter (`notElem` coreBuildTools) $ map unDep tools)- , extraLibs = normalizeNixLibs libs- , pkgConfDeps = normalizeNixLibs pcs+ , buildDepends = map unDep deps+ , buildTools = map unDep tools+ , extraLibs = libs+ , pkgConfDeps = pcs , runHaddock = True , metaSection = Meta { homepage = Cabal.homepage descr- , description = normalizeDescription (Cabal.synopsis descr)+ , description = Cabal.synopsis descr , license = fromCabalLicense (Cabal.license descr) , platforms = [] , maintainers = []@@ -36,36 +36,18 @@ where 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)+ 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--normalizeDescription :: String -> String-normalizeDescription desc- | null desc = []- | last desc == '.' && length (filter ('.'==) desc) == 1 = normalizeDescription (reverse (tail (reverse desc)))- | otherwise = unwords (words desc) >>= quote--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/PostProcess.hs view
@@ -0,0 +1,35 @@+{-# LANGUAGE RecordWildCards #-}++module Cabal2Nix.PostProcess ( postProcess ) where++import Distribution.NixOS.Derivation.Cabal+import Data.List++postProcess :: Derivation -> Derivation+postProcess deriv@(MkDerivation {..})+ | pname == "alex" = deriv { buildTools = "perl":buildTools }+ | pname == "cairo" = deriv { extraLibs = "pkgconfig":"glibc":"cairo":"zlib":extraLibs }+ | pname == "editline" = deriv { extraLibs = "libedit":extraLibs }+ | pname == "epic" = deriv { extraLibs = "gmp":"boehmgc":extraLibs, buildTools = "happy":buildTools }+ | pname == "glade" = deriv { extraLibs = "pkgconfig":"glibc":extraLibs, pkgConfDeps = "gtkC":(delete "gtk" pkgConfDeps) }+ | pname == "glib" = deriv { extraLibs = "pkgconfig":"glibc":extraLibs }+ | pname == "GLUT" = deriv { extraLibs = "glut":"libSM":"libICE":"libXmu":"libXi":"mesa":extraLibs }+ | pname == "gtk" = deriv { extraLibs = "pkgconfig":"glibc":extraLibs, buildDepends = delete "gio" buildDepends }+ | pname == "gtksourceview2" = deriv { extraLibs = "pkgconfig":"glibc":extraLibs }+ | pname == "haskell-src" = deriv { buildTools = "happy":buildTools }+ | pname == "hmatrix" = deriv { extraLibs = "gsl":"liblapack":"blas":extraLibs }+ | pname == "idris" = deriv { buildTools = "happy":buildTools }+ | pname == "OpenAL" = deriv { extraLibs = "openal":extraLibs }+ | pname == "OpenGL" = deriv { extraLibs = "mesa":"libX11":extraLibs }+ | pname == "pango" = deriv { extraLibs = "pkgconfig":"glibc":extraLibs }+ | pname == "repa-examples" = deriv { extraLibs = "llvm":extraLibs }+ | pname == "SDL-image" = deriv { extraLibs = "SDL_image":extraLibs }+ | pname == "SDL-mixer" = deriv { extraLibs = "SDL_mixer":extraLibs }+ | pname == "SDL-ttf" = deriv { extraLibs = "SDL_ttf":extraLibs }+ | pname == "svgcairo" = deriv { extraLibs = "glibc":extraLibs }+ | pname == "terminfo" = deriv { extraLibs = "ncurses":extraLibs }+ | pname == "vacuum" = deriv { extraLibs = "ghcPaths":extraLibs }+ | pname == "wxcore" = deriv { extraLibs = "wxGTK":"mesa":"libX11":extraLibs }+ | pname == "xmonad" = deriv { extraLibs = delete "libmpd" extraLibs }+ | pname == "xmonad-extras" = deriv { buildDepends = delete "libmpd" buildDepends }+ | otherwise = deriv
− src/Distribution/NixOS/Derivation/Cabal.hs
@@ -1,106 +0,0 @@-{-# 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
@@ -1,54 +0,0 @@-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
@@ -1,39 +0,0 @@-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
@@ -1,47 +0,0 @@-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
@@ -11,12 +11,13 @@ import Control.Exception ( bracket ) import Text.Regex.Posix import Data.Version-import Text.ParserCombinators.ReadP ( readP_to_S ) import Distribution.PackageDescription.Parse ( parsePackageDescription, ParseResult(..) )+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 @@ -65,24 +66,19 @@ return pkg discoverNixFiles :: (FilePath -> Hackage4Nix ()) -> FilePath -> Hackage4Nix ()-discoverNixFiles yield dirOrFile- | "." `isPrefixOf` takeFileName dirOrFile = return ()- | otherwise = do- isFile <- io (doesFileExist dirOrFile)- case (isFile, takeExtension dirOrFile) of- (True,".nix") -> yield dirOrFile- (True,_) -> return ()- (False,_) -> io (readDirectory dirOrFile) >>= mapM_ (discoverNixFiles yield . (dirOrFile </>))+discoverNixFiles yield dirOrFile = do+ isFile <- io (doesFileExist dirOrFile)+ case (isFile, takeExtension dirOrFile) of+ (True,".nix") -> yield dirOrFile+ (True,_) -> return ()+ (False,_) -> io (readDirectory dirOrFile) >>= mapM_ (discoverNixFiles yield . (dirOrFile </>)) regenerateDerivation :: Derivation -> String -> Bool-regenerateDerivation deriv buf = not (display (pname deriv) `elem` patchedPackages) &&- not (buf =~ "preConfigure|configureFlags|postInstall|patchPhase")+regenerateDerivation deriv buf = not (pname deriv `elem` patchedPackages) &&+ not (buf =~ "(pre|post)Configure|configureFlags|(pre|post)Install|patchPhase") readVersion :: String -> Version-readVersion str =- case [ v | (v,[]) <- readP_to_S parseVersion str ] of- [ v' ] -> v'- _ -> error ("invalid version specifier " ++ show str)+readVersion str = maybe (error $ "cannot parse version " ++ show str) id (simpleParse str) parseNixFile :: FilePath -> String -> Hackage4Nix (Maybe Pkg) parseNixFile path buf@@ -121,26 +117,23 @@ 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 ++ ["self.stdenv.lib.maintainers.andres","self.stdenv.lib.maintainers.simons"]))- plats'- | null plats && not (null maints) = ["self.ghc.meta.platforms"]- | otherwise = plats- pkg <- readCabalFile (display (pname deriv)) (display (version deriv))+ pkg <- readCabalFile (pname deriv) (display (version deriv)) let deriv' = (cabal2nix pkg) { sha256 = sha256 deriv, runHaddock = runHaddock deriv }- deriv'' = deriv' { metaSection = (metaSection deriv')- { maintainers = maints'+ meta = metaSection deriv'+ plats' = if null plats then platforms meta else plats+ deriv'' = deriv' { metaSection = meta+ { maintainers = maints ++ ["simons","andres"] , platforms = plats' } }- io $ writeFile path (show (disp deriv''))+ io $ writeFile path (show (disp (normalize (deriv'')))) pkgset <- gets (selectLatestVersions . _pkgset) updates' <- flip mapM (Set.elems pkgset) $ \pkg -> do let Pkg deriv _ _ = pkg- updates <- discoverUpdates (display (pname deriv)) (display (version deriv))+ updates <- discoverUpdates (pname deriv) (display (version deriv)) return (pkg,updates) let updates = [ u | u@(_,(_:_)) <- updates' ] when (not (null updates)) $ do@@ -148,7 +141,7 @@ flip mapM_ updates $ \(pkg,versions) -> do let Pkg deriv path regenerate = pkg msgInfo ""- msgInfo $ (display (pname deriv)) ++ "-" ++ (display (version deriv)) ++ ":"+ msgInfo $ (display (packageId deriv)) ++ ":" flip mapM_ versions $ \newVersion -> do let deriv' = deriv { version = readVersion newVersion } msgInfo $ " " ++ genCabal2NixCmdline (Pkg deriv' path regenerate)@@ -159,7 +152,7 @@ where meta = metaSection deriv opts = [cabal] ++ maints' ++ plats' ++ if runHaddock deriv then [] else ["--no-haddock"]- cabal = "cabal://" ++ display (pname deriv) ++ "-" ++ display (version deriv)+ cabal = "cabal://" ++ display (packageId deriv) maints' = [ "--maintainer=" ++ normalizeMaintainer m | m <- maintainers meta ] plats' | ["self.ghc.meta.platforms"] == platforms meta = []@@ -186,21 +179,22 @@ ] usage :: String- usage = usageInfo "Usage: hackage4nix [options] [dir-or-file ...]" options ++- "\n\- \The purpose of 'hackage4nix' is to keep all Haskell packages in our\n\- \repository packages up-to-date. It scans a checked-out copy of\n\- \Nixpkgs for expressions that use 'cabal.mkDerivation', and\n\- \re-generates them in-place with cabal2nix.\n\- \\n\- \Because we don't want to generate a barrage of HTTP requests during\n\- \that procedure, the tool expects a copy of the Hackage database\n\- \available at some local path, i.e. \"/dev/shm/hackage\" by default.\n\- \That directory can be set up as follows:\n\- \\n\- \ cabal update\n\- \ mkdir -p /dev/shm/hackage\n\- \ tar xf ~/.cabal/packages/hackage.haskell.org/00-index.tar -C /dev/shm/hackage\n"+ usage = usageInfo "Usage: hackage4nix [options] [dir-or-file ...]" options ++ unlines+ [ ""+ , "The purpose of 'hackage4nix' is to keep all Haskell packages in our"+ , "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 cmdlineError "" = hPutStrLn stderr usage >> exitFailure@@ -230,38 +224,6 @@ patchedPackages :: [String] patchedPackages =- [ "alex" -- undeclared dependencies- , "cairo" -- undeclared dependencies- , "citeproc-hs" -- undeclared dependencies- , "editline" -- undeclared dependencies- , "glade" -- undeclared dependencies- , "glib" -- undeclared dependencies- , "epic" -- undeclared dependencies- , "GLUT" -- undeclared dependencies- , "gtk" -- undeclared dependencies- , "gtksourceview2" -- undeclared dependencies- , "haddock" -- undeclared dependencies- , "haskell-src" -- undeclared dependencies- , "hmatrix" -- undeclared dependencies- , "hp2any-graph" -- undeclared dependencies- , "lhs2tex" -- undeclared dependencies- , "OpenAL" -- undeclared dependencies- , "OpenGL" -- undeclared dependencies- , "pango" -- undeclared dependencies- , "idris" -- undeclared dependencies- , "readline" -- undeclared dependencies- , "repa-examples" -- undeclared dependencies- , "scion" -- expects non-existent networkBytestring- , "SDL" -- undeclared dependencies- , "SDL-image" -- undeclared dependencies- , "SDL-mixer" -- undeclared dependencies- , "SDL-ttf" -- undeclared dependencies- , "svgcairo" -- undeclared dependencies- , "terminfo" -- undeclared dependencies- , "xmonad" -- undeclared dependencies- , "xmonad-extras" -- undeclared dependencies- , "vacuum" -- undeclared dependencies- , "wxcore" -- undeclared dependencies- , "X11" -- undeclared dependencies- , "X11-xft" -- undeclared dependencies+ [ "X11" -- expression uses function arguments to determine feature set+ , "xmonad-extras" -- the generated expression doesn't build, don't know why ]
+ src/PackageList.hs view
@@ -0,0 +1,73 @@+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)