git.iko.soy/typeable/stackage2nix
on master help sign in
Add: deriveJSON
34abc9eDmitry Bushev
src/Distribution/Nixpkgs/Haskell/Stack.hs+17−11
@@ -1,5 +1,6 @@
1+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
1{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE LambdaCase #-}
2−{-# LANGUAGE OverloadedStrings, GeneralizedNewtypeDeriving #-}
3+{-# LANGUAGE OverloadedStrings #-}
3{-# LANGUAGE RecordWildCards #-}
4{-# LANGUAGE RecordWildCards #-}
4{-# LANGUAGE TemplateHaskell #-}
5{-# LANGUAGE TemplateHaskell #-}
5
6
@@ -7,14 +8,15 @@ module Distribution.Nixpkgs.Haskell.Stack where
7
8
8import Control.Lens
9import Control.Lens
9import Data.Text as T
10import Data.Text as T
10−import Distribution.System as System
11import Distribution.Compiler as Compiler
11import Distribution.Compiler as Compiler
12−import Distribution.PackageDescription as PackageDescription
13import Distribution.Nixpkgs.Fetch
12import Distribution.Nixpkgs.Fetch
14import Distribution.Nixpkgs.Haskell.Derivation
13import Distribution.Nixpkgs.Haskell.Derivation
15import Distribution.Nixpkgs.Haskell.FromCabal as FromCabal
14import Distribution.Nixpkgs.Haskell.FromCabal as FromCabal
16import Distribution.Nixpkgs.Haskell.PackageSourceSpec as PackageSourceSpec
15import Distribution.Nixpkgs.Haskell.PackageSourceSpec as PackageSourceSpec
16+import Distribution.PackageDescription as PackageDescription
17+import Distribution.System as System
17−import Language.Nix
18+import Language.Nix as Nix
19+import Network.URI as URI
18import Stack.Config
20import Stack.Config
19
21
20newtype HackageDb = HackageDb { fromHackageDB :: T.Text }
22newtype HackageDb = HackageDb { fromHackageDB :: T.Text }
@@ -38,7 +40,7 @@ makeLenses ''PackageConfig
38mkPackageConfig :: Platform -> CompilerId -> PackageConfig
40mkPackageConfig :: Platform -> CompilerId -> PackageConfig
39mkPackageConfig platform compilerId = PackageConfig
41mkPackageConfig platform compilerId = PackageConfig
40 { _pcHaskellResolver = const True
42 { _pcHaskellResolver = const True
41− , _pcNixpkgsResolver = \i -> Just (binding # (i, path # [i]))
43+ , _pcNixpkgsResolver = \i -> Just (Nix.binding # (i, Nix.path # [i]))
42 , _pcTargetPlatform = platform
44 , _pcTargetPlatform = platform
43 , _pcTargetCompiler = unknownCompilerInfo compilerId NoAbiTag
45 , _pcTargetCompiler = unknownCompilerInfo compilerId NoAbiTag
44 , _pcFlagAssignment = []
46 , _pcFlagAssignment = []
@@ -51,22 +53,26 @@ getStackPackageFromDb
51getStackPackageFromDb optHackageDb stackPackage =
53getStackPackageFromDb optHackageDb stackPackage =
52 PackageSourceSpec.getPackage
54 PackageSourceSpec.getPackage
53 (unHackageDb <$> optHackageDb)
55 (unHackageDb <$> optHackageDb)
54− (stackLocationToSource $ stackPackage ^. spSource)
56+ (stackLocationToSource $ stackPackage ^. spLocation)
55
57
56−stackLocationToSource :: StackLocation -> Source
58+stackLocationToSource :: PackageLocation -> Source
57stackLocationToSource = \case
59stackLocationToSource = \case
58 HackagePackage p -> Source
60 HackagePackage p -> Source
59 { sourceUrl = "cabal://" ++ T.unpack p
61 { sourceUrl = "cabal://" ++ T.unpack p
60 , sourceRevision = mempty
62 , sourceRevision = mempty
61 , sourceHash = UnknownHash
63 , sourceHash = UnknownHash
62 , sourceCabalDir = mempty }
64 , sourceCabalDir = mempty }
63− StackPath p -> Source
65+ StackFilePath p -> Source
64− { sourceUrl = T.unpack p
66+ { sourceUrl = p
65 , sourceRevision = mempty
67 , sourceRevision = mempty
66 , sourceHash = UnknownHash
68 , sourceHash = UnknownHash
67 , sourceCabalDir = mempty }
69 , sourceCabalDir = mempty }
68−
70+ StackUri uri -> Source
71+ { sourceUrl = URI.uriToString id uri mempty
72+ , sourceRevision = mempty
73+ , sourceHash = UnknownHash
74+ , sourceCabalDir = mempty }
69− StackRepoGit rg -> Source
75+ StackRepoGit rg -> Source
70 { sourceUrl = T.unpack $ rg ^. rgUri
76 { sourceUrl = T.unpack $ rg ^. rgUri
71 , sourceRevision = T.unpack $ rg ^. rgCommit
77 , sourceRevision = T.unpack $ rg ^. rgCommit
72 , sourceHash = UnknownHash
78 , sourceHash = UnknownHash
src/Stack/Config.hs+16−11
@@ -1,6 +1,7 @@
1{-# LANGUAGE LambdaCase #-}
1{-# LANGUAGE LambdaCase #-}
2{-# LANGUAGE RecordWildCards #-}
2{-# LANGUAGE RecordWildCards #-}
3{-# LANGUAGE TemplateHaskell #-}
3{-# LANGUAGE TemplateHaskell #-}
4+{-# LANGUAGE ViewPatterns #-}
4
5
5module Stack.Config where
6module Stack.Config where
6
7
@@ -12,6 +13,7 @@ import Data.Maybe
12import Data.Text as T
13import Data.Text as T
13import Data.Yaml
14import Data.Yaml
14import Stack.Config.Yaml as Yaml
15import Stack.Config.Yaml as Yaml
16+import Network.URI
15
17
16newtype StackResolver = StackResolver { fromStackResolver :: Text }
18newtype StackResolver = StackResolver { fromStackResolver :: Text }
17 deriving (Eq, Ord, Show)
19 deriving (Eq, Ord, Show)
@@ -28,16 +30,17 @@ data RepoGit = RepoGit
28
30
29makeLenses ''RepoGit
31makeLenses ''RepoGit
30
32
31−data StackLocation
33+data PackageLocation
32 = HackagePackage Text
34 = HackagePackage Text
33− | StackPath Text
35+ | StackFilePath FilePath
36+ | StackUri URI
34 | StackRepoGit RepoGit
37 | StackRepoGit RepoGit
35 deriving (Eq, Ord, Show)
38 deriving (Eq, Ord, Show)
36
39
37−makePrisms ''StackLocation
40+makePrisms ''PackageLocation
38
41
39data StackPackage = StackPackage
42data StackPackage = StackPackage
40− { _spSource :: StackLocation
43+ { _spLocation :: PackageLocation
41 , _spExtraDep :: Bool
44 , _spExtraDep :: Bool
42 } deriving (Eq, Ord, Show)
45 } deriving (Eq, Ord, Show)
43
46
@@ -55,17 +58,19 @@ fromYamlConfig c = StackConfig{..}
55 where
58 where
56 _scResolver = coerce $ c ^. cResolver
59 _scResolver = coerce $ c ^. cResolver
57 _scPackages =
60 _scPackages =
58− (fromYamlPackage <$> c ^. cPackages) ++
61+ (fromYamlPackage <$> c ^. cPackages . to (fromMaybe mempty)) ++
59− (fromYamlExtraDep <$> c ^. cExtraDeps)
62+ (fromYamlExtraDep <$> c ^. cExtraDeps . to (fromMaybe mempty))
60
63
61fromYamlPackage :: Yaml.Package -> StackPackage
64fromYamlPackage :: Yaml.Package -> StackPackage
62fromYamlPackage = \case
65fromYamlPackage = \case
63− Yaml.Simple path ->
66+ Yaml.Simple p ->
64− StackPackage (StackPath path) False
67+ StackPackage (parseSimplePath p) False
65− Yaml.LocationSimple (Yaml.Location path extraDep) ->
68+ Yaml.LocationSimple (Yaml.Location p extraDep) ->
66− StackPackage (StackPath path) (fromMaybe False extraDep)
69+ StackPackage (parseSimplePath p) (fromMaybe False extraDep)
67− Yaml.LocationGit (Location git extraDep) ->
70+ Yaml.LocationGit (Location git extraDep) ->
68 StackPackage (StackRepoGit $ fromYamlGit git) (fromMaybe False extraDep)
71 StackPackage (StackRepoGit $ fromYamlGit git) (fromMaybe False extraDep)
72+ where
73+ parseSimplePath (T.unpack -> p) = maybe (StackFilePath p) StackUri $ parseURI p
69
74
70fromYamlExtraDep :: Text -> StackPackage
75fromYamlExtraDep :: Text -> StackPackage
71fromYamlExtraDep = flip StackPackage True . HackagePackage
76fromYamlExtraDep = flip StackPackage True . HackagePackage
src/Stack/Config/TH.hsnew file+23
@@ -0,0 +1,23 @@
1+module Stack.Config.TH where
2+
3+import Data.Aeson.TH
4+import Data.Char as C
5+import Data.List as L
6+import Data.Text as T
7+import Text.Inflections as TI
8+
9+toDashedField :: String -> String
10+toDashedField = toDashed' . dropPrefix
11+
12+toDashed' :: String -> String
13+toDashed' = either (const $ error "toDashed failed") T.unpack
14+ . TI.toDashed
15+ . T.pack
16+
17+dropPrefix :: String -> String
18+dropPrefix = L.dropWhile (not . C.isUpper)
19+
20+jsonOpts :: Options
21+jsonOpts = defaultOptions
22+ { fieldLabelModifier = toDashedField
23+ , omitNothingFields = True }
src/Stack/Config/Yaml.hs+16−19
@@ -1,12 +1,15 @@
1−{-# LANGUAGE TemplateHaskell #-}
2{-# LANGUAGE OverloadedStrings #-}
1{-# LANGUAGE OverloadedStrings #-}
2+{-# LANGUAGE TemplateHaskell #-}
3+{-# LANGUAGE LambdaCase #-}
3
4
4module Stack.Config.Yaml where
5module Stack.Config.Yaml where
5
6
6import Control.Applicative
7import Control.Applicative
7import Control.Lens
8import Control.Lens
8import Data.Aeson
9import Data.Aeson
10+import Data.Aeson.TH
9import Data.Text as T
11import Data.Text as T
12+import Stack.Config.TH
10
13
11data Location a = Location
14data Location a = Location
12 { _lLocation :: a
15 { _lLocation :: a
@@ -15,11 +18,7 @@ data Location a = Location
15
18
16makeLenses ''Location
19makeLenses ''Location
17
20
18−instance FromJSON a => FromJSON (Location a) where
19− parseJSON = withObject "Location" $ \v ->
20− Location <$>
21+deriveJSON jsonOpts ''Location
21− v .: "location" <*>
22− v .:? "extra-dep"
23
22
24data Git = Git
23data Git = Git
25 { _gGit :: Text
24 { _gGit :: Text
@@ -28,17 +27,14 @@ data Git = Git
28
27
29makeLenses ''Git
28makeLenses ''Git
30
29
31−instance FromJSON Git where
30+deriveJSON jsonOpts ''Git
32− parseJSON = withObject "Git" $ \v ->
33− Git <$>
34− v .: "git" <*>
35− v .: "commit"
36
31
37data Package
32data Package
38 = Simple Text
33 = Simple Text
39 | LocationSimple (Location Text)
34 | LocationSimple (Location Text)
40 | LocationGit (Location Git)
35 | LocationGit (Location Git)
41 deriving (Eq, Show)
36 deriving (Eq, Show)
37+
42makePrisms ''Package
38makePrisms ''Package
43
39
44instance FromJSON Package where
40instance FromJSON Package where
@@ -47,17 +43,18 @@ instance FromJSON Package where
47 (LocationSimple <$> parseJSON v) <|>
43 (LocationSimple <$> parseJSON v) <|>
48 (LocationGit <$> parseJSON v)
44 (LocationGit <$> parseJSON v)
49
45
46+instance ToJSON Package where
47+ toJSON = \case
48+ Simple t -> toJSON t
49+ LocationSimple t -> toJSON t
50+ LocationGit t -> toJSON t
51+
50data Config = Config
52data Config = Config
51 { _cResolver :: Text
53 { _cResolver :: Text
52− , _cPackages :: [Package]
54+ , _cPackages :: Maybe [Package]
53− , _cExtraDeps :: [Text]
55+ , _cExtraDeps :: Maybe [Text]
54 } deriving (Eq, Show)
56 } deriving (Eq, Show)
55
57
56makeLenses ''Config
58makeLenses ''Config
57
59
58−instance FromJSON Config where
59− parseJSON = withObject "Config" $ \v ->
60− Config <$>
60+deriveJSON jsonOpts ''Config
61− v .: "resolver" <*>
62− v .:? "packages" .!= [] <*>
63− v .:? "extra-deps" .!= []
stack2nix.cabal+3
@@ -20,6 +20,7 @@ library
20 , Runner
20 , Runner
21 , Runner.Cli
21 , Runner.Cli
22 , Stack.Config
22 , Stack.Config
23+ , Stack.Config.TH
23 , Stack.Config.Yaml
24 , Stack.Config.Yaml
24 , Stack.Types
25 , Stack.Types
25 build-depends: base > 4.7 && < 5
26 build-depends: base > 4.7 && < 5
@@ -31,8 +32,10 @@ library
31 , deepseq
32 , deepseq
32 , distribution-nixpkgs >= 1.1
33 , distribution-nixpkgs >= 1.1
33 , filepath
34 , filepath
35+ , inflections
34 , language-nix
36 , language-nix
35 , lens
37 , lens
38+ , network-uri
36 , optparse-applicative
39 , optparse-applicative
37 , pretty
40 , pretty
38 , text
41 , text
test.shnew file+3
@@ -0,0 +1,3 @@
1+#!/usr/bin/env sh
2+
3+exec stack2nix --nix-stackage-config=nix/configuration-packages.nix --nix-stackage-packages=./nix/packages.nix
test/Stack/Config/YamlSpec.hs+4−4
@@ -36,14 +36,14 @@ extra-deps:
36configMinimal :: Config
36configMinimal :: Config
37configMinimal = Config
37configMinimal = Config
38 { _cResolver = "lts-8.15"
38 { _cResolver = "lts-8.15"
39− , _cPackages = [ Simple "." ]
39+ , _cPackages = Just [ Simple "." ]
40− , _cExtraDeps = []
40+ , _cExtraDeps = Nothing
41 }
41 }
42
42
43config :: Config
43config :: Config
44config = Config
44config = Config
45 { _cResolver = "lts-3.7"
45 { _cResolver = "lts-3.7"
46− , _cPackages =
46+ , _cPackages = Just
47 [ Simple "."
47 [ Simple "."
48 , LocationSimple (Location "dir1/dir2" Nothing)
48 , LocationSimple (Location "dir1/dir2" Nothing)
49 , LocationSimple (Location "https://example.com/foo/bar/baz-0.0.2.tar.gz" (Just True))
49 , LocationSimple (Location "https://example.com/foo/bar/baz-0.0.2.tar.gz" (Just True))
@@ -52,7 +52,7 @@ config = Config
52 "git@github.com:commercialhaskell/stack.git"
52 "git@github.com:commercialhaskell/stack.git"
53 "6a86ee32e5b869a877151f74064572225e1a0398")
53 "6a86ee32e5b869a877151f74064572225e1a0398")
54 Nothing]
54 Nothing]
55− , _cExtraDeps =
55+ , _cExtraDeps = Just
56 ["acme-missiles-0.3"]
56 ["acme-missiles-0.3"]
57 }
57 }
58
58