@@ -18,6 +18,8 @@ import Data.Version
1818import Data.List
1919import Control.Monad
2020import Data.Char
21+import Network.HTTP
22+import System.Process
2123
2224type PkgName = String
2325type PkgVersion = [Int]
@@ -77,38 +79,67 @@ toNix (Pkg name ver sha256 url desc lic deps libs) =
7779 showLic OtherLicense = "unknown"
7880 showLic l = error $ "unknown license: " ++ show l
7981
80−readPackage :: FilePath -> String -> IO Pkg
81−readPackage cabalFile sha256 = do
82− cabal <- readPackageDescription silent cabalFile
83− let pkg = packageDescription cabal
84− PackageName pkgname = pkgName (package pkg)
85− pkgver = versionBranch (pkgVersion (package pkg))
86− lic = license pkg
87− url = homepage pkg
88− desc = synopsis pkg
89− -- globalDeps = buildDepends pkg
90− libDeps = maybe [] (\x -> [x]) (condLibrary cabal)
91− exeDeps = [ tree | (_,tree) <- condExecutables cabal ]
92− libs = concat [ extraLibs (libBuildInfo (condTreeData x)) | x <- libDeps ]
93− libs' = concat [ extraLibs (buildInfo (condTreeData x)) | x <- exeDeps ]
94− return (Pkg pkgname pkgver sha256 url desc lic (map simplify libDeps ++ map simplify exeDeps) (libs++libs'))
95− where
82+cabal2nix :: GenericPackageDescription -> PkgSHA256 -> Pkg
83+cabal2nix cabal sha256 = Pkg pkgname pkgver sha256 url desc lic (map simplify libDeps ++ map simplify exeDeps) (libs++libs')
84+ where
85+ pkg = packageDescription cabal
86+ PackageName pkgname = pkgName (package pkg)
87+ pkgver = versionBranch (pkgVersion (package pkg))
88+ lic = license pkg
89+ url = homepage pkg
90+ desc = synopsis pkg
91+ -- globalDeps = buildDepends pkg
92+ libDeps = maybe [] (\x -> [x]) (condLibrary cabal)
93+ exeDeps = [ tree | (_,tree) <- condExecutables cabal ]
94+ libs = concat [ extraLibs (libBuildInfo (condTreeData x)) | x <- libDeps ]
95+ libs' = concat [ extraLibs (buildInfo (condTreeData x)) | x <- exeDeps ]
9696
9797simplify :: CondTree ConfVar [Dependency] a -> CondTree ConfVar [Dependency] ()
9898simplify (CondNode _ deps nodes) = CondNode () deps (map simp nodes)
9999 where
100100 simp (cond,tree,mtree) = (cond, simplify tree, maybe Nothing (Just . simplify) mtree)
101101
102+readCabalFile :: FilePath -> IO String
103+readCabalFile path
104+ | "http://" `isPrefixOf` path = Network.HTTP.simpleHTTP (getRequest path) >>= getResponseBody
105+ | "file://" `isPrefixOf` path = readCabalFile (drop 7 path)
106+ | otherwise = readFile path
107+
108+hashPackage :: GenericPackageDescription -> IO String
109+hashPackage pkg = readProcess "bash" ["-c", "exec nix-prefetch-url 2>/dev/tty " ++ url] ""
110+ where
111+ url = "http://hackage.haskell.org/packages/archive/" ++ name ++ "/" ++ version ++ "/" ++ name ++ "-" ++ version ++ ".tar.gz"
112+ PackageIdentifier (PackageName name) version' = package (packageDescription pkg)
113+ version = showVersion version'
114+
102115main :: IO ()
103116main = bracket (return ()) (\() -> hFlush stdout >> hFlush stderr) $ \() -> do
104117 args <- getArgs
105118
106− when (length args /= 2) $ do
119+ let usage = "Usage: cabal2nix url-to-cabal-file [sha256-hash]"
120+
121+ when (length args < 1 || length args > 2) $ do
107122 mapM_ (hPutStrLn stderr) [ "*** invalid command line syntax"
108− , "Usage: cabal2nix cabal-file sha256-hash"
123+ , usage
109124 ]
110125 exitFailure
111126
112− let cabalFile:sha256:[] = args
113− pkg <- readPackage cabalFile sha256
127+ when ("--help" `elem` args || "-h" `elem` args) $ do
128+ putStrLn usage
129+ exitFailure
130+
131+ cabal' <- fmap parsePackageDescription (readCabalFile (head args))
132+ cabal <- case cabal' of
133+ ParseOk _ a -> return a
134+ ParseFailed err -> do
135+ hPutStrLn stderr ("*** cannot parse cabal file: " ++ show err)
136+ exitFailure
137+
138+ sha256 <- case args of
139+ _:hash:[] -> return hash
140+ _:[] -> hashPackage cabal
141+
142+ let pkg = cabal2nix cabal sha256
114143 putStr (toNix pkg)
144+
145+