@@ -1,4 +1,6 @@
1{-# LANGUAGE NoImplicitPrelude #-}
1{-# LANGUAGE NoImplicitPrelude #-}
2+{-# LANGUAGE DeriveDataTypeable #-}
3+{-# LANGUAGE TupleSections #-}
2{-# LANGUAGE RecordWildCards #-}
4{-# LANGUAGE RecordWildCards #-}
3{-# LANGUAGE OverloadedStrings #-}
5{-# LANGUAGE OverloadedStrings #-}
4{-# LANGUAGE DeriveFunctor #-}
6{-# LANGUAGE DeriveFunctor #-}
@@ -146,32 +148,76 @@ instance FromJSON TestState where
146newBuildPlan :: MonadIO m => m (BuildPlan FlatComponent)
148newBuildPlan :: MonadIO m => m (BuildPlan FlatComponent)
147newBuildPlan = liftIO $ do
149newBuildPlan = liftIO $ do
148 core <- getCorePackages
150 core <- getCorePackages
151+ coreExes <- getCoreExecutables
149 extraOrig <- getLatestDescriptions (isAllowed core) mkPackageBuild
152 extraOrig <- getLatestDescriptions (isAllowed core) mkPackageBuild
153+ let toolMap = makeToolMap extraOrig
154+ extra = populateUsers $ removeUnincluded toolMap extraOrig
155+ toolNames :: [ExeName]
150− let toolNames = concatMap (seTools . fcExtra . pbDesc) extraOrig -- FIXME extraOrig ==> extra
156+ toolNames = concatMap (Map.keys . seTools . fcExtra . pbDesc) extra
151− extra = populateUsers $ removeUnincluded (Map.keysSet toolNames) extraOrig
157+ tools <- topologicalSortTools toolMap $ mapFromList $ do
158+ exeName <- toolNames
159+ guard $ exeName `notMember` coreExes
160+ packageName <- maybe mempty setToList $ lookup exeName toolMap
161+ packageBuild <- maybeToList $ lookup packageName extraOrig
162+ return (packageName, packageBuild)
152 return BuildPlan
163 return BuildPlan
153 { bpCore = core
164 { bpCore = core
154− , bpTools = topologicalSort
165+ , bpTools = tools
155− $ filter (\(x, _) -> x `member` toolNames)
157 , bpExtra = extra
166 , bpExtra = extra
158 , bpGlobalFlags = defaultGlobalFlags
167 , bpGlobalFlags = defaultGlobalFlags
170+makeToolMap :: Map PackageName (PackageBuild FlatComponent)
171+ -> Map ExeName (Set PackageName)
173+ unionsWith (++) . map go . mapToList
175+ go (packageName, pb) =
176+ foldMap go' $ seProvidedExes $ fcExtra $ pbDesc pb
178+ go' exeName = singletonMap exeName (singletonSet packageName)
180+topologicalSortTools :: MonadThrow m
181+ => Map ExeName (Set PackageName)
161−topologicalSort :: [(PackageName, PackageBuild FlatComponent)]
182+ -> Map PackageName (PackageBuild FlatComponent)
162− -> Vector (PackageName, Version)
183+ -> m (Vector (PackageName, Version))
163−topologicalSort = fromList . fmap (fmap pbVersion) -- FIXME
184+topologicalSortTools toolMap = topologicalSort
186+ (concatMap (fromMaybe mempty . flip lookup toolMap) . Map.keys . seTools . fcExtra . pbDesc)
188+topologicalSort :: (Ord key, Show key, MonadThrow m, Typeable key)
189+ => (value -> finalValue)
190+ -> (value -> Set key) -- ^ deps
192+ -> m (Vector (key, finalValue))
193+topologicalSort toFinal toDeps =
194+ loop id . mapWithKey removeSelfDeps . fmap (toDeps &&& toFinal)
196+ removeSelfDeps k (deps, final) = (deleteSet k deps, final)
197+ loop front toProcess | null toProcess = return $ pack $ front []
198+ loop front toProcess
199+ | null noDeps = throwM $ NoEmptyDeps (map fst toProcess')
200+ | otherwise = loop (front . noDeps') (mapFromList hasDeps)
202+ toProcess' = fmap (first removeUnavailable) toProcess
203+ allKeys = Map.keysSet toProcess
204+ removeUnavailable = asSet . setFromList . filter (`member` allKeys) . setToList
205+ (noDeps, hasDeps) = partition (null . fst . snd) $ mapToList toProcess'
206+ noDeps' = (map (second snd) noDeps ++)
208+data TopologicalSortException key = NoEmptyDeps (Map key (Set key))
209+ deriving (Show, Typeable)
210+instance (Show key, Typeable key) => Exception (TopologicalSortException key)
165−removeUnincluded :: Set PackageName -- ^ tool names
212+removeUnincluded :: Map ExeName (Set PackageName)
166 -> Map PackageName (PackageBuild FlatComponent)
213 -> Map PackageName (PackageBuild FlatComponent)
167 -> Map PackageName (PackageBuild FlatComponent)
214 -> Map PackageName (PackageBuild FlatComponent)
168−removeUnincluded toolNames orig =
215+removeUnincluded toolMap orig =
169 mapFromList $ filter (\(x, _) -> x `member` included) $ mapToList orig
216 mapFromList $ filter (\(x, _) -> x `member` included) $ mapToList orig
171 included :: Set PackageName
218 included :: Set PackageName
172− included = flip execState mempty $ do
219+ included = flip execState mempty $
173 mapM_ (add . fst) $ mapToList $ pcPackages defaultPackageConstraints
220 mapM_ (add . fst) $ mapToList $ pcPackages defaultPackageConstraints
174− mapM_ add toolNames -- FIXME remove this
176 add name = do
222 add name = do
177 inc <- get
223 inc <- get
@@ -179,8 +225,10 @@ removeUnincluded toolNames orig =
179 put $ insertSet name inc
225 put $ insertSet name inc
180 case lookup name orig of
226 case lookup name orig of
181 Nothing -> return ()
227 Nothing -> return ()
182− Just pb -> mapM_ (add . fst) $ mapToList $ fcDeps $ pbDesc pb
229+ mapM_ (add . fst) $ mapToList $ fcDeps $ pbDesc pb
183− -- FIXME add tools here
230+ forM_ (map fst $ mapToList $ seTools $ fcExtra $ pbDesc pb) $
231+ \exeName -> mapM_ add $ fromMaybe mempty $ lookup exeName toolMap
185populateUsers :: Map PackageName (PackageBuild FlatComponent)
233populateUsers :: Map PackageName (PackageBuild FlatComponent)
186 -> Map PackageName (PackageBuild FlatComponent)
234 -> Map PackageName (PackageBuild FlatComponent)