1
1
{-# LANGUAGE OverloadedStrings #-}
2
2
{-# LANGUAGE NamedFieldPuns #-}
3
+ {-# LANGUAGE LambdaCase #-}
3
4
4
5
module Main where
5
6
6
7
import Cabal2Nix
8
+ import Cabal2Nix.Util ( quoted )
7
9
import Control.Applicative ( liftA2 )
8
10
import Control.Monad.Trans.State.Strict
9
11
import Crypto.Hash.SHA256 ( hash )
10
- import Data.Aeson
11
- import Data.Aeson.Types ( Pair )
12
- import Data.Aeson.Encode.Pretty
13
12
import qualified Data.ByteString.Base16 as Base16
14
13
import qualified Data.ByteString.Char8 as BS
15
- import qualified Data.ByteString.Lazy as BL
16
14
import Data.Foldable ( toList
17
15
, for_
18
16
)
@@ -25,6 +23,7 @@ import qualified Data.Sequence as Seq
25
23
import Data.String ( IsString (fromString )
26
24
)
27
25
import Data.Text ( Text )
26
+ import qualified Data.Text as T ( pack )
28
27
import Data.Text.Encoding ( decodeUtf8 )
29
28
import Distribution.Hackage.DB ( hackageTarball )
30
29
import qualified Distribution.Hackage.DB.Parsed
@@ -36,13 +35,30 @@ import Distribution.Pretty ( prettyShow
36
35
)
37
36
import Distribution.Types.PackageName ( PackageName )
38
37
import Distribution.Types.Version ( Version )
38
+ import Nix ( (@@)
39
+ , mkSym
40
+ , mkInt
41
+ , mkStr
42
+ , NExpr
43
+ , ($=)
44
+ , mkNonRecSet
45
+ )
39
46
import Nix.Pretty ( prettyNix )
40
47
import System.Directory ( createDirectoryIfMissing
41
48
)
42
49
import System.Environment ( getArgs )
43
50
import System.FilePath ( (</>)
44
51
, (<.>)
45
52
)
53
+ import Data.Char (isUpper )
54
+
55
+ -- Avoid issues with case insensitive file systems by escaping upper case
56
+ -- characters with a leading _ character.
57
+ escapeUpperCase :: String -> String
58
+ escapeUpperCase = (>>= (\ case
59
+ ' _' -> " __"
60
+ c | isUpper c -> [' _' , c]
61
+ | otherwise -> [c]))
46
62
47
63
main :: IO ()
48
64
main = do
@@ -53,23 +69,25 @@ main = do
53
69
54
70
db <- U. readTarball Nothing inp
55
71
56
- let (defaultJson , cabalFiles) =
57
- runState (fmap (object . toList . (Seq. sortOn fst )) $ foldMapWithKeyA package2json db) mempty
72
+ let (nixFiles , cabalFiles) =
73
+ runState (fmap (toList . (Seq. sortOn fst )) $ foldMapWithKeyA package2nix db) mempty
58
74
createDirectoryIfMissing False out
59
- BL. writeFile (out </> " default.nix" ) $
75
+ writeFile (out </> " default.nix" ) $
60
76
" with builtins; mapAttrs (_: mapAttrs (_: data: rec {\n \
61
77
\ inherit (data) sha256;\n \
62
- \ revisions = (mapAttrs (rev: rdata: {\n \
63
- \ inherit (rdata) revNum sha256;\n \
64
- \ outPath = ./. + \" /hackage/${rdata.outPath}\" ;\n \
65
- \ }) data.revisions) // {\n \
78
+ \ revisions = data.revisions // {\n \
66
79
\ default = revisions.\" ${data.revisions.default}\" ;\n \
67
80
\ };\n \
68
- \})) (fromJSON (readFile ./hackage.json))\n "
81
+ \})) {\n "
82
+ -- Import all the per package nix files
83
+ <> mconcat (map (\ (pname, _) ->
84
+ " " <> quoted pname <> " = import ./nix/" <> escapeUpperCase pname <> " .nix;\n " ) nixFiles)
85
+ <> " }\n "
86
+
87
+ createDirectoryIfMissing False (out </> " nix" )
88
+ for_ nixFiles $ \ (pname, nix) ->
89
+ writeFile (out </> " nix" </> escapeUpperCase pname <.> " nix" ) $ show $ prettyNix nix
69
90
70
- BL. writeFile (out </> " hackage.json" ) $ encodePretty'
71
- (defConfig {confCompare = compare , confIndent = Spaces 1 })
72
- defaultJson
73
91
createDirectoryIfMissing False (out </> " hackage" )
74
92
75
93
for_ cabalFiles $ \ (cabalFile, pname, path) -> do
@@ -93,32 +111,32 @@ foldMapWithKeyA f =
93
111
fromPretty :: (Pretty a , IsString b ) => a -> b
94
112
fromPretty = fromString . prettyShow
95
113
96
- package2json :: PackageName -> U. PackageData -> GPDWriter (Seq Pair )
97
- package2json pname (U. PackageData { U. versions }) = do
98
- versionBindings <- foldMapWithKeyA (version2json pname) versions
99
- return $ Seq. singleton $ fromPretty pname .= (object . toList $ Seq. sortOn fst $ versionBindings)
114
+ package2nix :: PackageName -> U. PackageData -> GPDWriter (Seq ( String , NExpr ) )
115
+ package2nix pname (U. PackageData { U. versions }) = do
116
+ versionBindings <- foldMapWithKeyA (version2nix pname) versions
117
+ return $ Seq. singleton ( fromPretty pname, (mkNonRecSet . map ( uncurry ($=) ) . toList $ Seq. sortOn fst $ versionBindings) )
100
118
101
- version2json
102
- :: PackageName -> Version -> U. VersionData -> GPDWriter (Seq (Pair ))
103
- version2json pname vnum (U. VersionData { U. cabalFileRevisions, U. metaFile }) =
119
+ version2nix
120
+ :: PackageName -> Version -> U. VersionData -> GPDWriter (Seq (Text , NExpr ))
121
+ version2nix pname vnum (U. VersionData { U. cabalFileRevisions, U. metaFile }) =
104
122
do
105
123
revisionBindings <- sequenceA
106
124
$ zipWith (revBindingJson pname vnum) cabalFileRevisions [0 .. ]
107
125
let hash = decodeUtf8 $ fromString $ P. parseMetaData pname vnum metaFile Map. ! " sha256"
108
- return $ Seq. singleton $ fromPretty vnum .= object
109
- [ " sha256" .= hash
110
- , " revisions" .= object
111
- ( revisionBindings
112
- ++ [" default" .= fst (last revisionBindings)]
126
+ return $ Seq. singleton (quoted ( fromPretty vnum), mkNonRecSet
127
+ [ " sha256" $= mkStr hash
128
+ , " revisions" $= mkNonRecSet
129
+ ( map ( uncurry ($=) ) revisionBindings
130
+ ++ [" default" $= mkStr ( fst (last revisionBindings) )]
113
131
)
114
- ]
132
+ ])
115
133
116
134
revBindingJson
117
135
:: PackageName
118
136
-> Version
119
137
-> BS. ByteString
120
138
-> Integer
121
- -> GPDWriter (Key , Value )
139
+ -> GPDWriter (Text , NExpr )
122
140
revBindingJson pname vnum cabalFile revNum = do
123
141
let qualifiedName = mconcat $ intersperse
124
142
" -"
@@ -130,8 +148,8 @@ revBindingJson pname vnum cabalFile revNum = do
130
148
cabalHash = Base16. encode $ hash cabalFile
131
149
modify' $ mappend $ Seq. singleton
132
150
(cabalFile, prettyPname ++ " .cabal" , revPath)
133
- return $ revName .= object
134
- [ " outPath " .= ( qualifiedName <> " .nix" )
135
- , " revNum" .= revNum
136
- , " sha256" .= decodeUtf8 cabalHash
137
- ]
151
+ return ( revName, mkNonRecSet
152
+ [ " nix " $= mkSym " import " @@ mkSym ( T. pack ( " ../hackage/ " <> qualifiedName <> " .nix" ) )
153
+ , " revNum" $= mkInt revNum
154
+ , " sha256" $= mkStr ( decodeUtf8 cabalHash)
155
+ ])
0 commit comments