{-# LANGUAGE CPP #-}
module Distribution.RPM.Build.Graph
(PackageGraph,
createGraph,
createGraphRpmOpts,
createGraph1,
createGraph2,
createGraph3,
createGraph4,
createGraph',
createGraph'',
createGraph''',
createGraph'''',
dependencyNodes,
subgraph',
packageLayers,
lowestLayer,
lowestLayer',
packageLeaves,
separatePackages,
printGraph,
renderGraph,
depsGraph,
depsGraphDeps,
Components (..),
topsortGraph,
) where
import Data.Graph.Inductive.Query.DFS (components, scc, topsort', xdfsWith)
import Data.Graph.Inductive.Query.SP (sp)
import Data.Graph.Inductive.PatriciaTree (Gr)
import qualified Data.Graph.Inductive.Graph as G
#if !MIN_VERSION_base(4,8,0)
import Control.Applicative ((<$>))
#endif
import Control.Monad.Extra (forM_, guard, when, unless, unlessM)
import Data.Maybe (catMaybes, fromMaybe, mapMaybe)
import Data.List.Extra
import Data.GraphViz
import SimpleCmd
import System.Directory (doesDirectoryExist, doesFileExist,
withCurrentDirectory, listDirectory)
import System.FilePath
import Distribution.RPM.Build.ProvReqs (rpmspecProvidesBuildRequires)
data SourcePackage =
SourcePackage {
SourcePackage -> String
packagePath :: FilePath,
SourcePackage -> [String]
dependencies :: [FilePath]
}
deriving SourcePackage -> SourcePackage -> Bool
(SourcePackage -> SourcePackage -> Bool)
-> (SourcePackage -> SourcePackage -> Bool) -> Eq SourcePackage
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SourcePackage -> SourcePackage -> Bool
== :: SourcePackage -> SourcePackage -> Bool
$c/= :: SourcePackage -> SourcePackage -> Bool
/= :: SourcePackage -> SourcePackage -> Bool
Eq
type PackageGraph = Gr FilePath ()
dependencyNodes :: [FilePath]
-> PackageGraph
-> [FilePath]
dependencyNodes :: [String] -> PackageGraph -> [String]
dependencyNodes [String]
subset PackageGraph
graph =
let nodes :: [LNode String]
nodes = PackageGraph -> [LNode String]
forall a b. Gr a b -> [LNode a]
forall (gr :: * -> * -> *) a b. Graph gr => gr a b -> [LNode a]
G.labNodes PackageGraph
graph
subnodes :: [Node]
subnodes = (String -> Maybe Node) -> [String] -> [Node]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe ([LNode String] -> String -> Maybe Node
pkgNode [LNode String]
nodes) [String]
subset
in CFun String () [Node]
-> CFun String () String -> [Node] -> PackageGraph -> [String]
forall (gr :: * -> * -> *) a b c.
Graph gr =>
CFun a b [Node] -> CFun a b c -> [Node] -> gr a b -> [c]
xdfsWith CFun String () [Node]
forall a b. Context a b -> [Node]
G.pre' CFun String () String
forall {a} {b} {c} {d}. (a, b, c, d) -> c
third [Node]
subnodes PackageGraph
graph
where
pkgNode :: [G.LNode FilePath] -> FilePath -> Maybe Int
pkgNode :: [LNode String] -> String -> Maybe Node
pkgNode [] String
_ = Maybe Node
forall a. Maybe a
Nothing
pkgNode ((Node
i,String
l):[LNode String]
ns) String
p = if String -> String -> String
forall a. Eq a => [a] -> [a] -> [a]
dropSuffix String
"/" String
p String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String -> String -> String
forall a. Eq a => [a] -> [a] -> [a]
dropSuffix String
"/" String
l then Node -> Maybe Node
forall a. a -> Maybe a
Just Node
i else [LNode String] -> String -> Maybe Node
pkgNode [LNode String]
ns String
p
third :: (a, b, c, d) -> c
third (a
_, b
_, c
c, d
_) = c
c
createGraph :: [FilePath]
-> IO PackageGraph
createGraph :: [String] -> IO PackageGraph
createGraph = Bool -> Bool -> Bool -> Maybe String -> [String] -> IO PackageGraph
createGraph1 Bool
False Bool
False Bool
True Maybe String
forall a. Maybe a
Nothing
createGraphRpmOpts :: [String]
-> [FilePath]
-> IO PackageGraph
createGraphRpmOpts :: [String] -> [String] -> IO PackageGraph
createGraphRpmOpts [String]
rpmopts =
[String]
-> Bool
-> Bool
-> Bool
-> Maybe String
-> [String]
-> IO PackageGraph
createGraph2 [String]
rpmopts Bool
False Bool
False Bool
True Maybe String
forall a. Maybe a
Nothing
createGraph1 :: Bool
-> Bool
-> Bool
-> Maybe FilePath
-> [FilePath]
-> IO PackageGraph
createGraph1 :: Bool -> Bool -> Bool -> Maybe String -> [String] -> IO PackageGraph
createGraph1 = [String]
-> Bool
-> Bool
-> Bool
-> Maybe String
-> [String]
-> IO PackageGraph
createGraph2 []
createGraph' :: Bool
-> Bool
-> Bool
-> Maybe FilePath
-> [FilePath]
-> IO PackageGraph
createGraph' :: Bool -> Bool -> Bool -> Maybe String -> [String] -> IO PackageGraph
createGraph' = Bool -> Bool -> Bool -> Maybe String -> [String] -> IO PackageGraph
createGraph1
createGraph2 :: [String]
-> Bool
-> Bool
-> Bool
-> Maybe FilePath
-> [FilePath]
-> IO PackageGraph
createGraph2 :: [String]
-> Bool
-> Bool
-> Bool
-> Maybe String
-> [String]
-> IO PackageGraph
createGraph2 = [String]
-> [String]
-> Bool
-> Bool
-> Bool
-> Maybe String
-> [String]
-> IO PackageGraph
createGraph3 []
createGraph'' :: [String]
-> Bool
-> Bool
-> Bool
-> Maybe FilePath
-> [FilePath]
-> IO PackageGraph
createGraph'' :: [String]
-> Bool
-> Bool
-> Bool
-> Maybe String
-> [String]
-> IO PackageGraph
createGraph'' = [String]
-> Bool
-> Bool
-> Bool
-> Maybe String
-> [String]
-> IO PackageGraph
createGraph2
createGraph3 :: [String]
-> [String]
-> Bool
-> Bool
-> Bool
-> Maybe FilePath
-> [FilePath]
-> IO PackageGraph
createGraph3 :: [String]
-> [String]
-> Bool
-> Bool
-> Bool
-> Maybe String
-> [String]
-> IO PackageGraph
createGraph3 = Bool
-> [String]
-> [String]
-> Bool
-> Bool
-> Bool
-> Maybe String
-> [String]
-> IO PackageGraph
createGraph4 Bool
True
createGraph''' :: [String]
-> [String]
-> Bool
-> Bool
-> Bool
-> Maybe FilePath
-> [FilePath]
-> IO PackageGraph
createGraph''' :: [String]
-> [String]
-> Bool
-> Bool
-> Bool
-> Maybe String
-> [String]
-> IO PackageGraph
createGraph''' = [String]
-> [String]
-> Bool
-> Bool
-> Bool
-> Maybe String
-> [String]
-> IO PackageGraph
createGraph3
createGraph4 :: Bool
-> [String]
-> [String]
-> Bool
-> Bool
-> Bool
-> Maybe FilePath
-> [FilePath]
-> IO PackageGraph
createGraph4 :: Bool
-> [String]
-> [String]
-> Bool
-> Bool
-> Bool
-> Maybe String
-> [String]
-> IO PackageGraph
createGraph4 Bool
checkcycles [String]
ignoredBRs [String]
rpmopts Bool
verbose Bool
lenient Bool
rev Maybe String
mdir [String]
paths =
do
[(String, [String], [String])]
metadata <- [Maybe (String, [String], [String])]
-> [(String, [String], [String])]
forall a. [Maybe a] -> [a]
catMaybes ([Maybe (String, [String], [String])]
-> [(String, [String], [String])])
-> IO [Maybe (String, [String], [String])]
-> IO [(String, [String], [String])]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (String -> IO (Maybe (String, [String], [String])))
-> [String] -> IO [Maybe (String, [String], [String])]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM String -> IO (Maybe (String, [String], [String]))
readSpecMetadata [String]
paths
let realpkgs :: [String]
realpkgs = ((String, [String], [String]) -> String)
-> [(String, [String], [String])] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String, [String], [String]) -> String
forall a b c. (a, b, c) -> a
fst3 [(String, [String], [String])]
metadata
deps :: [[String]]
deps = (String -> Maybe [String]) -> [String] -> [[String]]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe ([(String, [String], [String])] -> String -> Maybe [String]
getDepsSrcResolved [(String, [String], [String])]
metadata) [String]
realpkgs
spkgs :: [SourcePackage]
spkgs = (String -> [String] -> SourcePackage)
-> [String] -> [[String]] -> [SourcePackage]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith String -> [String] -> SourcePackage
SourcePackage [String]
realpkgs [[String]]
deps
graph :: PackageGraph
graph = [SourcePackage] -> PackageGraph
getBuildGraph [SourcePackage]
spkgs
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
checkcycles (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
PackageGraph -> IO ()
checkForCycles PackageGraph
graph
PackageGraph -> IO PackageGraph
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return PackageGraph
graph
where
readSpecMetadata :: FilePath -> IO (Maybe (FilePath,[String],[String]))
readSpecMetadata :: String -> IO (Maybe (String, [String], [String]))
readSpecMetadata String
path = do
Maybe (String, String)
mspecdir <- IO (Maybe (String, String))
findSpec
case Maybe (String, String)
mspecdir of
Maybe (String, String)
Nothing -> Maybe (String, [String], [String])
-> IO (Maybe (String, [String], [String]))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (String, [String], [String])
forall a. Maybe a
Nothing
Just (String
dir,String
spec) -> do
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
verbose (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> IO ()
warning String
spec
String
-> IO (Maybe (String, [String], [String]))
-> IO (Maybe (String, [String], [String]))
forall a. String -> IO a -> IO a
withCurrentDirectory String
dir (IO (Maybe (String, [String], [String]))
-> IO (Maybe (String, [String], [String])))
-> IO (Maybe (String, [String], [String]))
-> IO (Maybe (String, [String], [String]))
forall a b. (a -> b) -> a -> b
$ do
Maybe ([String], [String])
mprovbrs <- Bool -> [String] -> String -> IO (Maybe ([String], [String]))
rpmspecProvidesBuildRequires Bool
lenient [String]
rpmopts String
spec
case Maybe ([String], [String])
mprovbrs of
Maybe ([String], [String])
Nothing -> Maybe (String, [String], [String])
-> IO (Maybe (String, [String], [String]))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (String, [String], [String])
forall a. Maybe a
Nothing
Just ([String]
provs,[String]
brs) -> do
let provs' :: [String]
provs' = (String -> Bool) -> [String] -> [String]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> (String -> Bool) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
"(x86-64)" String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isSuffixOf`)) [String]
provs
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
verbose (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
String -> IO ()
warning (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
forall a. Show a => a -> String
show ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ [String] -> [String]
forall a. Ord a => [a] -> [a]
sort [String]
provs'
String -> IO ()
warning (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
forall a. Show a => a -> String
show ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ [String] -> [String]
forall a. Ord a => [a] -> [a]
sort [String]
brs
Maybe (String, [String], [String])
-> IO (Maybe (String, [String], [String]))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (String, [String], [String])
-> IO (Maybe (String, [String], [String])))
-> Maybe (String, [String], [String])
-> IO (Maybe (String, [String], [String]))
forall a b. (a -> b) -> a -> b
$ (String, [String], [String]) -> Maybe (String, [String], [String])
forall a. a -> Maybe a
Just (String
path,
[String] -> [String]
forall a. Eq a => [a] -> [a]
nub [String]
provs',
[String] -> [String]
forall a. Eq a => [a] -> [a]
nub [String]
brs [String] -> [String] -> [String]
forall a. Eq a => [a] -> [a] -> [a]
\\ [String]
ignoredBRs)
where
findSpec :: IO (Maybe (FilePath,FilePath))
findSpec :: IO (Maybe (String, String))
findSpec =
(String -> (String, String))
-> Maybe String -> Maybe (String, String)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> (String, String)
splitFileName (Maybe String -> Maybe (String, String))
-> IO (Maybe String) -> IO (Maybe (String, String))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
if String -> String
takeExtension String
path String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
".spec"
then Bool -> String -> IO (Maybe String)
checkFile Bool
lenient String
path
else do
Bool
dirp <- String -> IO Bool
doesDirectoryExist String
path
if Bool
dirp
then do
let dir :: String
dir = String -> (String -> String) -> Maybe String -> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe String
path (String
path String -> String -> String
</>) Maybe String
mdir
dirname :: String
dirname = String -> String
takeFileName (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String -> String -> String
forall a. Eq a => [a] -> [a] -> [a]
dropSuffix String
"/" String
path
Maybe String
mspec <- Bool -> String -> IO (Maybe String)
checkFile Bool
True (String -> IO (Maybe String)) -> String -> IO (Maybe String)
forall a b. (a -> b) -> a -> b
$ String
dir String -> String -> String
</> String
dirname String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
".spec"
case Maybe String
mspec of
Just String
spec -> Maybe String -> IO (Maybe String)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe String -> IO (Maybe String))
-> Maybe String -> IO (Maybe String)
forall a b. (a -> b) -> a -> b
$ String -> Maybe String
forall a. a -> Maybe a
Just String
spec
Maybe String
Nothing -> do
Bool
dead <- String -> IO Bool
doesFileExist (String -> IO Bool) -> String -> IO Bool
forall a b. (a -> b) -> a -> b
$ String
dir String -> String -> String
</> String
"dead.package"
if Bool
dead then Maybe String -> IO (Maybe String)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe String
forall a. Maybe a
Nothing
else do
[String]
specs <- String -> String -> IO [String]
filesWithExtension String
dir String
".spec"
case [String]
specs of
[String
spec] -> Maybe String -> IO (Maybe String)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe String -> IO (Maybe String))
-> Maybe String -> IO (Maybe String)
forall a b. (a -> b) -> a -> b
$ String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ String
dir String -> String -> String
</> String
spec
[String]
_ -> if Bool
lenient then Maybe String -> IO (Maybe String)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe String
forall a. Maybe a
Nothing
else String -> IO (Maybe String)
forall a. String -> a
error' (String -> IO (Maybe String)) -> String -> IO (Maybe String)
forall a b. (a -> b) -> a -> b
$
if [String] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
specs
then String
"No spec file found in " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
path
else String
"More than one .spec file found in " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
dir
else String -> IO (Maybe String)
forall a. String -> a
error' (String -> IO (Maybe String)) -> String -> IO (Maybe String)
forall a b. (a -> b) -> a -> b
$ String
"No spec file found for " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
path
where
checkFile :: Bool -> FilePath -> IO (Maybe FilePath)
checkFile :: Bool -> String -> IO (Maybe String)
checkFile Bool
may String
f = do
Bool
e <- String -> IO Bool
doesFileExist String
f
Maybe String -> IO (Maybe String)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe String -> IO (Maybe String))
-> Maybe String -> IO (Maybe String)
forall a b. (a -> b) -> a -> b
$ if Bool
e
then String -> Maybe String
forall a. a -> Maybe a
Just String
f
else if Bool
may
then Maybe String
forall a. Maybe a
Nothing
else String -> Maybe String
forall a. String -> a
error' (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ String
f String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" not found"
getBuildGraph :: [SourcePackage] -> PackageGraph
getBuildGraph :: [SourcePackage] -> PackageGraph
getBuildGraph [SourcePackage]
srcPkgs =
let nodes :: [(Node, SourcePackage)]
nodes = [Node] -> [SourcePackage] -> [(Node, SourcePackage)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Node
0..] [SourcePackage]
srcPkgs
nodeDict :: [(String, Node)]
nodeDict = [String] -> [Node] -> [(String, Node)]
forall a b. [a] -> [b] -> [(a, b)]
zip ((SourcePackage -> String) -> [SourcePackage] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map SourcePackage -> String
packagePath [SourcePackage]
srcPkgs) [Node
0..]
edges :: [LEdge ()]
edges = do
(Node
srcNode,SourcePackage
srcPkg) <- [(Node, SourcePackage)]
nodes
Node
dstNode <- (String -> Maybe Node) -> [String] -> [Node]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (String -> [(String, Node)] -> Maybe Node
forall a b. Eq a => a -> [(a, b)] -> Maybe b
`lookup` [(String, Node)]
nodeDict) (SourcePackage -> [String]
dependencies SourcePackage
srcPkg)
Bool -> [()]
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Node
dstNode Node -> Node -> Bool
forall a. Eq a => a -> a -> Bool
/= Node
srcNode)
LEdge () -> [LEdge ()]
forall a. a -> [a]
forall (m :: * -> *) a. Monad m => a -> m a
return (LEdge () -> [LEdge ()]) -> LEdge () -> [LEdge ()]
forall a b. (a -> b) -> a -> b
$ if Bool
rev
then (Node
dstNode, Node
srcNode, ())
else (Node
srcNode, Node
dstNode, ())
in [LNode String] -> [LEdge ()] -> PackageGraph
forall a b. [LNode a] -> [LEdge b] -> Gr a b
forall (gr :: * -> * -> *) a b.
Graph gr =>
[LNode a] -> [LEdge b] -> gr a b
G.mkGraph (((Node, SourcePackage) -> LNode String)
-> [(Node, SourcePackage)] -> [LNode String]
forall a b. (a -> b) -> [a] -> [b]
map ((SourcePackage -> String) -> (Node, SourcePackage) -> LNode String
forall a b. (a -> b) -> (Node, a) -> (Node, b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap SourcePackage -> String
packagePath) [(Node, SourcePackage)]
nodes) ([LEdge ()] -> PackageGraph) -> [LEdge ()] -> PackageGraph
forall a b. (a -> b) -> a -> b
$ [LEdge ()] -> [LEdge ()]
forall a. Eq a => [a] -> [a]
nub [LEdge ()]
edges
checkForCycles :: PackageGraph -> IO ()
checkForCycles :: PackageGraph -> IO ()
checkForCycles PackageGraph
graph = do
let cycles :: [[Node]]
cycles = ([Node] -> Bool) -> [[Node]] -> [[Node]]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Node -> Node -> Bool
forall a. Ord a => a -> a -> Bool
>= Node
2) (Node -> Bool) -> ([Node] -> Node) -> [Node] -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Node] -> Node
forall a. [a] -> Node
forall (t :: * -> *) a. Foldable t => t a -> Node
length) (PackageGraph -> [[Node]]
forall (gr :: * -> * -> *) a b. Graph gr => gr a b -> [[Node]]
scc PackageGraph
graph)
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([[Node]] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [[Node]]
cycles) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
let plural :: String
plural = if [[Node]] -> Node
forall a. [a] -> Node
forall (t :: * -> *) a. Foldable t => t a -> Node
length [[Node]]
cycles Node -> Node -> Bool
forall a. Ord a => a -> a -> Bool
> Node
1 then String
"s" else String
""
String -> IO ()
forall a. String -> a
error' (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
unlines ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$
(String
"ordering not possible due to build dependency cycle" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
plural String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
":\n") String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String] -> [[String]] -> [String]
forall a. [a] -> [[a]] -> [a]
intercalate [String
""] (([Node] -> [String]) -> [[Node]] -> [[String]]
forall a b. (a -> b) -> [a] -> [b]
map (([String], [[String]]) -> [String]
renderCycles (([String], [[String]]) -> [String])
-> ([Node] -> ([String], [[String]])) -> [Node] -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Node] -> ([String], [[String]])
subcycles) [[Node]]
cycles)
where
subcycles :: [G.Node] -> ([FilePath],[[FilePath]])
subcycles :: [Node] -> ([String], [[String]])
subcycles [] = String -> ([String], [[String]])
forall a. HasCallStack => String -> a
error String
"cyclic graph with no nodes!"
subcycles [Node]
cycle' =
let shorter :: [[Node]]
shorter = ([Node] -> [Node]) -> [[Node]] -> [[Node]]
forall b a. Ord b => (a -> b) -> [a] -> [a]
nubOrdOn [Node] -> [Node]
forall a. Ord a => [a] -> [a]
sort ([[Node]] -> [[Node]]) -> [[Node]] -> [[Node]]
forall a b. (a -> b) -> a -> b
$ ([Node] -> Node) -> [[Node]] -> [[Node]]
forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn [Node] -> Node
forall a. [a] -> Node
forall (t :: * -> *) a. Foldable t => t a -> Node
length ([[Node]] -> [[Node]]) -> [[Node]] -> [[Node]]
forall a b. (a -> b) -> a -> b
$ ([Node] -> Bool) -> [[Node]] -> [[Node]]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Node -> Node -> Bool
forall a. Ord a => a -> a -> Bool
< [Node] -> Node
forall a. [a] -> Node
forall (t :: * -> *) a. Foldable t => t a -> Node
length [Node]
cycle') (Node -> Bool) -> ([Node] -> Node) -> [Node] -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Node] -> Node
forall a. [a] -> Node
forall (t :: * -> *) a. Foldable t => t a -> Node
length) ([[Node]] -> [[Node]]) -> [[Node]] -> [[Node]]
forall a b. (a -> b) -> a -> b
$ ((Node, Node, Node) -> Maybe [Node])
-> [(Node, Node, Node)] -> [[Node]]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (Node, Node, Node) -> Maybe [Node]
forall {c}. (Node, Node, c) -> Maybe [Node]
findSp ([(Node, Node, Node)] -> [[Node]])
-> [(Node, Node, Node)] -> [[Node]]
forall a b. (a -> b) -> a -> b
$ Gr String Node -> [(Node, Node, Node)]
forall a b. Gr a b -> [LEdge b]
forall (gr :: * -> * -> *) a b. Graph gr => gr a b -> [LEdge b]
G.labEdges Gr String Node
sg
in (PackageGraph -> [Node] -> [String]
forall a b. Gr a b -> [Node] -> [a]
nodeLabels PackageGraph
graph [Node]
cycle', ([Node] -> [String]) -> [[Node]] -> [[String]]
forall a b. (a -> b) -> [a] -> [b]
map (Gr String Node -> [Node] -> [String]
forall a b. Gr a b -> [Node] -> [a]
nodeLabels Gr String Node
sg) [[Node]]
shorter)
where
sg :: Gr String Node
sg = (() -> Node) -> PackageGraph -> Gr String Node
forall (gr :: * -> * -> *) b c a.
DynGraph gr =>
(b -> c) -> gr a b -> gr a c
G.emap (Node -> () -> Node
forall a b. a -> b -> a
const (Node
1 :: Int)) (PackageGraph -> Gr String Node) -> PackageGraph -> Gr String Node
forall a b. (a -> b) -> a -> b
$ [Node] -> PackageGraph -> PackageGraph
forall (gr :: * -> * -> *) a b.
DynGraph gr =>
[Node] -> gr a b -> gr a b
G.subgraph [Node]
cycle' PackageGraph
graph
findSp :: (Node, Node, c) -> Maybe [Node]
findSp (Node
i,Node
j,c
_) | Gr String Node -> Edge -> Bool
forall (gr :: * -> * -> *) a b. Graph gr => gr a b -> Edge -> Bool
G.hasEdge Gr String Node
sg (Node
i,Node
j) = Node -> Node -> Gr String Node -> Maybe [Node]
forall (gr :: * -> * -> *) b a.
(Graph gr, Real b) =>
Node -> Node -> gr a b -> Maybe [Node]
sp Node
j Node
i Gr String Node
sg
| Gr String Node -> Edge -> Bool
forall (gr :: * -> * -> *) a b. Graph gr => gr a b -> Edge -> Bool
G.hasEdge Gr String Node
sg (Node
j,Node
i) = Node -> Node -> Gr String Node -> Maybe [Node]
forall (gr :: * -> * -> *) b a.
(Graph gr, Real b) =>
Node -> Node -> gr a b -> Maybe [Node]
sp Node
i Node
j Gr String Node
sg
| Bool
otherwise = Maybe [Node]
forall a. Maybe a
Nothing
renderCycles :: ([FilePath],[[FilePath]]) -> [String]
renderCycles :: ([String], [[String]]) -> [String]
renderCycles ([String]
c,[[String]]
sc) =
[String] -> String
unwords [String]
c String -> [String] -> [String]
forall a. a -> [a] -> [a]
: if [[String]] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [[String]]
sc then [] else String
"\nShortest path subcycles: " String -> [String] -> [String]
forall a. a -> [a] -> [a]
: ([String] -> String) -> [[String]] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map [String] -> String
unwords [[String]]
sc
getDepsSrcResolved :: [(FilePath,[String],[String])] -> FilePath -> Maybe [FilePath]
getDepsSrcResolved :: [(String, [String], [String])] -> String -> Maybe [String]
getDepsSrcResolved [(String, [String], [String])]
metadata String
pkg =
(String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map String -> String
resolveBase ([String] -> [String])
-> ((String, [String], [String]) -> [String])
-> (String, [String], [String])
-> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String, [String], [String]) -> [String]
forall {a} {b} {c}. (a, b, c) -> c
thd ((String, [String], [String]) -> [String])
-> Maybe (String, [String], [String]) -> Maybe [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((String, [String], [String]) -> Bool)
-> [(String, [String], [String])]
-> Maybe (String, [String], [String])
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
find ((String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
pkg) (String -> Bool)
-> ((String, [String], [String]) -> String)
-> (String, [String], [String])
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String, [String], [String]) -> String
forall a b c. (a, b, c) -> a
fst3) [(String, [String], [String])]
metadata
where
resolveBase :: FilePath -> FilePath
resolveBase :: String -> String
resolveBase String
br =
case ((String, [String], [String]) -> Maybe String)
-> [(String, [String], [String])] -> [String]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (\ (String
p,[String]
provs,[String]
_) -> if String
br String -> [String] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [String]
provs then String -> Maybe String
forall a. a -> Maybe a
Just String
p else Maybe String
forall a. Maybe a
Nothing) [(String, [String], [String])]
metadata of
[] -> String
br
[String
p] -> String
p
[String]
ps -> String -> String
forall a. String -> a
error' (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String
pkg String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
": " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
br String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" is provided by: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
unwords [String]
ps
thd :: (a, b, c) -> c
thd (a
_,b
_,c
c) = c
c
fst3 :: (a,b,c) -> a
fst3 :: forall a b c. (a, b, c) -> a
fst3 (a
a,b
_,c
_) = a
a
nodeLabels :: Gr a b -> [G.Node] -> [a]
nodeLabels :: forall a b. Gr a b -> [Node] -> [a]
nodeLabels Gr a b
graph =
(Node -> a) -> [Node] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (a -> Maybe a -> a
forall a. a -> Maybe a -> a
fromMaybe (String -> a
forall a. HasCallStack => String -> a
error String
"node not found in graph") (Maybe a -> a) -> (Node -> Maybe a) -> Node -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
Gr a b -> Node -> Maybe a
forall (gr :: * -> * -> *) a b.
Graph gr =>
gr a b -> Node -> Maybe a
G.lab Gr a b
graph)
createGraph'''' :: Bool
-> [String]
-> [String]
-> Bool
-> Bool
-> Bool
-> Maybe FilePath
-> [FilePath]
-> IO PackageGraph
createGraph'''' :: Bool
-> [String]
-> [String]
-> Bool
-> Bool
-> Bool
-> Maybe String
-> [String]
-> IO PackageGraph
createGraph'''' = Bool
-> [String]
-> [String]
-> Bool
-> Bool
-> Bool
-> Maybe String
-> [String]
-> IO PackageGraph
createGraph4
subgraph' :: Gr a b -> [G.Node] -> Gr a b
subgraph' :: forall a b. Gr a b -> [Node] -> Gr a b
subgraph' = ([Node] -> Gr a b -> Gr a b) -> Gr a b -> [Node] -> Gr a b
forall a b c. (a -> b -> c) -> b -> a -> c
flip [Node] -> Gr a b -> Gr a b
forall (gr :: * -> * -> *) a b.
DynGraph gr =>
[Node] -> gr a b -> gr a b
G.subgraph
packageLayers :: PackageGraph -> [[FilePath]]
packageLayers :: PackageGraph -> [[String]]
packageLayers PackageGraph
graph =
if PackageGraph -> Bool
forall a b. Gr a b -> Bool
forall (gr :: * -> * -> *) a b. Graph gr => gr a b -> Bool
G.isEmpty PackageGraph
graph then []
else
let layer :: [LNode String]
layer = PackageGraph -> [LNode String]
lowestLayer' PackageGraph
graph
in (LNode String -> String) -> [LNode String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map LNode String -> String
forall a b. (a, b) -> b
snd [LNode String]
layer [String] -> [[String]] -> [[String]]
forall a. a -> [a] -> [a]
: PackageGraph -> [[String]]
packageLayers ([Node] -> PackageGraph -> PackageGraph
forall (gr :: * -> * -> *) a b.
Graph gr =>
[Node] -> gr a b -> gr a b
G.delNodes ((LNode String -> Node) -> [LNode String] -> [Node]
forall a b. (a -> b) -> [a] -> [b]
map LNode String -> Node
forall a b. (a, b) -> a
fst [LNode String]
layer) PackageGraph
graph)
lowestLayer :: PackageGraph -> [FilePath]
lowestLayer :: PackageGraph -> [String]
lowestLayer PackageGraph
graph =
(LNode String -> String) -> [LNode String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map LNode String -> String
forall a b. (a, b) -> b
snd ([LNode String] -> [String]) -> [LNode String] -> [String]
forall a b. (a -> b) -> a -> b
$ PackageGraph -> [LNode String]
forall a b. Gr a b -> [LNode a]
forall (gr :: * -> * -> *) a b. Graph gr => gr a b -> [LNode a]
G.labNodes (PackageGraph -> [LNode String]) -> PackageGraph -> [LNode String]
forall a b. (a -> b) -> a -> b
$ (Node -> Bool) -> PackageGraph -> PackageGraph
forall (gr :: * -> * -> *) a b.
DynGraph gr =>
(Node -> Bool) -> gr a b -> gr a b
G.nfilter ((Node -> Node -> Bool
forall a. Eq a => a -> a -> Bool
==Node
0) (Node -> Bool) -> (Node -> Node) -> Node -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageGraph -> Node -> Node
forall (gr :: * -> * -> *) a b. Graph gr => gr a b -> Node -> Node
G.indeg PackageGraph
graph) PackageGraph
graph
lowestLayer' :: PackageGraph -> [G.LNode FilePath]
lowestLayer' :: PackageGraph -> [LNode String]
lowestLayer' PackageGraph
graph =
PackageGraph -> [LNode String]
forall a b. Gr a b -> [LNode a]
forall (gr :: * -> * -> *) a b. Graph gr => gr a b -> [LNode a]
G.labNodes (PackageGraph -> [LNode String]) -> PackageGraph -> [LNode String]
forall a b. (a -> b) -> a -> b
$ (Node -> Bool) -> PackageGraph -> PackageGraph
forall (gr :: * -> * -> *) a b.
DynGraph gr =>
(Node -> Bool) -> gr a b -> gr a b
G.nfilter ((Node -> Node -> Bool
forall a. Eq a => a -> a -> Bool
==Node
0) (Node -> Bool) -> (Node -> Node) -> Node -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageGraph -> Node -> Node
forall (gr :: * -> * -> *) a b. Graph gr => gr a b -> Node -> Node
G.indeg PackageGraph
graph) PackageGraph
graph
packageLeaves :: PackageGraph -> [FilePath]
packageLeaves :: PackageGraph -> [String]
packageLeaves PackageGraph
graph =
(LNode String -> String) -> [LNode String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map LNode String -> String
forall a b. (a, b) -> b
snd ([LNode String] -> [String]) -> [LNode String] -> [String]
forall a b. (a -> b) -> a -> b
$ PackageGraph -> [LNode String]
forall a b. Gr a b -> [LNode a]
forall (gr :: * -> * -> *) a b. Graph gr => gr a b -> [LNode a]
G.labNodes (PackageGraph -> [LNode String]) -> PackageGraph -> [LNode String]
forall a b. (a -> b) -> a -> b
$ (Node -> Bool) -> PackageGraph -> PackageGraph
forall (gr :: * -> * -> *) a b.
DynGraph gr =>
(Node -> Bool) -> gr a b -> gr a b
G.nfilter ((Node -> Node -> Bool
forall a. Eq a => a -> a -> Bool
==Node
0) (Node -> Bool) -> (Node -> Node) -> Node -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageGraph -> Node -> Node
forall (gr :: * -> * -> *) a b. Graph gr => gr a b -> Node -> Node
G.outdeg PackageGraph
graph) PackageGraph
graph
separatePackages :: PackageGraph -> [FilePath]
separatePackages :: PackageGraph -> [String]
separatePackages PackageGraph
graph =
(LNode String -> String) -> [LNode String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map LNode String -> String
forall a b. (a, b) -> b
snd ([LNode String] -> [String]) -> [LNode String] -> [String]
forall a b. (a -> b) -> a -> b
$ PackageGraph -> [LNode String]
forall a b. Gr a b -> [LNode a]
forall (gr :: * -> * -> *) a b. Graph gr => gr a b -> [LNode a]
G.labNodes (PackageGraph -> [LNode String]) -> PackageGraph -> [LNode String]
forall a b. (a -> b) -> a -> b
$ (Node -> Bool) -> PackageGraph -> PackageGraph
forall (gr :: * -> * -> *) a b.
DynGraph gr =>
(Node -> Bool) -> gr a b -> gr a b
G.nfilter ((Node -> Node -> Bool
forall a. Eq a => a -> a -> Bool
==Node
0) (Node -> Bool) -> (Node -> Node) -> Node -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageGraph -> Node -> Node
forall (gr :: * -> * -> *) a b. Graph gr => gr a b -> Node -> Node
G.deg PackageGraph
graph) PackageGraph
graph
printGraph :: PackageGraph -> IO ()
printGraph :: PackageGraph -> IO ()
printGraph PackageGraph
g = do
String -> IO ()
putStrLn String
"digraph {"
[LNode String] -> (LNode String -> IO ()) -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (PackageGraph -> [LNode String]
forall a b. Gr a b -> [LNode a]
forall (gr :: * -> * -> *) a b. Graph gr => gr a b -> [LNode a]
G.labNodes PackageGraph
g) ((LNode String -> IO ()) -> IO ())
-> (LNode String -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ (Node
n,String
l) -> do
String -> IO ()
putStr (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String -> String
forall a. Show a => a -> String
show String
l
String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ [String] -> String
renderDeps ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map String -> String
forall a. Show a => a -> String
show ([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ ((Node, ()) -> Maybe String) -> [(Node, ())] -> [String]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (PackageGraph -> Node -> Maybe String
forall (gr :: * -> * -> *) a b.
Graph gr =>
gr a b -> Node -> Maybe a
G.lab PackageGraph
g (Node -> Maybe String)
-> ((Node, ()) -> Node) -> (Node, ()) -> Maybe String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Node, ()) -> Node
forall a b. (a, b) -> a
fst) ([(Node, ())] -> [String]) -> [(Node, ())] -> [String]
forall a b. (a -> b) -> a -> b
$ PackageGraph -> Node -> [(Node, ())]
forall (gr :: * -> * -> *) a b.
Graph gr =>
gr a b -> Node -> [(Node, b)]
G.lsuc PackageGraph
g Node
n
String -> IO ()
putStrLn String
"}"
where
renderDeps :: [String] -> String
renderDeps :: [String] -> String
renderDeps [] = String
""
renderDeps [String
d] = String
" -> " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
d
renderDeps [String]
ds = String
" -> {" String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
unwords [String]
ds String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"}"
renderGraph :: PackageGraph -> IO ()
renderGraph :: PackageGraph -> IO ()
renderGraph PackageGraph
graph = do
Bool
gv <- IO Bool
isGraphvizInstalled
if Bool
gv
then do
let g :: Gr String String
g = (() -> String) -> PackageGraph -> Gr String String
forall (gr :: * -> * -> *) b c a.
DynGraph gr =>
(b -> c) -> gr a b -> gr a c
G.emap (String -> () -> String
forall a b. a -> b -> a
const (String
"" :: String)) PackageGraph
graph
DotGraph Node -> GraphvizCanvas -> IO ()
forall (dg :: * -> *) n.
PrintDotRepr dg n =>
dg n -> GraphvizCanvas -> IO ()
runGraphvizCanvas' ((GraphvizParams Node String String () String
-> Gr String String -> DotGraph Node)
-> GraphvizParams Node String String () String
-> Gr String String
-> DotGraph Node
forall el (gr :: * -> * -> *) nl cl l a.
(Ord el, Graph gr) =>
(GraphvizParams Node nl el cl l -> gr nl el -> a)
-> GraphvizParams Node nl el cl l -> gr nl el -> a
setDirectedness GraphvizParams Node String String () String
-> Gr String String -> DotGraph Node
forall cl (gr :: * -> * -> *) nl el l.
(Ord cl, Graph gr) =>
GraphvizParams Node nl el cl l -> gr nl el -> DotGraph Node
graphToDot GraphvizParams Node String String () String
forall nl el n.
(Labellable nl, Labellable el) =>
GraphvizParams n nl el () nl
quickParams Gr String String
g) GraphvizCanvas
Xlib
else String -> IO ()
forall a. String -> a
error' String
"please install graphviz first"
depsGraph :: Bool
-> [String]
-> Bool
-> [String]
-> [String]
-> Bool
-> Maybe FilePath
-> [FilePath]
-> IO PackageGraph
depsGraph :: Bool
-> [String]
-> Bool
-> [String]
-> [String]
-> Bool
-> Maybe String
-> [String]
-> IO PackageGraph
depsGraph Bool
rev [String]
rpmopts Bool
verbose [String]
excludedPkgs [String]
ignoredBRs Bool
lenient Maybe String
mdir [String]
pkgs =
String -> IO [String]
listDirectory String
"." IO [String] -> ([String] -> IO PackageGraph) -> IO PackageGraph
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
Bool
-> [String]
-> Bool
-> [String]
-> [String]
-> Bool
-> Maybe String
-> [String]
-> [String]
-> IO PackageGraph
depsGraphDeps Bool
rev [String]
rpmopts Bool
verbose [String]
excludedPkgs [String]
ignoredBRs Bool
lenient Maybe String
mdir [String]
pkgs ([String] -> IO PackageGraph)
-> ([String] -> [String]) -> [String] -> IO PackageGraph
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
([String] -> [String] -> [String]
forall a. Eq a => [a] -> [a] -> [a]
`union` [String]
pkgs)
depsGraphDeps :: Bool
-> [String]
-> Bool
-> [String]
-> [String]
-> Bool
-> Maybe FilePath
-> [FilePath]
-> [FilePath]
-> IO PackageGraph
depsGraphDeps :: Bool
-> [String]
-> Bool
-> [String]
-> [String]
-> Bool
-> Maybe String
-> [String]
-> [String]
-> IO PackageGraph
depsGraphDeps Bool
rev [String]
rpmopts Bool
verbose [String]
excludedPkgs [String]
ignoredBRs Bool
lenient Maybe String
mdir [String]
pkgs [String]
deps = do
IO Bool -> IO () -> IO ()
forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
unlessM ([Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and ([Bool] -> Bool) -> IO [Bool] -> IO Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (String -> IO Bool) -> [String] -> IO [Bool]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM String -> IO Bool
doesDirectoryExist [String]
pkgs) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> IO ()
forall a. String -> a
errorWithoutStackTrace String
"Please use package directory paths"
[String]
-> [String]
-> Bool
-> Bool
-> Bool
-> Maybe String
-> [String]
-> IO PackageGraph
createGraph3 [String]
ignoredBRs [String]
rpmopts Bool
verbose Bool
lenient (Bool -> Bool
not Bool
rev) Maybe String
mdir ((String -> Bool) -> [String] -> [String]
forall a. (a -> Bool) -> [a] -> [a]
filter (\String
d -> String
d String -> [String] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [String]
excludedPkgs Bool -> Bool -> Bool
&& String -> Char
forall a. HasCallStack => [a] -> a
head String
d Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'.') [String]
deps) IO PackageGraph
-> (PackageGraph -> IO PackageGraph) -> IO PackageGraph
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
[String]
-> Bool
-> Bool
-> Bool
-> Maybe String
-> [String]
-> IO PackageGraph
createGraph2 [String]
rpmopts Bool
verbose Bool
lenient Bool
True Maybe String
mdir ([String] -> IO PackageGraph)
-> (PackageGraph -> [String]) -> PackageGraph -> IO PackageGraph
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> PackageGraph -> [String]
dependencyNodes [String]
pkgs
data Components = Parallel
| Combine
| Connected
| Separate
topsortGraph :: Components -> PackageGraph -> [[String]]
topsortGraph :: Components -> PackageGraph -> [[String]]
topsortGraph Components
opt PackageGraph
graph =
case Components
opt of
Components
Parallel -> ([Node] -> [String]) -> [[Node]] -> [[String]]
forall a b. (a -> b) -> [a] -> [b]
map (PackageGraph -> [String]
forall (gr :: * -> * -> *) a b. Graph gr => gr a b -> [a]
topsort' (PackageGraph -> [String])
-> ([Node] -> PackageGraph) -> [Node] -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageGraph -> [Node] -> PackageGraph
forall a b. Gr a b -> [Node] -> Gr a b
subgraph' PackageGraph
graph) (PackageGraph -> [[Node]]
forall (gr :: * -> * -> *) a b. Graph gr => gr a b -> [[Node]]
components PackageGraph
graph)
Components
Combine -> [String] -> [[String]]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([String] -> [[String]]) -> [String] -> [[String]]
forall a b. (a -> b) -> a -> b
$ PackageGraph -> [String]
forall (gr :: * -> * -> *) a b. Graph gr => gr a b -> [a]
topsort' PackageGraph
graph
Components
Connected ->
([Node] -> [String]) -> [[Node]] -> [[String]]
forall a b. (a -> b) -> [a] -> [b]
map (PackageGraph -> [String]
forall (gr :: * -> * -> *) a b. Graph gr => gr a b -> [a]
topsort' (PackageGraph -> [String])
-> ([Node] -> PackageGraph) -> [Node] -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PackageGraph -> [Node] -> PackageGraph
forall a b. Gr a b -> [Node] -> Gr a b
subgraph' PackageGraph
graph) ([[Node]] -> [[String]]) -> [[Node]] -> [[String]]
forall a b. (a -> b) -> a -> b
$ ([Node] -> Bool) -> [[Node]] -> [[Node]]
forall a. (a -> Bool) -> [a] -> [a]
filter ((Node -> Node -> Bool
forall a. Ord a => a -> a -> Bool
>Node
1) (Node -> Bool) -> ([Node] -> Node) -> [Node] -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Node] -> Node
forall a. [a] -> Node
forall (t :: * -> *) a. Foldable t => t a -> Node
length) (PackageGraph -> [[Node]]
forall (gr :: * -> * -> *) a b. Graph gr => gr a b -> [[Node]]
components PackageGraph
graph)
Components
Separate -> [String] -> [[String]]
forall a. a -> [a]
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([String] -> [[String]]) -> [String] -> [[String]]
forall a b. (a -> b) -> a -> b
$ PackageGraph -> [String]
separatePackages PackageGraph
graph
#if !MIN_VERSION_simple_cmd(0,2,4)
filesWithExtension :: FilePath -> String -> IO [FilePath]
filesWithExtension dir ext =
filter (ext `isExtensionOf`) <$> listDirectory dir
#if !MIN_VERSION_filepath(1,4,2)
isExtensionOf :: String -> FilePath -> Bool
isExtensionOf ext@('.':_) = isSuffixOf ext . takeExtensions
isExtensionOf ext = isSuffixOf ('.':ext) . takeExtensions
#endif
#endif