@@ -9,6 +9,7 @@ import Data.Coerce
99import Data.Foldable as F
1010import Data.List.NonEmpty as NE
1111import Data.Maybe
12+import Data.Semigroup (sconcat)
1213import Data.Text as T
1314import Data.Yaml
1415import Network.URI
@@ -48,6 +49,8 @@ makePrisms ''PackageLocation
4849data StackPackage = StackPackage
4950 { _spLocation :: !PackageLocation
5051 , _spExtraDep :: !Bool
52+ -- | Subdirectory containing the cabal file if any specified.
53+ , _spDir :: !(Maybe FilePath)
5154 } deriving (Eq, Ord, Show)
5255
5356makeLenses ''StackPackage
@@ -62,28 +65,39 @@ makeLenses ''StackConfig
6265fromYamlConfig :: Yaml.Config -> StackConfig
6366fromYamlConfig c = StackConfig{..}
6467 where
65− _scResolver = coerce $ c ^. cResolver
66− _scPackages = F.foldr (NE.<|) neYamlPackages yamlExtraDeps
67− neYamlPackages = fromMaybe (pure defaultPackage) $ NE.nonEmpty yamlPackages
68− yamlPackages = fromYamlPackage <$> fromMaybe mempty (c ^. cPackages)
68+ _scResolver = coerce $ c ^. cResolver
69+ _scPackages = F.foldr (NE.<|) neYamlPackages yamlExtraDeps
70+ neYamlPackages = fromMaybe (pure defaultPackage)
71+ . fmap sconcat $ NE.nonEmpty yamlPackages
72+ yamlPackages = fromYamlPackage <$> (fromMaybe mempty (c ^. cPackages))
6973 yamlExtraDeps = fromYamlExtraDep <$> fromMaybe mempty (c ^. cExtraDeps)
70− defaultPackage = StackPackage (StackFilePath ".") False
74+ defaultPackage = StackPackage (StackFilePath ".") False Nothing
7175
72−fromYamlPackage :: Yaml.Package -> StackPackage
76+
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
7382fromYamlPackage = \case
7483 Yaml.Simple p ->
75− StackPackage (parseSimplePath p) False
76− Yaml.LocationSimple (Yaml.Location p extraDep) ->
77− StackPackage (parseSimplePath p) (fromMaybe False extraDep)
78− Yaml.LocationGit (Location git extraDep) ->
79− StackPackage (StackRepo $ fromYamlGit git) (fromMaybe False extraDep)
80− Yaml.LocationHg (Location hg extraDep) ->
81− StackPackage (StackRepo $ fromYamlHg hg) (fromMaybe False extraDep)
84+ unroll Nothing $ StackPackage (parseSimplePath p) False
85+ Yaml.LocationSimple (Location p extraDep ms) ->
86+ unroll ms $ StackPackage (parseSimplePath p) (fromMaybe False extraDep)
87+ Yaml.LocationGit (Location git extraDep ms) ->
88+ unroll ms $ StackPackage (StackRepo $ fromYamlGit git) (fromMaybe False extraDep)
89+ Yaml.LocationHg (Location hg extraDep ms) ->
90+ unroll ms $ StackPackage (StackRepo $ fromYamlHg hg) (fromMaybe False extraDep)
8291 where
8392 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 :| []
8498
8599fromYamlExtraDep :: Text -> StackPackage
86−fromYamlExtraDep = flip StackPackage True . HackagePackage
100+fromYamlExtraDep t = StackPackage (HackagePackage t) True Nothing
87101
88102fromYamlGit :: Yaml.Git -> Repo
89103fromYamlGit yg = Repo{..}