git.iko.soy/typeable/stackage2nix
on master help sign in
Add: Cli module
commit3382b6ac692f15da2985df3c7b6504ea981e69c3 authorDmitry Bushev <bushevdv@gmail.com> dateThu 25 May 2017, 20:30 (9 years ago) parent596bf03
12 files changed+227−54
app/Main.hs+2−30 src/Cli.hs+87 src/Distribution/Nixpkgs/Haskell/Packages/PrettyPrinting.hs+28 src/Distribution/Nixpkgs/Haskell/Stack.hs+15−14 src/Runner.hs+30 src/Stack/Config.hs+7 src/Stack/Config/Yaml.hs+3−3 src/Stack/Types.hs+14 stack.yaml+3 stack2nix.cabal+10−3 test/PrettyPrintingSpec.hs+8 test/Stack/YamlSpec.hs → test/Stack/Config/YamlSpec.hs+20−4
app/Main.hs+2−30
@@ -1,34 +1,6 @@
1−{-# LANGUAGE RecordWildCards #-}
2−
31module Main where
42
5−import Data.Monoid ( (<>) )
6−import Options.Applicative
7−import Distribution.Nixpkgs.Haskell.Stack
8−
9−data Options = Options
10− { optStackYaml :: Maybe FilePath
11− , optStackResolver :: Maybe String
12− , optOutDir :: FilePath
13− , optHackageDb :: Maybe FilePath
14− } deriving (Show)
15−
16−options :: Parser Options
17−options = Options
18− <$> optional (strArgument $ metavar "STACK_YAML")
19− <*> optional (strOption $ long "resolver" <> metavar "RESOLVER" <> help "override stack resolver")
20− <*> strOption (long "out" <> metavar "OUT" <> value "nix" <> showDefaultWith id <> help "output directory")
21− <*> optional (strOption $ long "hackage-db" <> metavar "HACKAGE_DB" <> help "path to the local hackage db in tar format")
22−
23−pinfo :: ParserInfo Options
24−pinfo = info
25− ( helper
26− <*> options )
27− ( fullDesc
28− <> header "stack2nix converts Stack files into build instructions for Nix." )
29−
3+import Runner
304
315main :: IO ()
32−main = do
33− Options {..} <- execParser pinfo
34− print $ nixpkgsOverride overrideConfigFixture
6+main = run
src/Cli.hsnew file+87
@@ -0,0 +1,87 @@
1+module Cli where
2+
3+import Data.Monoid ( (<>) )
4+import Data.Text as T
5+import qualified Distribution.Compat.ReadP as P
6+import Distribution.Compiler as Compiler
7+import Distribution.Nixpkgs.Haskell.Stack
8+import Distribution.System as System
9+import qualified Distribution.Text as Text
10+import Options.Applicative
11+import Stack.Config
12+import Stack.Types
13+
14+
15+data Options = Options
16+ { optStackResolver :: Maybe StackResolver
17+ , optHackageDb :: Maybe HackageDb
18+ , optFlags :: [CabalFlag]
19+ , optCompilerId :: CompilerId
20+ , optPlatform :: Platform
21+ , optStackYaml :: FilePath
22+ } deriving (Show)
23+
24+options :: Parser Options
25+options = Options
26+ <$> optional stackResolver
27+ <*> optional hackageDb
28+ <*> many cabalFlag
29+ <*> compilerId
30+ <*> platform
31+ <*> stackYamlArg
32+
33+pinfo :: ParserInfo Options
34+pinfo = info
35+ ( helper
36+ <*> options )
37+ ( fullDesc
38+ <> header "stack2nix converts Stack files into build instructions for Nix." )
39+
40+stackResolver :: Parser StackResolver
41+stackResolver = StackResolver <$>
42+ option text
43+ ( long "resolver"
44+ <> metavar "RESOLVER"
45+ <> help "override stack resolver" )
46+
47+stackYamlArg :: Parser FilePath
48+stackYamlArg = argument str
49+ ( metavar "STACK_YAML"
50+ <> value "stack.yaml" )
51+
52+hackageDb :: Parser HackageDb
53+hackageDb = HackageDb <$>
54+ option text
55+ ( long "hackage-db"
56+ <> metavar "HACKAGE_DB"
57+ <> help "path to the local hackage db in tar format" )
58+
59+cabalFlag :: Parser CabalFlag
60+cabalFlag = CabalFlag <$>
61+ option text
62+ ( short 'f'
63+ <> long "flag"
64+ <> help "Cabal flag (may be specified multiple times)" )
65+
66+compilerId :: Parser CompilerId
67+compilerId = option (readP Text.parse)
68+ ( long "compiler"
69+ <> help "compiler to use when evaluating the Cabal file"
70+ <> value buildCompilerId
71+ <> showDefaultWith Text.display )
72+
73+platform :: Parser Platform
74+platform = option (readP Text.parse)
75+ ( long "system"
76+ <> help "target system to use when evaluating the Cabal file"
77+ <> value buildPlatform
78+ <> showDefaultWith Text.display )
79+
80+text :: ReadM Text
81+text = T.pack <$> str
82+
83+readP :: P.ReadP a a -> ReadM a
84+readP p = eitherReader $ \s ->
85+ case [ r' | (r',"") <- P.readP_to_S p s ] of
86+ (r:_) -> Right r
87+ _ -> Left ("invalid value " ++ show s)
src/Distribution/Nixpkgs/Haskell/Packages/PrettyPrinting.hsnew file+28
@@ -0,0 +1,28 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+
3+module Distribution.Nixpkgs.Haskell.Packages.PrettyPrinting where
4+
5+import Language.Nix.PrettyPrinting
6+
7+compilerConfig :: Doc -> Doc
8+compilerConfig body =
9+ funargsCurried ["self", "super"] <+> body
10+
11+packageSetConfig :: Doc -> Doc
12+packageSetConfig body = vcat
13+ [ funargs ["pkgs", "stdenv", "callPackage"]
14+ , ""
15+ , funarg "self" <+> body ]
16+
17+overrides :: Doc -> Doc
18+overrides body = funargsCurried ["self", "super"] <+> body
19+
20+-- | Function argument
21+-- output 'arg:'
22+funarg :: Doc -> Doc
23+funarg = flip (<>) colon
24+
25+-- | Function arguments curried
26+-- output 'arg1: arg2:'
27+funargsCurried :: [Doc] -> Doc
28+funargsCurried = hsep . fmap funarg
src/Distribution/Nixpkgs/Haskell/Stack.hs+15−14
@@ -83,10 +83,10 @@ getPackageFromDb
8383 -> StackExtraDep
8484 -> IO Package
8585getPackageFromDb optHackageDb stackExtraDep =
86− PackageSourceSpec.getPackage (unHackageDb <$> optHackageDb) (extraDepToSource stackExtraDep)
86+ PackageSourceSpec.getPackage (unHackageDb <$> optHackageDb) (sourceFromExtraDep stackExtraDep)
8787
88−extraDepToSource :: StackExtraDep -> Source
89−extraDepToSource sed = Source{..}
88+sourceFromExtraDep :: StackExtraDep -> Source
89+sourceFromExtraDep sed = Source{..}
9090 where
9191 sourceUrl = "cabal://" ++ unExtraDep sed
9292 sourceRevision = mempty
@@ -95,17 +95,18 @@ extraDepToSource sed = Source{..}
9595extraDepDerivation
9696 :: Maybe HackageDb
9797 -> System.Platform
98− -> Compiler.CompilerInfo
98+ -> Compiler.CompilerId
9999 -> PackageDescription.FlagAssignment
100100 -> StackExtraDep
101101 -> IO Derivation
102−extraDepDerivation optHackageDb optPlatform optCompilerInfo optFlagAssignment sed =
103− FromCabal.fromGenericPackageDescription
104− (const True)
105− (\i -> Just (binding # (i, path # [i])))
106− optPlatform
107− optCompilerInfo
108− optFlagAssignment
109− []
110− . pkgCabal
111− <$> getPackageFromDb optHackageDb sed
102+extraDepDerivation optHackageDb optPlatform optCompilerId optFlagAssignment sed = do
103+ pkg <- getPackageFromDb optHackageDb sed
104+ pure $ FromCabal.fromGenericPackageDescription
105+ (const True)
106+ (\i -> Just (binding # (i, path # [i])))
107+ optPlatform
108+ (unknownCompilerInfo optCompilerId NoAbiTag)
109+ optFlagAssignment
110+ []
111+ (pkgCabal pkg)
112+ & src .~ pkgSource pkg
src/Runner.hsnew file+30
@@ -0,0 +1,30 @@
1+{-# LANGUAGE RecordWildCards #-}
2+
3+module Runner where
4+
5+import Cli
6+import Control.Lens
7+import Distribution.Nixpkgs.Haskell.Stack
8+import Distribution.PackageDescription ( FlagName(..), FlagAssignment )
9+import Distribution.Simple.Utils ( lowercase )
10+import Language.Nix.PrettyPrinting as PP
11+import Options.Applicative
12+import Stack.Config
13+import Stack.Types
14+
15+
16+readFlagList :: [CabalFlag] -> FlagAssignment
17+readFlagList = fmap (tagWithValue . unCabalFlag)
18+ where tagWithValue ('-':fname) = (FlagName (lowercase fname), False)
19+ tagWithValue fname = (FlagName (lowercase fname), True)
20+
21+run :: IO ()
22+run = do
23+ Options{..} <- execParser pinfo
24+ stackYaml <- either fail pure =<< readStackConfig optStackYaml
25+ print $ stackYaml ^. scExtraDeps
26+ derivations <- traverse (extraDepDerivation optHackageDb optPlatform optCompilerId (readFlagList optFlags))
27+ $ stackYaml ^. scExtraDeps
28+ let out = PP.cat $ PP.pPrint <$> derivations
29+ print out
30+ --print $ nixpkgsOverride overrideConfigFixture
src/Stack/Config.hs+7
@@ -5,9 +5,12 @@
55module Stack.Config where
66
77import Control.Lens
8+import Data.Bifunctor
9+import Data.ByteString as BS
810import Data.Coerce
911import Data.Maybe
1012import Data.Text as T
13+import Data.Yaml
1114import Stack.Config.Yaml as Yaml
1215
1316newtype StackResolver = StackResolver { fromStackResolver :: Text }
@@ -76,3 +79,7 @@ fromYamlGit yg = RepoGit{..}
7679 where
7780 _rgUri = yg ^. gGit
7881 _rgCommit = yg ^. gCommit
82+
83+readStackConfig :: FilePath -> IO (Either String StackConfig)
84+readStackConfig stackYaml =
85+ second fromYamlConfig . decodeEither <$> BS.readFile stackYaml
src/Stack/Config/Yaml.hs+3−3
@@ -58,6 +58,6 @@ makeLenses ''Config
5858instance FromJSON Config where
5959 parseJSON = withObject "Config" $ \v ->
6060 Config <$>
61− v .: "resolver" <*>
62− v .: "packages" <*>
63− v .: "extra-deps"
61+ v .: "resolver" <*>
62+ v .:? "packages" .!= [] <*>
63+ v .:? "extra-deps" .!= []
src/Stack/Types.hsnew file+14
@@ -0,0 +1,14 @@
1+{-# LANGUAGE TemplateHaskell #-}
2+
3+module Stack.Types where
4+
5+import Control.Lens
6+import Data.Text as T
7+
8+newtype CabalFlag = CabalFlag { fromCabalFlag :: Text }
9+ deriving (Ord, Eq, Show)
10+
11+makePrisms ''CabalFlag
12+
13+unCabalFlag :: CabalFlag -> String
14+unCabalFlag = T.unpack . fromCabalFlag
stack.yaml+3
@@ -1,3 +1,6 @@
11resolver: lts-8.15
22packages:
33- '.'
4+extra-deps:
5+- list-t-1
6+- type-fun-0.1.1
stack2nix.cabal+10−3
@@ -13,16 +13,22 @@ cabal-version: >=1.10
1313
1414library
1515 hs-source-dirs: src
16− exposed-modules: Distribution.Nixpkgs.Haskell.Stack
16+ exposed-modules: Cli
17+ , Distribution.Nixpkgs.Haskell.Packages.PrettyPrinting
18+ , Distribution.Nixpkgs.Haskell.Stack
19+ , Runner
1720 , Stack.Config
1821 , Stack.Config.Yaml
22+ , Stack.Types
1923 build-depends: base > 4.7 && < 5
2024 , Cabal > 1.24 && < 1.25
2125 , aeson > 1.0 && < 1.1
26+ , bytestring > 0.10 && < 0.11
2227 , cabal2nix > 2.0 && < 2.1
2328 , distribution-nixpkgs > 1 && < 1.1
2429 , language-nix > 2.1 && < 2.2
2530 , lens > 4.15 && < 4.16
31+ , optparse-applicative > 0.13 && < 0.14
2632 , pretty > 1.1 && < 1.2
2733 , text > 1.2 && < 1.3
2834 , yaml > 0.8 && < 0.9
@@ -34,7 +40,6 @@ executable stack2nix
3440 main-is: Main.hs
3541 ghc-options: -threaded -rtsopts -with-rtsopts=-N
3642 build-depends: base
37− , optparse-applicative > 0.13 && < 1
3843 , stack2nix
3944 default-language: Haskell2010
4045
@@ -42,7 +47,6 @@ test-suite spec
4247 type: exitcode-stdio-1.0
4348 hs-source-dirs: test
4449 main-is: Spec.hs
45− other-modules: Stack.YamlSpec
4650 build-depends: base
4751 , bytestring > 0.10 && < 0.11
4852 , hspec
@@ -50,6 +54,9 @@ test-suite spec
5054 , stack2nix
5155 , text
5256 , yaml
57+ default-extensions: OverloadedStrings
58+ other-modules: PrettyPrintingSpec
59+ , Stack.Config.YamlSpec
5360 ghc-options: -threaded -rtsopts -with-rtsopts=-N
5461 default-language: Haskell2010
5562
test/PrettyPrintingSpec.hsnew file+8
@@ -0,0 +1,8 @@
1+module PrettyPrintingSpec where
2+
3+import Distribution.Nixpkgs.Haskell.Packages.PrettyPrinting
4+import Test.Hspec
5+
6+spec :: Spec
7+spec = specify "test" $
8+ print (overrides "body")
test/Stack/YamlSpec.hs → test/Stack/Config/YamlSpec.hsrenamed+20−4
@@ -1,15 +1,22 @@
11{-# LANGUAGE OverloadedStrings #-}
22{-# LANGUAGE QuasiQuotes #-}
33
4−module Stack.YamlSpec where
4+module Stack.Config.YamlSpec where
55
66import Data.ByteString
77import Data.Text.Encoding as T
88import Data.Yaml as Y
9−import Stack.Yaml
9+import Stack.Config.Yaml
1010import Test.Hspec
1111import Text.Shakespeare.Text
1212
13+configYamlMinimal :: ByteString
14+configYamlMinimal = T.encodeUtf8 [st|
15+resolver: lts-8.15
16+packages:
17+- '.'
18+|]
19+
1320configYaml :: ByteString
1421configYaml = T.encodeUtf8 [st|
1522resolver: lts-3.7
@@ -26,6 +33,13 @@ extra-deps:
2633- acme-missiles-0.3
2734|]
2835
36+configMinimal :: Config
37+configMinimal = Config
38+ { _cResolver = "lts-8.15"
39+ , _cPackages = [ Simple "." ]
40+ , _cExtraDeps = []
41+ }
42+
2943config :: Config
3044config = Config
3145 { _cResolver = "lts-3.7"
@@ -43,6 +57,8 @@ config = Config
4357 }
4458
4559spec :: Spec
46−spec = describe "Config" $
47− it "parsed" $
60+spec = describe "Parse" $ do
61+ specify "config-minimal" $
62+ (Y.decode configYamlMinimal :: Maybe Config) `shouldBe` Just configMinimal
63+ specify "config-full" $
4864 (Y.decode configYaml :: Maybe Config) `shouldBe` Just config