1{-# LANGUAGE DeriveDataTypeable #-}
2{-# LANGUAGE DeriveFoldable #-}
3{-# LANGUAGE DeriveFunctor #-}
4{-# LANGUAGE DeriveTraversable #-}
5{-# LANGUAGE NoImplicitPrelude #-}
6{-# LANGUAGE OverloadedStrings #-}
7{-# LANGUAGE RecordWildCards #-}
8{-# LANGUAGE TupleSections #-}
9{-# LANGUAGE TypeFamilies #-}
10-- | Representation of a concrete build plan, and how to generate a new one
11-- based on constraints.
12module Stackage.BuildPlan
17 , getLatestAllowedPlans
20import Control.Monad.State.Strict (execState, get, put)
22import qualified Data.Map as Map
23import qualified Data.Set as Set
24import qualified Distribution.Compiler
25import Distribution.PackageDescription
26import Stackage.BuildConstraints
27import Stackage.GithubPings
28import Stackage.PackageDescription
29import Stackage.PackageIndex
30import Stackage.Prelude
32data BuildPlan = BuildPlan
33 { bpSystemInfo :: SystemInfo
34 , bpTools :: Vector (PackageName, Version)
35 , bpPackages :: Map PackageName PackagePlan
36 , bpGithubUsers :: Map Text (Set Text)
40instance ToJSON BuildPlan where
41 toJSON BuildPlan {..} = object
42 [ "system-info" .= bpSystemInfo
43 , "tools" .= map goTool bpTools
44 , "packages" .= Map.mapKeysWith const unPackageName bpPackages
45 , "github-users" .= bpGithubUsers
48 goTool (k, v) = object
50 , "version" .= display v
52instance FromJSON BuildPlan where
53 parseJSON = withObject "BuildPlan" $ \o -> do
54 bpSystemInfo <- o .: "system-info"
55 bpTools <- (o .: "tools") >>= mapM goTool
56 bpPackages <- Map.mapKeysWith const mkPackageName <$> (o .: "packages")
57 bpGithubUsers <- o .:? "github-users" .!= mempty
60 goTool = withObject "Tool" $ \o -> (,)
61 <$> ((o .: "name") >>=
62 either (fail . show) return . simpleParse . asText)
63 <*> ((o .: "version") >>=
64 either (fail . show) return . simpleParse . asText)
66data PackagePlan = PackagePlan
67 { ppVersion :: Version
68 , ppGithubPings :: Set Text
69 , ppUsers :: Set PackageName
70 , ppConstraints :: PackageConstraints
71 , ppDesc :: SimpleDesc
75instance ToJSON PackagePlan where
76 toJSON PackagePlan {..} = object
77 [ "version" .= asText (display ppVersion)
78 , "github-pings" .= ppGithubPings
79 , "users" .= map unPackageName (unpack ppUsers)
80 , "constraints" .= ppConstraints
81 , "description" .= ppDesc
83instance FromJSON PackagePlan where
84 parseJSON = withObject "PackageBuild" $ \o -> do
85 ppVersion <- o .: "version"
86 >>= either (fail . show) return
87 . simpleParse . asText
88 ppGithubPings <- o .:? "github-pings" .!= mempty
89 ppUsers <- Set.map PackageName <$> (o .:? "users" .!= mempty)
90 ppConstraints <- o .: "constraints"
91 ppDesc <- o .: "description"
92 return PackagePlan {..}
94-- | Make a build plan given these package set and build constraints.
95newBuildPlan :: MonadIO m => Map PackageName PackagePlan -> BuildConstraints -> m BuildPlan
96newBuildPlan packagesOrig bc@BuildConstraints {..} = liftIO $ do
97 let toolMap = makeToolMap packagesOrig
98 packages = populateUsers $ removeUnincluded bc toolMap packagesOrig
99 toolNames :: [ExeName]
100 toolNames = concatMap (Map.keys . sdTools . ppDesc) packages
101 tools <- topologicalSortTools toolMap $ mapFromList $ do
103 guard $ exeName `notMember` siCoreExecutables
104 packageName <- maybe mempty setToList $ lookup exeName toolMap
105 packagePlan <- maybeToList $ lookup packageName packagesOrig
106 return (packageName, packagePlan)
107 -- FIXME topologically sort packages? maybe just leave that to the build phase
109 { bpSystemInfo = bcSystemInfo
111 , bpPackages = packages
112 , bpGithubUsers = bcGithubUsers
115 SystemInfo {..} = bcSystemInfo
117makeToolMap :: Map PackageName PackagePlan
118 -> Map ExeName (Set PackageName)
120 unionsWith (++) . map go . mapToList
122 go (packageName, pp) =
123 foldMap go' $ sdProvidedExes $ ppDesc pp
125 go' exeName = singletonMap exeName (singletonSet packageName)
127topologicalSortTools :: MonadThrow m
128 => Map ExeName (Set PackageName)
129 -> Map PackageName PackagePlan
130 -> m (Vector (PackageName, Version))
131topologicalSortTools toolMap = topologicalSort
133 (concatMap (fromMaybe mempty . flip lookup toolMap) . Map.keys . sdTools . ppDesc)
135-- | Include only packages which are dependencies of the required packages and
137removeUnincluded :: BuildConstraints
138 -> Map ExeName (Set PackageName)
139 -> Map PackageName PackagePlan
140 -> Map PackageName PackagePlan
141removeUnincluded BuildConstraints {..} toolMap orig =
142 mapFromList $ filter (\(x, _) -> x `member` included) $ mapToList orig
144 SystemInfo {..} = bcSystemInfo
146 included :: Set PackageName
147 included = flip execState mempty $ mapM_ add bcPackages
151 when (name `notMember` inc) $ do
152 put $ insertSet name inc
153 case lookup name orig of
156 mapM_ add $ Map.keys $ sdPackages $ ppDesc pb
157 forM_ (Map.keys $ sdTools $ ppDesc pb) $
158 \exeName -> when (exeName `notMember` siCoreExecutables)
159 $ mapM_ add $ fromMaybe mempty $ lookup exeName toolMap
161populateUsers :: Map PackageName PackagePlan
162 -> Map PackageName PackagePlan
166 go name pb = pb { ppUsers = foldMap (go2 name) (mapToList orig) }
169 | dep `member` sdPackages (ppDesc pb) = singletonSet user
172-- | Check whether the given package/version combo meets the constraints
173-- currently in place.
174isAllowed :: BuildConstraints
175 -> PackageName -> Version -> Bool
176isAllowed bc = \name version ->
177 case lookup name $ siCorePackages $ bcSystemInfo bc of
178 Just _ -> False -- never reinstall a core package
179 Nothing -> withinRange version $ pcVersionRange $ bcPackageConstraints bc name
181mkPackagePlan :: MonadThrow m
183 -> GenericPackageDescription
185mkPackagePlan bc gpd = do
186 ppDesc <- toSimpleDesc CheckCond {..} gpd
187 return PackagePlan {..}
189 PackageIdentifier name ppVersion = package $ packageDescription gpd
190 ppGithubPings = getGithubPings bc gpd
191 ppConstraints = bcPackageConstraints bc name
192 ppUsers = mempty -- must be filled in later
197 ccCompilerFlavor = Distribution.Compiler.GHC
198 ccCompilerVersion = siGhcVersion
200 ccIncludeTests = pcTests ppConstraints /= Don'tBuild
201 ccIncludeBenchmarks = pcBuildBenchmarks ppConstraints
203 SystemInfo {..} = bcSystemInfo bc
205 overrides = pcFlagOverrides ppConstraints
206 getFlag MkFlag {..} =
207 (flagName, fromMaybe flagDefault $ lookup flagName overrides)
208 flags = mapFromList $ map getFlag $ genPackageFlags gpd
210getLatestAllowedPlans :: MonadIO m => BuildConstraints -> m (Map PackageName PackagePlan)
211getLatestAllowedPlans bc =
212 getLatestDescriptions
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list