@@ -0,0 +1,96 @@
1+module Distribution.NixOS.Derivation.Cabal where
2+
3+import Distribution.NixOS.Derivation.PrettyPrinting
4+import Distribution.NixOS.Derivation.Meta
5+import Distribution.NixOS.Derivation.License
6+import Distribution.Package
7+import Distribution.Text
8+import Data.Version
9+import Data.List
10+import Text.PrettyPrint
11+import Text.ParserCombinators.ReadP ( readP_to_S )
12+import Text.Regex.Posix
13+
14+data Derivation = MkDerivation
15+ { pname :: PackageName
16+ , version :: Version
17+ , sha256 :: String
18+ , isLibrary :: Bool
19+ , isExecutable :: Bool
20+ , buildDepends :: [String]
21+ , buildTools :: [String]
22+ , extraLibs :: [String]
23+ , pkgConfDeps :: [String]
24+ , runHaddock :: Bool
25+ , metaSection :: Meta
26+ }
27+ deriving (Show, Eq, Ord)
28+
29+instance Text Derivation where
30+ disp = renderDerivation
31+ parse = error "parsing Distribution.NixOS.Derivation.Cabal.Derivation is not supported yet"
32+
33+renderDerivation :: Derivation -> Doc
34+renderDerivation deriv = funargs (map text ("cabal" : inputs)) $$ vcat
35+ [ text ""
36+ , text "cabal.mkDerivation" <+> lparen <> text "self" <> colon <+> lbrace
37+ , nest 2 $ vcat
38+ [ attr "pname" $ doubleQuotes (disp (pname deriv))
39+ , attr "version" $ doubleQuotes (disp (version deriv))
40+ , attr "sha256" $ string (sha256 deriv)
41+ , boolattr "isLibrary" (not (isLibrary deriv) || (isExecutable deriv)) (isLibrary deriv)
42+ , boolattr "isExecutable" (not (isLibrary deriv) || (isExecutable deriv)) (isExecutable deriv)
43+ , listattr "buildDepends" (buildDepends deriv)
44+ , listattr "buildTools" (buildTools deriv)
45+ , listattr "extraLibraries" (extraLibs deriv)
46+ , listattr "pkgconfigDepends" (pkgConfDeps deriv)
47+ , boolattr "noHaddock" (not (runHaddock deriv)) (not (runHaddock deriv))
48+ , disp (metaSection deriv)
49+ ]
50+ , rbrace <> rparen
51+ , text ""
52+ ]
53+ where
54+ inputs = nub $ sort $ filter (/="cabal") $ buildDepends deriv ++ buildTools deriv ++ extraLibs deriv ++ pkgConfDeps deriv
55+
56+parseDerivation :: String -> Maybe Derivation
57+parseDerivation buf
58+ | buf =~ "cabal.mkDerivation"
59+ , [name] <- buf `regsubmatch` "pname *= *\"([^\"]+)\""
60+ , [vers] <- buf `regsubmatch` "version *= *\"([^\"]+)\""
61+ , [sha] <- buf `regsubmatch` "sha256 *= *\"([^\"]+)\""
62+ , plats <- buf `regsubmatch` "platforms *= *([^;]+);"
63+ , maint <- buf `regsubmatch` "maintainers *= *\\[([^\"]+)]"
64+ , noHaddock <- buf `regsubmatch` "noHaddock *= *(true|false) *;"
65+ = Just $ MkDerivation
66+ { pname = PackageName name
67+ , version = readVersion vers
68+ , sha256 = sha
69+ , isLibrary = False
70+ , isExecutable = False
71+ , buildDepends = []
72+ , buildTools = []
73+ , extraLibs = []
74+ , pkgConfDeps = []
75+ , runHaddock = case noHaddock of "true":[] -> False
76+ _ -> True
77+ , metaSection = Meta
78+ { homepage = ""
79+ , description = ""
80+ , license = Unknown Nothing
81+ , maintainers = concatMap words maint
82+ , platforms = concatMap words (map (map (\c -> if c == '+' then ' ' else c)) plats)
83+ }
84+ }
85+ | otherwise = Nothing
86+
87+regsubmatch :: String -> String -> [String]
88+regsubmatch buf patt = let (_,_,_,x) = f in x
89+ where f :: (String,String,String,[String])
90+ f = match (makeRegexOpts compExtended execBlank patt) buf
91+
92+readVersion :: String -> Version
93+readVersion str =
94+ case [ v | (v,[]) <- readP_to_S parseVersion str ] of
95+ [ v' ] -> v'
96+ _ -> error ("invalid version specifier " ++ show str)