@@ -1,4 +1,6 @@
11{-# LANGUAGE NoImplicitPrelude #-}
2+{-# LANGUAGE DeriveDataTypeable #-}
3+{-# LANGUAGE TupleSections #-}
24{-# LANGUAGE RecordWildCards #-}
35{-# LANGUAGE OverloadedStrings #-}
46{-# LANGUAGE DeriveFunctor #-}
@@ -146,32 +148,76 @@ instance FromJSON TestState where
146148newBuildPlan :: MonadIO m => m (BuildPlan FlatComponent)
147149newBuildPlan = liftIO $ do
148150 core <- getCorePackages
151+ coreExes <- getCoreExecutables
149152 extraOrig <- getLatestDescriptions (isAllowed core) mkPackageBuild
150− let toolNames = concatMap (seTools . fcExtra . pbDesc) extraOrig -- FIXME extraOrig ==> extra
151− extra = populateUsers $ removeUnincluded (Map.keysSet toolNames) extraOrig
153+ let toolMap = makeToolMap extraOrig
154+ extra = populateUsers $ removeUnincluded toolMap extraOrig
155+ toolNames :: [ExeName]
156+ toolNames = concatMap (Map.keys . seTools . fcExtra . pbDesc) extra
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)
152163 return BuildPlan
153164 { bpCore = core
154− , bpTools = topologicalSort
155− $ filter (\(x, _) -> x `member` toolNames)
156− $ mapToList extra
165+ , bpTools = tools
157166 , bpExtra = extra
158167 , bpGlobalFlags = defaultGlobalFlags
159168 }
160169
161−topologicalSort :: [(PackageName, PackageBuild FlatComponent)]
162− -> Vector (PackageName, Version)
163−topologicalSort = fromList . fmap (fmap pbVersion) -- FIXME
170+makeToolMap :: Map PackageName (PackageBuild FlatComponent)
171+ -> Map ExeName (Set PackageName)
172+makeToolMap =
173+ unionsWith (++) . map go . mapToList
174+ where
175+ go (packageName, pb) =
176+ foldMap go' $ seProvidedExes $ fcExtra $ pbDesc pb
177+ where
178+ go' exeName = singletonMap exeName (singletonSet packageName)
179+
180+topologicalSortTools :: MonadThrow m
181+ => Map ExeName (Set PackageName)
182+ -> Map PackageName (PackageBuild FlatComponent)
183+ -> m (Vector (PackageName, Version))
184+topologicalSortTools toolMap = topologicalSort
185+ pbVersion
186+ (concatMap (fromMaybe mempty . flip lookup toolMap) . Map.keys . seTools . fcExtra . pbDesc)
187+
188+topologicalSort :: (Ord key, Show key, MonadThrow m, Typeable key)
189+ => (value -> finalValue)
190+ -> (value -> Set key) -- ^ deps
191+ -> Map key value
192+ -> m (Vector (key, finalValue))
193+topologicalSort toFinal toDeps =
194+ loop id . mapWithKey removeSelfDeps . fmap (toDeps &&& toFinal)
195+ where
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)
201+ where
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 ++)
207+
208+data TopologicalSortException key = NoEmptyDeps (Map key (Set key))
209+ deriving (Show, Typeable)
210+instance (Show key, Typeable key) => Exception (TopologicalSortException key)
164211
165−removeUnincluded :: Set PackageName -- ^ tool names
212+removeUnincluded :: Map ExeName (Set PackageName)
166213 -> Map PackageName (PackageBuild FlatComponent)
167214 -> Map PackageName (PackageBuild FlatComponent)
168−removeUnincluded toolNames orig =
215+removeUnincluded toolMap orig =
169216 mapFromList $ filter (\(x, _) -> x `member` included) $ mapToList orig
170217 where
171218 included :: Set PackageName
172− included = flip execState mempty $ do
219+ included = flip execState mempty $
173220 mapM_ (add . fst) $ mapToList $ pcPackages defaultPackageConstraints
174− mapM_ add toolNames -- FIXME remove this
175221
176222 add name = do
177223 inc <- get
@@ -179,8 +225,10 @@ removeUnincluded toolNames orig =
179225 put $ insertSet name inc
180226 case lookup name orig of
181227 Nothing -> return ()
182− Just pb -> mapM_ (add . fst) $ mapToList $ fcDeps $ pbDesc pb
183− -- FIXME add tools here
228+ Just pb -> do
229+ mapM_ (add . fst) $ mapToList $ fcDeps $ pbDesc pb
230+ forM_ (map fst $ mapToList $ seTools $ fcExtra $ pbDesc pb) $
231+ \exeName -> mapM_ add $ fromMaybe mempty $ lookup exeName toolMap
184232
185233populateUsers :: Map PackageName (PackageBuild FlatComponent)
186234 -> Map PackageName (PackageBuild FlatComponent)