git.iko.soy/typeable/cabal2nix
on de9c596 help sign in
typeable/cabal2nix/src/PackageList.hs
73 lines 3.4 kB history raw
1module Main ( main ) where
3import Control.Exception ( assert )
4import Control.Monad ( when, filterM )
5import Data.Char ( toLower )
6import Data.List ( nubBy, sortBy )
7import Data.Ord ( comparing )
8import Data.Version ( Version(..) )
9import Distribution.Package ( PackageIdentifier(..), PackageName(..) )
10import Distribution.Text ( simpleParse, display )
11import System.Directory ( doesDirectoryExist, doesFileExist )
12import System.FilePath ( (</>), (<.>) )
13import System.Process ( readProcess )
14import Text.Regex.Posix ( (=~), match, makeRegexOpts, compExtended, execBlank )
16type Pkg = (String,Version,String) -- (Name, Version, Attribute)
17type Pkgset = [Pkg]
19comparePkgByVersion :: Pkg -> Pkg -> Ordering -- prefers the latest version
20comparePkgByVersion (n1,v1,a1) (n2,v2,a2)
21 | a1 == a2 = assert (n1 == n2) (compare v2 v1)
22 | otherwise = compare a2 a1
24comparePkgByName :: Pkg -> Pkg-> Ordering
25comparePkgByName (n1,_,_) (n2,_,_) = comparing (map toLower) n1 n2
27parseHaskellPackageName :: String -> Maybe Pkg
28parseHaskellPackageName name =
29 case name `regsubmatch` "^(haskellPackages[^ \t]+)[ \t]+(.+)$" of
30 [attr,name'] -> case name' `regsubmatch` "^haskell-(.+)-ghc[0-9.]+-(.+)$" of
31 [name'',version] -> case simpleParse version of
32 Just version' -> Just (name'',version',attr)
33 _ -> error ("cannot parse " ++ show name)
34 _ -> case simpleParse name' of
35 Just (PackageIdentifier (PackageName n) v) -> Just (n,v,attr)
36 _ -> error ("cannot parse " ++ show name)
37 _ -> Nothing
39getHaskellPackageList :: IO Pkgset
40getHaskellPackageList = do
41 allPkgs <- fmap lines (readProcess "bash" ["-c", "exec nix-env -qaP \\* 2>/dev/tty"] "")
42 return [ p | Just p <- map parseHaskellPackageName allPkgs ]
44stripProfilingVersions :: Pkgset -> Pkgset
45stripProfilingVersions pkgs = [ p | p@(_,_,attr) <- pkgs , not (attr =~ "ghc[0-9.]+_profiling") ]
47stripGhc721Versions :: Pkgset -> Pkgset
48stripGhc721Versions pkgs = [ p | p@(_,_,attr) <- pkgs , not (attr =~ "ghc721") ]
50selectLatestVersions :: Pkgset -> Pkgset
51selectLatestVersions = nubBy (\x y -> comparePkgByName x y == EQ) . sortBy comparePkgByVersion
53isHackagePackage :: Pkg -> IO Bool
54isHackagePackage (name,version,_) = doesFileExist path
55 where path = "/dev/shm/hackage/" </> name </> display version </> name <.> "cabal"
57formatPackageLine :: Pkg -> String
58formatPackageLine (name,version,attr) = show (name, display version, Just url)
59 where
60 url = "http://hydra.nixos.org/job/nixpkgs/trunk/" ++ attr
62regsubmatch :: String -> String -> [String]
63regsubmatch buf patt = let (_,_,_,x) = f in x
64 where f :: (String,String,String,[String])
65 f = match (makeRegexOpts compExtended execBlank patt) buf
67main :: IO ()
68main = do
69 haveHackage <- doesDirectoryExist "/dev/shm/hackage"
70 when (not haveHackage) (fail "cannot find hackage database at /dev/shm/hackage")
71 pkgset' <- fmap (selectLatestVersions . stripGhc721Versions . stripProfilingVersions) getHaskellPackageList
72 pkgset <- filterM isHackagePackage pkgset'
73 mapM_ (putStrLn . formatPackageLine) (sortBy comparePkgByName pkgset)