git.iko.soy/typeable/stackage2nix
on master help sign in
Honour stack.yaml's subdirs (#31)
89af70dMateusz Kowalczyk
src/Distribution/Nixpkgs/Haskell/Stack.hs+15−7
@@ -1,6 +1,7 @@
1module Distribution.Nixpkgs.Haskell.Stack where
1module Distribution.Nixpkgs.Haskell.Stack where
2
2
3import Control.Lens
3import Control.Lens
4+import Data.Maybe (fromMaybe)
4import Data.Text as T
5import Data.Text as T
5import Distribution.Compiler as Compiler
6import Distribution.Compiler as Compiler
6import Distribution.Nixpkgs.Fetch
7import Distribution.Nixpkgs.Fetch
@@ -42,30 +43,36 @@ getStackPackageFromDb
42getStackPackageFromDb optHackageDb stackPackage =
43getStackPackageFromDb optHackageDb stackPackage =
43 PackageSourceSpec.getPackage
44 PackageSourceSpec.getPackage
44 (unHackageDb <$> optHackageDb)
45 (unHackageDb <$> optHackageDb)
45− (stackLocationToSource $ stackPackage ^. spLocation)
46+ (stackLocationToSource (stackPackage ^. spLocation) (stackPackage ^. spDir))
46
47
47−stackLocationToSource :: PackageLocation -> Source
48+stackLocationToSource
49+ :: PackageLocation
50+ -- | Subdirectory in the package containing cabal file.
51+ -> Maybe FilePath
52+ -> Source
48−stackLocationToSource = \case
53+stackLocationToSource pl mCabalDir = case pl of
49 HackagePackage p -> Source
54 HackagePackage p -> Source
50 { sourceUrl = "cabal://" ++ T.unpack p
55 { sourceUrl = "cabal://" ++ T.unpack p
51 , sourceRevision = mempty
56 , sourceRevision = mempty
52 , sourceHash = UnknownHash
57 , sourceHash = UnknownHash
53− , sourceCabalDir = mempty }
58+ , sourceCabalDir = cabalDir }
54 StackFilePath p -> Source
59 StackFilePath p -> Source
55 { sourceUrl = p
60 { sourceUrl = p
56 , sourceRevision = mempty
61 , sourceRevision = mempty
57 , sourceHash = UnknownHash
62 , sourceHash = UnknownHash
58− , sourceCabalDir = mempty }
63+ , sourceCabalDir = cabalDir }
59 StackUri uri -> Source
64 StackUri uri -> Source
60 { sourceUrl = URI.uriToString id uri mempty
65 { sourceUrl = URI.uriToString id uri mempty
61 , sourceRevision = mempty
66 , sourceRevision = mempty
62 , sourceHash = UnknownHash
67 , sourceHash = UnknownHash
63− , sourceCabalDir = mempty }
68+ , sourceCabalDir = cabalDir }
64 StackRepo r -> Source
69 StackRepo r -> Source
65 { sourceUrl = T.unpack $ r ^. rUri
70 { sourceUrl = T.unpack $ r ^. rUri
66 , sourceRevision = T.unpack $ r ^. rCommit
71 , sourceRevision = T.unpack $ r ^. rCommit
67 , sourceHash = UnknownHash
72 , sourceHash = UnknownHash
68− , sourceCabalDir = mempty }
73+ , sourceCabalDir = cabalDir }
74+ where
75+ cabalDir = fromMaybe mempty mCabalDir
69
76
70packageDerivation
77packageDerivation
71 :: StackPackagesConfig
78 :: StackPackagesConfig
@@ -79,6 +86,7 @@ packageDerivation conf optHackageDb stackPackage = do
79 & src .~ pkgSource pkg
86 & src .~ pkgSource pkg
80 -- TODO: remove after Nixos/Nixpkgs #27196 released
87 -- TODO: remove after Nixos/Nixpkgs #27196 released
81 & enableSeparateDataOutput .~ False
88 & enableSeparateDataOutput .~ False
89+ & subpath %~ flip fromMaybe (stackPackage ^. spDir)
82 return $ if stackPackage ^. spExtraDep
90 return $ if stackPackage ^. spExtraDep
83 then drv
91 then drv
84 & doCheck &&~ conf ^. spcDoCheckStackage
92 & doCheck &&~ conf ^. spcDoCheckStackage
src/LtsHaskell.hs+1−1
@@ -51,7 +51,7 @@ getPackageFromRepo allCabalHashesPath mSha1Hash pkgId = do
51getPackageFromDb :: PackageIdentifier -> IO Package
51getPackageFromDb :: PackageIdentifier -> IO Package
52getPackageFromDb pkgId =
52getPackageFromDb pkgId =
53 getStackPackageFromDb Nothing
53 getStackPackageFromDb Nothing
54− $ StackPackage (HackagePackage (T.pack $ Text.display pkgId)) True
54+ $ StackPackage (HackagePackage (T.pack $ Text.display pkgId)) True Nothing
55
55
56loadPackage :: FilePath -> Maybe SHA1Hash -> PackageIdentifier -> IO Package
56loadPackage :: FilePath -> Maybe SHA1Hash -> PackageIdentifier -> IO Package
57loadPackage allCabalHashesPath mSha1Hash pkgId =
57loadPackage allCabalHashesPath mSha1Hash pkgId =
src/Stack/Config.hs+28−14
@@ -9,6 +9,7 @@ import Data.Coerce
9import Data.Foldable as F
9import Data.Foldable as F
10import Data.List.NonEmpty as NE
10import Data.List.NonEmpty as NE
11import Data.Maybe
11import Data.Maybe
12+import Data.Semigroup (sconcat)
12import Data.Text as T
13import Data.Text as T
13import Data.Yaml
14import Data.Yaml
14import Network.URI
15import Network.URI
@@ -48,6 +49,8 @@ makePrisms ''PackageLocation
48data StackPackage = StackPackage
49data StackPackage = StackPackage
49 { _spLocation :: !PackageLocation
50 { _spLocation :: !PackageLocation
50 , _spExtraDep :: !Bool
51 , _spExtraDep :: !Bool
52+ -- | Subdirectory containing the cabal file if any specified.
53+ , _spDir :: !(Maybe FilePath)
51 } deriving (Eq, Ord, Show)
54 } deriving (Eq, Ord, Show)
52
55
53makeLenses ''StackPackage
56makeLenses ''StackPackage
@@ -62,28 +65,39 @@ makeLenses ''StackConfig
62fromYamlConfig :: Yaml.Config -> StackConfig
65fromYamlConfig :: Yaml.Config -> StackConfig
63fromYamlConfig c = StackConfig{..}
66fromYamlConfig c = StackConfig{..}
64 where
67 where
65− _scResolver = coerce $ c ^. cResolver
68+ _scResolver = coerce $ c ^. cResolver
66− _scPackages = F.foldr (NE.<|) neYamlPackages yamlExtraDeps
69+ _scPackages = F.foldr (NE.<|) neYamlPackages yamlExtraDeps
67− neYamlPackages = fromMaybe (pure defaultPackage) $ NE.nonEmpty yamlPackages
70+ neYamlPackages = fromMaybe (pure defaultPackage)
71+ . fmap sconcat $ NE.nonEmpty yamlPackages
68− yamlPackages = fromYamlPackage <$> fromMaybe mempty (c ^. cPackages)
72+ yamlPackages = fromYamlPackage <$> (fromMaybe mempty (c ^. cPackages))
69 yamlExtraDeps = fromYamlExtraDep <$> fromMaybe mempty (c ^. cExtraDeps)
73 yamlExtraDeps = fromYamlExtraDep <$> fromMaybe mempty (c ^. cExtraDeps)
70− defaultPackage = StackPackage (StackFilePath ".") False
74+ defaultPackage = StackPackage (StackFilePath ".") False Nothing
71
75
76+
72−fromYamlPackage :: Yaml.Package -> StackPackage
77+fromYamlPackage
78+ :: Yaml.Package
79+ -- | A single 'Yaml.Package' can result in multiple actual
80+ -- packages if it has multiple subdirs specified.
81+ -> NonEmpty StackPackage
73fromYamlPackage = \case
82fromYamlPackage = \case
74 Yaml.Simple p ->
83 Yaml.Simple p ->
75− StackPackage (parseSimplePath p) False
84+ unroll Nothing $ StackPackage (parseSimplePath p) False
76− Yaml.LocationSimple (Yaml.Location p extraDep) ->
85+ Yaml.LocationSimple (Location p extraDep ms) ->
77− StackPackage (parseSimplePath p) (fromMaybe False extraDep)
86+ unroll ms $ StackPackage (parseSimplePath p) (fromMaybe False extraDep)
78− Yaml.LocationGit (Location git extraDep) ->
87+ Yaml.LocationGit (Location git extraDep ms) ->
79− StackPackage (StackRepo $ fromYamlGit git) (fromMaybe False extraDep)
88+ unroll ms $ StackPackage (StackRepo $ fromYamlGit git) (fromMaybe False extraDep)
80− Yaml.LocationHg (Location hg extraDep) ->
89+ Yaml.LocationHg (Location hg extraDep ms) ->
81− StackPackage (StackRepo $ fromYamlHg hg) (fromMaybe False extraDep)
90+ unroll ms $ StackPackage (StackRepo $ fromYamlHg hg) (fromMaybe False extraDep)
82 where
91 where
83 parseSimplePath (T.unpack -> p) = maybe (StackFilePath p) StackUri $ parseURI p
92 parseSimplePath (T.unpack -> p) = maybe (StackFilePath p) StackUri $ parseURI p
93+ -- Each package gets a single directory with cabal file in it. If
94+ -- it's not specified, path is empty.
95+ unroll subs p = case subs of
96+ Just (x : xs) -> NE.map (p . Just) (x :| xs)
97+ _ -> p Nothing :| []
84
98
85fromYamlExtraDep :: Text -> StackPackage
99fromYamlExtraDep :: Text -> StackPackage
86−fromYamlExtraDep = flip StackPackage True . HackagePackage
100+fromYamlExtraDep t = StackPackage (HackagePackage t) True Nothing
87
101
88fromYamlGit :: Yaml.Git -> Repo
102fromYamlGit :: Yaml.Git -> Repo
89fromYamlGit yg = Repo{..}
103fromYamlGit yg = Repo{..}
src/Stack/Config/Yaml.hs+1
@@ -10,6 +10,7 @@ import Stack.Config.TH
10data Location a = Location
10data Location a = Location
11 { _lLocation :: !a
11 { _lLocation :: !a
12 , _lExtraDep :: !(Maybe Bool)
12 , _lExtraDep :: !(Maybe Bool)
13+ , _lSubdirs :: !(Maybe [FilePath])
13 } deriving (Eq, Show)
14 } deriving (Eq, Show)
14
15
15makeLenses ''Location
16makeLenses ''Location
test/Stack/Config/YamlSpec.hs+15−3
@@ -28,6 +28,12 @@ packages:
28 - location:
28 - location:
29 git: git@github.com:commercialhaskell/stack.git
29 git: git@github.com:commercialhaskell/stack.git
30 commit: 6a86ee32e5b869a877151f74064572225e1a0398
30 commit: 6a86ee32e5b869a877151f74064572225e1a0398
31+ - location:
32+ git: git@github.com:example/mega-repo
33+ commit: 6a86ee32e5b869a877151f74064572225e1a0000
34+ subdirs:
35+ - subdir1
36+ - subdir2
31# Comment
37# Comment
32extra-deps:
38extra-deps:
33- acme-missiles-0.3
39- acme-missiles-0.3
@@ -45,13 +51,19 @@ config = Config
45 { _cResolver = "lts-3.7"
51 { _cResolver = "lts-3.7"
46 , _cPackages = Just
52 , _cPackages = Just
47 [ Simple "."
53 [ Simple "."
48− , LocationSimple (Location "dir1/dir2" Nothing)
54+ , LocationSimple (Location "dir1/dir2" Nothing Nothing)
49− , LocationSimple (Location "https://example.com/foo/bar/baz-0.0.2.tar.gz" (Just True))
55+ , LocationSimple (Location "https://example.com/foo/bar/baz-0.0.2.tar.gz" (Just True) Nothing)
50 , LocationGit $ Location
56 , LocationGit $ Location
51 (Git
57 (Git
52 "git@github.com:commercialhaskell/stack.git"
58 "git@github.com:commercialhaskell/stack.git"
53 "6a86ee32e5b869a877151f74064572225e1a0398")
59 "6a86ee32e5b869a877151f74064572225e1a0398")
54− Nothing]
60+ Nothing Nothing
61+ , LocationGit (Location
62+ (Git
63+ "git@github.com:example/mega-repo"
64+ "6a86ee32e5b869a877151f74064572225e1a0000")
65+ Nothing (Just ["subdir1", "subdir2"]))
66+ ]
55 , _cExtraDeps = Just
67 , _cExtraDeps = Just
56 ["acme-missiles-0.3"]
68 ["acme-missiles-0.3"]
57 }
69 }