mirror of
https://github.com/commercialhaskell/stackage.git
synced 2026-02-16 16:25:49 +01:00
Track which components have which dependencies
This commit is contained in:
parent
0a234a5f51
commit
4ede5f0d9a
@ -3,6 +3,7 @@
|
|||||||
{-# LANGUAGE NoImplicitPrelude #-}
|
{-# LANGUAGE NoImplicitPrelude #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE RecordWildCards #-}
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
|
{-# LANGUAGE ViewPatterns #-}
|
||||||
-- | Confirm that a build plan has a consistent set of dependencies.
|
-- | Confirm that a build plan has a consistent set of dependencies.
|
||||||
module Stackage2.CheckBuildPlan
|
module Stackage2.CheckBuildPlan
|
||||||
( checkBuildPlan
|
( checkBuildPlan
|
||||||
@ -14,6 +15,9 @@ import Stackage2.BuildPlan
|
|||||||
import Stackage2.PackageDescription
|
import Stackage2.PackageDescription
|
||||||
import Stackage2.Prelude
|
import Stackage2.Prelude
|
||||||
|
|
||||||
|
-- FIXME check cycles in dependencies, only looking at libraries and
|
||||||
|
-- executables
|
||||||
|
|
||||||
checkBuildPlan :: MonadThrow m => BuildPlan -> m ()
|
checkBuildPlan :: MonadThrow m => BuildPlan -> m ()
|
||||||
checkBuildPlan BuildPlan {..}
|
checkBuildPlan BuildPlan {..}
|
||||||
| null errs' = return ()
|
| null errs' = return ()
|
||||||
@ -29,7 +33,7 @@ checkDeps :: Map PackageName Version
|
|||||||
checkDeps allPackages (user, pb) =
|
checkDeps allPackages (user, pb) =
|
||||||
mapM_ go $ mapToList $ sdPackages $ ppDesc pb
|
mapM_ go $ mapToList $ sdPackages $ ppDesc pb
|
||||||
where
|
where
|
||||||
go (dep, range) =
|
go (dep, diRange -> range) =
|
||||||
case lookup dep allPackages of
|
case lookup dep allPackages of
|
||||||
Nothing -> tell $ BadBuildPlan $ singletonMap (dep, Nothing) errMap
|
Nothing -> tell $ BadBuildPlan $ singletonMap (dep, Nothing) errMap
|
||||||
Just version
|
Just version
|
||||||
|
|||||||
@ -13,6 +13,8 @@ module Stackage2.PackageDescription
|
|||||||
( SimpleDesc (..)
|
( SimpleDesc (..)
|
||||||
, toSimpleDesc
|
, toSimpleDesc
|
||||||
, CheckCond (..)
|
, CheckCond (..)
|
||||||
|
, Component (..)
|
||||||
|
, DepInfo (..)
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Monad.Writer.Strict (MonadWriter, execWriterT,
|
import Control.Monad.Writer.Strict (MonadWriter, execWriterT,
|
||||||
@ -25,6 +27,49 @@ import Distribution.PackageDescription
|
|||||||
import Distribution.System (Arch, OS)
|
import Distribution.System (Arch, OS)
|
||||||
import Stackage2.Prelude
|
import Stackage2.Prelude
|
||||||
|
|
||||||
|
data Component = CompLibrary
|
||||||
|
| CompExecutable
|
||||||
|
| CompTestSuite
|
||||||
|
| CompBenchmark
|
||||||
|
deriving (Show, Read, Eq, Ord, Enum, Bounded)
|
||||||
|
|
||||||
|
compToText :: Component -> Text
|
||||||
|
compToText CompLibrary = "library"
|
||||||
|
compToText CompExecutable = "executable"
|
||||||
|
compToText CompTestSuite = "test-suite"
|
||||||
|
compToText CompBenchmark = "benchmark"
|
||||||
|
|
||||||
|
instance ToJSON Component where
|
||||||
|
toJSON = toJSON . compToText
|
||||||
|
instance FromJSON Component where
|
||||||
|
parseJSON = withText "Component" $ \t -> maybe
|
||||||
|
(fail $ "Invalid component: " ++ unpack t)
|
||||||
|
return
|
||||||
|
(lookup t comps)
|
||||||
|
where
|
||||||
|
comps = asHashMap $ mapFromList $ map (compToText &&& id) [minBound..maxBound]
|
||||||
|
|
||||||
|
data DepInfo = DepInfo
|
||||||
|
{ diComponents :: Set Component
|
||||||
|
, diRange :: VersionRange
|
||||||
|
}
|
||||||
|
deriving (Show, Eq)
|
||||||
|
|
||||||
|
instance Semigroup DepInfo where
|
||||||
|
DepInfo a x <> DepInfo b y = DepInfo
|
||||||
|
(a <> b)
|
||||||
|
(intersectVersionRanges x y)
|
||||||
|
instance ToJSON DepInfo where
|
||||||
|
toJSON DepInfo {..} = object
|
||||||
|
[ "components" .= diComponents
|
||||||
|
, "range" .= display diRange
|
||||||
|
]
|
||||||
|
instance FromJSON DepInfo where
|
||||||
|
parseJSON = withObject "DepInfo" $ \o -> do
|
||||||
|
diComponents <- o .: "components"
|
||||||
|
diRange <- o .: "range" >>= either (fail . show) return . simpleParse
|
||||||
|
return DepInfo {..}
|
||||||
|
|
||||||
-- | A simplified package description that tracks:
|
-- | A simplified package description that tracks:
|
||||||
--
|
--
|
||||||
-- * Package dependencies
|
-- * Package dependencies
|
||||||
@ -35,33 +80,27 @@ import Stackage2.Prelude
|
|||||||
--
|
--
|
||||||
-- It has fully resolved all conditionals
|
-- It has fully resolved all conditionals
|
||||||
data SimpleDesc = SimpleDesc
|
data SimpleDesc = SimpleDesc
|
||||||
{ sdPackages :: Map PackageName VersionRange
|
{ sdPackages :: Map PackageName DepInfo
|
||||||
, sdTools :: Map ExeName VersionRange
|
, sdTools :: Map ExeName DepInfo
|
||||||
, sdProvidedExes :: Set ExeName
|
, sdProvidedExes :: Set ExeName
|
||||||
}
|
}
|
||||||
deriving (Show, Eq)
|
deriving (Show, Eq)
|
||||||
instance Monoid SimpleDesc where
|
instance Monoid SimpleDesc where
|
||||||
mempty = SimpleDesc mempty mempty mempty
|
mempty = SimpleDesc mempty mempty mempty
|
||||||
mappend (SimpleDesc a b c) (SimpleDesc x y z) = SimpleDesc
|
mappend (SimpleDesc a b c) (SimpleDesc x y z) = SimpleDesc
|
||||||
(unionWith intersectVersionRanges a x)
|
(unionWith (<>) a x)
|
||||||
(unionWith intersectVersionRanges b y)
|
(unionWith (<>) b y)
|
||||||
(c ++ z)
|
(c ++ z)
|
||||||
instance ToJSON SimpleDesc where
|
instance ToJSON SimpleDesc where
|
||||||
toJSON SimpleDesc {..} = object
|
toJSON SimpleDesc {..} = object
|
||||||
[ "packages" .= Map.mapKeysWith const unPackageName (map display sdPackages)
|
[ "packages" .= Map.mapKeysWith const unPackageName sdPackages
|
||||||
, "tools" .= Map.mapKeysWith const unExeName (map display sdTools)
|
, "tools" .= Map.mapKeysWith const unExeName sdTools
|
||||||
, "provided-exes" .= sdProvidedExes
|
, "provided-exes" .= sdProvidedExes
|
||||||
]
|
]
|
||||||
instance FromJSON SimpleDesc where
|
instance FromJSON SimpleDesc where
|
||||||
parseJSON = withObject "SimpleDesc" $ \o -> do
|
parseJSON = withObject "SimpleDesc" $ \o -> do
|
||||||
sdPackages <- (o .: "packages") >>=
|
sdPackages <- Map.mapKeysWith const mkPackageName <$> (o .: "packages")
|
||||||
either (fail . show) return .
|
sdTools <- Map.mapKeysWith const ExeName <$> (o .: "tools")
|
||||||
mapM simpleParse .
|
|
||||||
Map.mapKeysWith const mkPackageName
|
|
||||||
sdTools <- (o .: "tools") >>=
|
|
||||||
either (fail . show) return .
|
|
||||||
mapM simpleParse .
|
|
||||||
Map.mapKeysWith const ExeName
|
|
||||||
sdProvidedExes <- o .: "provided-exes"
|
sdProvidedExes <- o .: "provided-exes"
|
||||||
return SimpleDesc {..}
|
return SimpleDesc {..}
|
||||||
|
|
||||||
@ -72,39 +111,46 @@ toSimpleDesc :: MonadThrow m
|
|||||||
-> GenericPackageDescription
|
-> GenericPackageDescription
|
||||||
-> m SimpleDesc
|
-> m SimpleDesc
|
||||||
toSimpleDesc cc gpd = execWriterT $ do
|
toSimpleDesc cc gpd = execWriterT $ do
|
||||||
forM_ (condLibrary gpd) $ tellTree cc libBuildInfo
|
forM_ (condLibrary gpd) $ tellTree cc CompLibrary libBuildInfo
|
||||||
forM_ (condExecutables gpd) $ tellTree cc buildInfo . snd
|
forM_ (condExecutables gpd) $ tellTree cc CompExecutable buildInfo . snd
|
||||||
tell mempty { sdProvidedExes = setFromList
|
tell mempty { sdProvidedExes = setFromList
|
||||||
$ map (fromString . fst)
|
$ map (fromString . fst)
|
||||||
$ condExecutables gpd
|
$ condExecutables gpd
|
||||||
}
|
}
|
||||||
when (ccIncludeTests cc) $ forM_ (condTestSuites gpd)
|
when (ccIncludeTests cc) $ forM_ (condTestSuites gpd)
|
||||||
$ tellTree cc testBuildInfo . snd
|
$ tellTree cc CompTestSuite testBuildInfo . snd
|
||||||
when (ccIncludeBenchmarks cc) $ forM_ (condBenchmarks gpd)
|
when (ccIncludeBenchmarks cc) $ forM_ (condBenchmarks gpd)
|
||||||
$ tellTree cc benchmarkBuildInfo . snd
|
$ tellTree cc CompBenchmark benchmarkBuildInfo . snd
|
||||||
|
|
||||||
-- | Convert a single CondTree to a 'SimpleDesc'.
|
-- | Convert a single CondTree to a 'SimpleDesc'.
|
||||||
tellTree :: (MonadWriter SimpleDesc m, MonadThrow m)
|
tellTree :: (MonadWriter SimpleDesc m, MonadThrow m)
|
||||||
=> CheckCond
|
=> CheckCond
|
||||||
|
-> Component
|
||||||
-> (a -> BuildInfo)
|
-> (a -> BuildInfo)
|
||||||
-> CondTree ConfVar [Dependency] a
|
-> CondTree ConfVar [Dependency] a
|
||||||
-> m ()
|
-> m ()
|
||||||
tellTree cc getBI (CondNode dat deps comps) = do
|
tellTree cc component getBI (CondNode dat deps comps) = do
|
||||||
tell mempty
|
tell mempty
|
||||||
{ sdPackages = unionsWith intersectVersionRanges $ flip map deps
|
{ sdPackages = unionsWith (<>) $ flip map deps
|
||||||
$ \(Dependency x y) -> singletonMap x $ simplifyVersionRange y
|
$ \(Dependency x y) -> singletonMap x DepInfo
|
||||||
, sdTools = unionsWith intersectVersionRanges $ flip map (buildTools $ getBI dat)
|
{ diComponents = singletonSet component
|
||||||
|
, diRange = simplifyVersionRange y
|
||||||
|
}
|
||||||
|
, sdTools = unionsWith (<>) $ flip map (buildTools $ getBI dat)
|
||||||
$ \(Dependency name range) -> singletonMap
|
$ \(Dependency name range) -> singletonMap
|
||||||
-- In practice, cabal files refer to the exe name, not the
|
-- In practice, cabal files refer to the exe name, not the
|
||||||
-- package name.
|
-- package name.
|
||||||
(ExeName $ unPackageName name)
|
(ExeName $ unPackageName name)
|
||||||
(simplifyVersionRange range)
|
DepInfo
|
||||||
|
{ diComponents = singletonSet component
|
||||||
|
, diRange = simplifyVersionRange range
|
||||||
|
}
|
||||||
}
|
}
|
||||||
forM_ comps $ \(cond, ontrue, onfalse) -> do
|
forM_ comps $ \(cond, ontrue, onfalse) -> do
|
||||||
b <- checkCond cc cond
|
b <- checkCond cc cond
|
||||||
if b
|
if b
|
||||||
then tellTree cc getBI ontrue
|
then tellTree cc component getBI ontrue
|
||||||
else maybe (return ()) (tellTree cc getBI) onfalse
|
else maybe (return ()) (tellTree cc component getBI) onfalse
|
||||||
|
|
||||||
-- | Resolve a condition to a boolean based on the provided 'CheckCond'.
|
-- | Resolve a condition to a boolean based on the provided 'CheckCond'.
|
||||||
checkCond :: MonadThrow m => CheckCond -> Condition ConfVar -> m Bool
|
checkCond :: MonadThrow m => CheckCond -> Condition ConfVar -> m Bool
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user