@@ -1,148 +0,0 @@
1−-- cabal2nix.hs
2−--
3−-- Copyright (c) 20011 Peter Simons <simons@cryp.to>
4−-- See LICENSE file for licensing details.
5−
6−module Main ( main ) where
7−
8−import System.IO
9−import System.Environment
10−import Control.Exception
11−import System.Exit
12−import Distribution.PackageDescription.Parse
13−import Distribution.PackageDescription
14−import Distribution.Package
15−import Distribution.License
16−import Data.Version
17−import Data.List
18−import Control.Monad
19−import Data.Char
20−import Network.HTTP
21−import System.Process
22−
23−type PkgName = String
24−type PkgVersion = [Int]
25−type PkgSHA256 = String
26−type PkgURL = String
27−type PkgDescription = String
28−type PkgLicense = License
29−type PkgDependencies = [CondTree ConfVar [Dependency] ()]
30−type PkgExtraLibs = [String]
31−
32−data Pkg = Pkg PkgName PkgVersion PkgSHA256 PkgURL PkgDescription PkgLicense PkgDependencies PkgExtraLibs
33− deriving (Show)
34−
35−toNixName :: String -> String
36−toNixName [] = error "toNixName: empty string is not a valid argument"
37−toNixName "Cabal" = "cabal"
38−toNixName name = f name
39− where
40− f [] = []
41− f ('-':c:cs) | c `notElem` "-" = toUpper c : f cs
42− f ('-':_) = error ("unexpected package name " ++ show name)
43− f (c:cs) = c : f cs
44−
45−toNix :: Pkg -> String
46−toNix (Pkg name ver sha256 url desc lic deps libs) =
47− "{" ++ exprArgs ++"}:\n\n"
48− ++ "cabal.mkDerivation (self : {\n"
49− ++ " pname = " ++ show name ++ ";\n"
50− ++ " version = \"" ++ showVer ++ "\";\n"
51− ++ " sha256 = " ++ show sha256 ++ ";\n"
52− ++ " propagatedBuildInputs = [" ++ depList ++ "];\n"
53− ++ " meta = {\n"
54− ++ " homepage = \"" ++ url ++ "\";\n"
55− ++ " description = " ++ show desc ++ ";\n"
56− ++ " license = " ++ showLic lic ++ ";\n"
57− ++ " };\n"
58− ++ "})\n"
59− where
60− exprArgs = concat (intersperse "," ("cabal":pkgDeps))
61− showVer = concat (intersperse "." (map show ver))
62− depList = concat (intersperse " " pkgDeps)
63− pkgDeps :: [String]
64− pkgDeps = filter (/="cabal") $ nub $ sort $ map toNixName $
65− libs ++ [ n | dep <- deps, Dependency (PackageName n) _ <- condTreeConstraints dep
66− , n `notElem` ["base","containers"]
67− ]
68− showLic (GPL Nothing) = show "GPL"
69− showLic (GPL (Just (Version [2] []))) = "self.stdenv.lib.licenses.gpl2"
70− showLic (GPL (Just (Version [3] []))) = "self.stdenv.lib.licenses.gpl3"
71− showLic (LGPL Nothing) = show "LGPL"
72− showLic (LGPL (Just (Version [2,1] []))) = "self.stdenv.lib.licenses.lgpl21"
73− showLic (LGPL (Just (Version [3] []))) = "self.stdenv.lib.licenses.lgpl3"
74− showLic BSD3 = "self.stdenv.lib.licenses.bsd3"
75− showLic BSD4 = "self.stdenv.lib.licenses.bsd4"
76− showLic MIT = "self.stdenv.lib.licenses.mit"
77− showLic PublicDomain = "self.stdenv.lib.licenses.publicDomain"
78− showLic AllRightsReserved = "unknown"
79− showLic OtherLicense = "unknown"
80− showLic l = error $ "unknown license: " ++ show l
81−
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 ]
96−
97−simplify :: CondTree ConfVar [Dependency] a -> CondTree ConfVar [Dependency] ()
98−simplify (CondNode _ deps nodes) = CondNode () deps (map simp nodes)
99− where
100− simp (cond,tree,mtree) = (cond, simplify tree, maybe Nothing (Just . simplify) mtree)
101−
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 = do
110− hash <- readProcess "bash" ["-c", "exec nix-prefetch-url 2>/dev/tty " ++ url] ""
111− return (reverse (dropWhile (=='\n') (reverse hash)))
112−
113− where
114− url = "http://hackage.haskell.org/packages/archive/" ++ name ++ "/" ++ version ++ "/" ++ name ++ "-" ++ version ++ ".tar.gz"
115− PackageIdentifier (PackageName name) version' = package (packageDescription pkg)
116− version = showVersion version'
117−
118−main :: IO ()
119−main = bracket (return ()) (\() -> hFlush stdout >> hFlush stderr) $ \() -> do
120− args <- getArgs
121−
122− let usage = "Usage: cabal2nix url-to-cabal-file [sha256-hash]"
123−
124− when (length args < 1 || length args > 2) $ do
125− mapM_ (hPutStrLn stderr) [ "*** invalid command line syntax"
126− , usage
127− ]
128− exitFailure
129−
130− when ("--help" `elem` args || "-h" `elem` args) $ do
131− putStrLn usage
132− exitFailure
133−
134− cabal' <- fmap parsePackageDescription (readCabalFile (head args))
135− cabal <- case cabal' of
136− ParseOk _ a -> return a
137− ParseFailed err -> do
138− hPutStrLn stderr ("*** cannot parse cabal file: " ++ show err)
139− exitFailure
140−
141− sha256 <- case args of
142− _:hash:[] -> return hash
143− _ -> hashPackage cabal
144−
145− let pkg = cabal2nix cabal sha256
146− putStr (toNix pkg)
147−
148−