3
3
{-# LANGUAGE OverloadedStrings #-}
4
4
module Main where
5
5
6
- import Data.Foldable (toList )
7
- import System.Environment (getArgs )
6
+ import System.Environment (getArgs ,lookupEnv )
7
+ import Data.Maybe (fromMaybe )
8
+
9
+ import Distribution.Text (disp )
8
10
9
11
import Data.Yaml (decodeFileEither )
10
12
13
+ import Data.Text (Text )
14
+ import qualified Data.Text as Text
15
+
11
16
import Nix.Pretty (prettyNix )
12
17
import Nix.Expr
13
18
14
19
import Data.Aeson
15
20
import qualified Data.HashMap.Strict as Map
21
+ import qualified Data.Vector as V
16
22
import Lens.Micro
17
23
import Lens.Micro.Aeson
18
24
19
25
import Cabal2Nix.Plan
20
26
27
+ import Stack2nix.Stack (parsePackageIdentifier )
28
+ import Distribution.Types.PackageId
29
+
30
+ type CompilerPackages = Map. HashMap Text (Map. HashMap Text Text )
31
+
21
32
main :: IO ()
22
33
main = getArgs >>= \ case
23
34
[file] -> do
@@ -26,34 +37,42 @@ main = getArgs >>= \case
26
37
27
38
ltsPackages :: FilePath -> IO NExpr
28
39
ltsPackages lts = do
40
+ -- use yaml here, so we don't have to deal with yaml AND json.
41
+ -- pull it from https://raw.githubusercontent.com/commercialhaskell/stackage-content/master/stack/global-hints.yaml
42
+ cpYaml <- fromMaybe " ./global-hints.yaml" <$> lookupEnv " GLOBAL_HINTS"
43
+ compilerPackages <- decodeFileEither cpYaml >>= \ case
44
+ Left e -> error $ " Parsing " ++ show cpYaml ++ " : " ++ show e
45
+ Right value -> pure value
29
46
evalue <- decodeFileEither lts
30
47
case evalue of
31
- Left e -> error (show e)
32
- Right value -> pure $ plan2nix $ lts2plan value
33
-
34
- lts2plan :: Value -> Plan
35
- lts2plan lts = Plan { packages , compilerVersion , compilerPackages }
36
- where
37
- packages = mappend compilerPackages' $ fmap Just $ lts ^. key " packages" . _Object <&> \ v -> Package
38
- { packageVersion = v ^. key " version" . _String
39
- , packageRevision = v ^? key " cabal-file-info" . key " hashes" . key " SHA256" . _String
40
- , packageFlags = Map. mapMaybe (^? _Bool) $ v ^. key " constraints" . key " flags" . _Object
41
- }
42
- compilerVersion = lts ^. key " system-info" . key " ghc-version" . _String
43
- compilerPackages =
44
- (lts ^. key " system-info" . key " core-packages" . _Object <&> (Just . (^. _String)))
45
- <> Map. fromList
46
- [ (p, Nothing ) -- core-executables is just a list of
47
- -- exe names shipped with GHC, which
48
- -- lots of packages depend on
49
- -- (e.g. hsc2hs)
50
- | p <- toList $ lts ^. key " system-info" . key " core-executables" . _Array <&> (^. _String)
51
- ]
52
- compilerPackages' = fmap
53
- (fmap $ \ v -> Package
54
- { packageVersion = v
55
- , packageRevision = Nothing
56
- , packageFlags = Map. empty
57
- }
58
- )
59
- compilerPackages
48
+ Left e -> error $ " Parsing " ++ show lts ++ " : " ++ show e
49
+ Right value -> pure $ plan2nix $ lts2plan compilerPackages value
50
+
51
+ -- pretty crude hack to get the compiler version. Assuming ghc-X.Y.Z
52
+ parseCompilerVersion :: Text -> Text
53
+ parseCompilerVersion c
54
+ | " ghc-" `Text.isPrefixOf` c = Text. drop 4 c
55
+ | otherwise = error $ " Unable to parse version from compiler: " ++ Text. unpack c
56
+
57
+ lts2plan :: CompilerPackages -> Value -> Plan
58
+ lts2plan compilerPackagesMap lts = Plan { packages, compilerVersion, compilerPackages }
59
+ where
60
+ compilerName = lts ^. key " resolver" . key " compiler" . _String
61
+ compilerVersion = parseCompilerVersion compilerName
62
+ compilerPackages = Just <$> Map. lookupDefault (error $ " failed to lookup the compiler packages for compiler: " ++ Text. unpack compilerName) compilerName compilerPackagesMap
63
+
64
+ -- turn flags into HashMap Text (HashMap Text Bool)
65
+ flags :: Map. HashMap Text (Map. HashMap Text Bool )
66
+ flags = lts ^. key " flags" . _Object <&> (\ v -> Map. mapMaybe (^? _Bool) $ v ^. _Object)
67
+ packages = Map. fromList . V. toList $ lts ^. key " packages" . _Array <&> \ v ->
68
+ let (pkg, rev) = case (parsePackageIdentifier . Text. unpack $ v ^. key " hackage" . _String) of
69
+ Just p -> p
70
+ _ -> error $ " failed to parse: " ++ Text. unpack (v ^. key " hackage" . _String)
71
+ name = Text. pack (show (disp (pkgName pkg)))
72
+ in (name, Just $ Package
73
+ { packageVersion = Text. pack (show (disp (pkgVersion pkg)))
74
+ , packageRevision = case rev of
75
+ Just (Left sha) -> Just $ Text. pack sha
76
+ _ -> Nothing
77
+ , packageFlags = Map. lookupDefault Map. empty name flags
78
+ })
0 commit comments