packages feed

rpmbuild-order 0.4.5 → 0.4.6

raw patch · 9 files changed

+255/−112 lines, 9 filesdep −containersdep −processdep ~basedep ~filepathdep ~simple-cmdPVP ok

version bump matches the API change (PVP)

Dependencies removed: containers, process

Dependency ranges changed: base, filepath, simple-cmd

API changes (from Hackage documentation)

+ Distribution.RPM.Build.Graph: createGraph1 :: Bool -> Bool -> Bool -> Maybe FilePath -> [FilePath] -> IO PackageGraph
+ Distribution.RPM.Build.Graph: createGraph2 :: [String] -> Bool -> Bool -> Bool -> Maybe FilePath -> [FilePath] -> IO PackageGraph
+ Distribution.RPM.Build.Graph: createGraph3 :: [String] -> [String] -> Bool -> Bool -> Bool -> Maybe FilePath -> [FilePath] -> IO PackageGraph
+ Distribution.RPM.Build.Graph: createGraph4 :: Bool -> [String] -> [String] -> Bool -> Bool -> Bool -> Maybe FilePath -> [FilePath] -> IO PackageGraph

Files

ChangeLog.md view
@@ -1,3 +1,11 @@+# 0.4.6 (2022-05-30)+- handle Dynamic BuildRequires (#3)+  with special support for golang Provs and rust & ruby BRs+- Graph: new aliases createGraph1 for createGraph',+  createGraph2 for createGraph'', createGraph3 for createGraph''',+  and createGraph4 for createGraph'''' (deprecating the primed names)+- Graph: use simple-cmd+ # 0.4.5 (2021-05-29) - 'render': do not reverse arrows - 'render': rename -o/--output option to -g/--gv-output
README.md view
@@ -5,7 +5,7 @@ # rpmbuild-order  This is a tool to sort RPM source packages in build dependency order.-This code is originally derived from+The code was originally derived from [cabal-sort](http://hackage.haskell.org/package/cabal-sort) by Henning Thielemann. @@ -45,20 +45,31 @@ 1. Given packages A, B, C, where C depends on B, and B depends on A, and you call -    rpmbuild-order sort C.spec A.spec+       rpmbuild-order sort C.spec A.spec -then the output may be wrong if C does not have a direct dependency on A.-Even if the order is correct, B is missing in the output-and thus in this case the list of packages cannot be reliably used-for a sequence of builds.+   then the output may be wrong if C does not have a direct dependency on A.+   Even if the order is correct, B is missing in the output+   and thus in this case the list of packages cannot be reliably used+   for a sequence of builds. -However the `deps` and `rdeps` commands take-other neighbouring package directories into account.+   However the `deps` and `rdeps` commands take+   other neighbouring package directories into account.  2. repoquery is not used to resolve meta-dependencies or files to packages. So if a package BuildRequires a file, it will not be resolved to a package.-This may get addressed some day, but file dependencies seem less common for-BuildRequires than Requires.+This may get addressed some day, but file dependencies seem uncommon for+BuildRequires compared to Requires.  3. rpmspec is used to parse spec files (for macro expansion etc): so missing macros packages can lead to erroneous results in some cases.++4. Since version 0.4.6 there is some support now for packages using+dynamic buildrequires (in Fedora: golang, python, ruby, and rust packages).++## Installation++rpmbuild-order is packaged in Fedora Linux.++## Building from source++Use `cabal-rpm builddep && cabal-install` or `stack install`.
TODO view
@@ -1,8 +1,8 @@ - --quiet to silence rpmspec warnings - use record to set createGraph options -- try topograph-- use Set?+- try topograph or agl+- use Data.Set * warn about uninstalled (specific?) macros packages - handle duplicate packages? - (r)deps: optimize using actual deps
rpmbuild-order.1 view
@@ -1,7 +1,7 @@-.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.48.3.-.TH RPMBUILD-ORDER "1" "May 2021" "rpmbuild-order 0.4.5" "User Commands"+.\" DO NOT MODIFY THIS FILE!  It was generated by help2man 1.49.2.+.TH RPMBUILD-ORDER "1" "May 2022" "rpmbuild-order 0.4.6" "User Commands" .SH NAME-rpmbuild-order \- manual page for rpmbuild-order 0.4.5+rpmbuild-order \- manual page for rpmbuild-order 0.4.6 .SH SYNOPSIS .B rpmbuild-order [\fI\,--version\/\fR] \fI\,COMMAND\/\fR@@ -28,7 +28,7 @@ sort dependents .TP layers-ordered output suitable for a chain\-build+ordered output of dependency layers .TP chain ordered output suitable for a chain\-build
rpmbuild-order.cabal view
@@ -1,12 +1,12 @@ Name:             rpmbuild-order-Version:          0.4.5+Version:          0.4.6 License:          BSD3 License-File:     LICENSE Author:           Jens Petersen <petersen@redhat.com>,                   Henning Thielemann <haskell@henning-thielemann.de> Maintainer:       Jens Petersen <petersen@redhat.com> Copyright:        2010-2018  Henning Thielemann,-                  2018-2021 Jens Petersen <petersen@redhat.com>+                  2018-2022 Jens Petersen <petersen@redhat.com> Category:         Distribution Homepage:         https://github.com/juhp/rpmbuild-order Bug-reports:      https://github.com/juhp/rpmbuild-order/issues@@ -23,10 +23,9 @@   which can affect dependencies. It can also output dependency graphs.    Since version 0.4, a library API is also provided.-Tested-with:       GHC == 7.4.2, GHC == 7.6.3, GHC == 7.8.4,-                   GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2,+Tested-with:       GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2,                    GHC == 8.4.4, GHC == 8.6.5, GHC == 8.8.4,-                   GHC == 8.10.4, GHC == 9.0.1+                   GHC == 8.10.7, GHC == 9.0.2 Cabal-Version:     1.18 Build-Type:        Simple Extra-doc-files:    README.md TODO ChangeLog.md@@ -50,6 +49,7 @@                  simple-cmd-args   Main-Is:          src/Main.hs   Other-modules:    Paths_rpmbuild_order+  default-language: Haskell2010   GHC-Options:         -Wall   if impl(ghc >= 8.0)     ghc-options:       -Wcompat@@ -62,21 +62,22 @@   if impl(ghc >= 8.4)     ghc-options:       -Wmissing-export-lists                        -Wpartial-fields-  default-language: Haskell2010+  if impl(ghc >= 8.10)+    ghc-options:       -Wunused-packages  Library   Exposed-Modules:  Distribution.RPM.Build.Graph                     Distribution.RPM.Build.Order   Build-Depends: base < 5,                  case-insensitive,-                 containers,                  directory,                  extra >= 1.6.4,-                 filepath,+                 filepath >= 1.4.2,                  fgl >= 5.5.4,                  graphviz,-                 process+                 simple-cmd >= 0.2.3   HS-Source-Dirs:      src+  default-language:    Haskell2010   GHC-Options:         -Wall   if impl(ghc >= 8.0)     ghc-options:       -Wcompat@@ -89,8 +90,8 @@   if impl(ghc >= 8.4)     ghc-options:       -Wmissing-export-lists                        -Wpartial-fields--  default-language:    Haskell2010+  if impl(ghc >= 8.10)+    ghc-options:       -Wunused-packages  test-suite test     main-is: Spec.hs@@ -106,4 +107,4 @@                  , rpmbuild-order                  , simple-cmd                  , unix-    build-tools:   rpmbuild-order+    build-tool-depends: rpmbuild-order:rpmbuild-order
src/Distribution/RPM/Build/Graph.hs view
@@ -15,6 +15,10 @@   (PackageGraph,    createGraph,    createGraphRpmOpts,+   createGraph1,+   createGraph2,+   createGraph3,+   createGraph4,    createGraph',    createGraph'',    createGraph''',@@ -41,22 +45,23 @@ #endif import Control.Monad (forM_, guard, when, unless) import Data.Maybe (catMaybes, fromMaybe, mapMaybe)-import Data.List.Extra (dropSuffix, find, intercalate, nub, nubOrdOn, sort, sortOn)+import Data.List.Extra import Data.GraphViz+import SimpleCmd import System.Directory (doesDirectoryExist, doesFileExist,+                         withCurrentDirectory,+#if !MIN_VERSION_simple_cmd(0,2,4) #if MIN_VERSION_directory(1,2,5)                          listDirectory #else                          getDirectoryContents #endif+#endif                         )-import System.Exit (ExitCode (..), exitFailure)+import System.Exit (exitFailure) import System.FilePath--- replace with warning-import System.IO (hPutStrLn, stderr)-import System.Process (readProcessWithExitCode) -#if !MIN_VERSION_directory(1,2,5)+#if !MIN_VERSION_directory(1,2,5) && !MIN_VERSION_simple_cmd(0,2,4) listDirectory :: FilePath -> IO [FilePath] listDirectory path =   filter f <$> getDirectoryContents path@@ -90,34 +95,45 @@     third (_, _, c, _) = c  -- | Create a directed dependency graph for a set of packages--- This is a convenience wrapper for createGraph' False False True Nothing+-- This is a convenience wrapper for createGraph1 False False True Nothing createGraph :: [FilePath] -- ^ package paths (directories or spec filepaths)             -> IO PackageGraph -- ^ dependency graph labelled by package paths-createGraph = createGraph' False False True Nothing+createGraph = createGraph1 False False True Nothing  -- | Create a directed dependency graph for a set of packages setting rpm options--- This is a convenience wrapper for @createGraph'' rpmopts False False True Nothing@+-- This is a convenience wrapper for @createGraph2 rpmopts False False True Nothing@ -- -- @since 0.4.2 createGraphRpmOpts :: [String] -- ^ rpmspec options                    -> [FilePath] -- ^ package paths (directories or spec filepaths)                    -> IO PackageGraph -- ^ dependency graph labelled by package paths createGraphRpmOpts rpmopts =-  createGraph'' rpmopts False False True Nothing+  createGraph2 rpmopts False False True Nothing  -- | Create a directed dependency graph for a set of packages -- For the (createGraph default) reverse deps graph the arrows point back -- from the dependencies to the dependendent (parent/consumer) packages, -- and this allows forward sorting by dependencies (ie lowest deps first). ----- This is the same as @createGraph'' []@+-- This is the same as @createGraph2 []@+--+-- @since 0.4.6+createGraph1 :: Bool -- ^ verbose+             -> Bool -- ^ lenient (skip rpmspec failures)+             -> Bool -- ^ reverse dependency graph+             -> Maybe FilePath -- ^ look for spec file in a subdirectory+             -> [FilePath] -- ^ package paths (directories or spec filepaths)+             -> IO PackageGraph -- ^ dependency graph labelled by package paths+createGraph1 = createGraph2 []++-- | Alias for createGraph1 createGraph' :: Bool -- ^ verbose              -> Bool -- ^ lenient (skip rpmspec failures)              -> Bool -- ^ reverse dependency graph              -> Maybe FilePath -- ^ look for spec file in a subdirectory              -> [FilePath] -- ^ package paths (directories or spec filepaths)              -> IO PackageGraph -- ^ dependency graph labelled by package paths-createGraph' = createGraph'' []+createGraph' = createGraph1  -- | Create a directed dependency graph for a set of packages -- For the (createGraph default) reverse deps graph the arrows point back@@ -127,7 +143,19 @@ -- Additionally this function allows passing options to rpmspec: -- eg `--with bootstrap` etc ----- @since 0.4.2+-- @since 0.4.6+createGraph2 :: [String] -- ^ rpmspec options+             -> Bool -- ^ verbose+             -> Bool -- ^ lenient (skip rpmspec failures)+             -> Bool -- ^ reverse dependency graph+             -> Maybe FilePath -- ^ look for spec file in a subdirectory+             -> [FilePath] -- ^ package paths (directories or spec filepaths)+             -> IO PackageGraph -- ^ dependency graph labelled by package paths+createGraph2 = createGraph3 []++-- | Alias for createGraph2+--+-- @since 0.4.2 (deprecated) createGraph'' :: [String] -- ^ rpmspec options               -> Bool -- ^ verbose               -> Bool -- ^ lenient (skip rpmspec failures)@@ -135,13 +163,26 @@               -> Maybe FilePath -- ^ look for spec file in a subdirectory               -> [FilePath] -- ^ package paths (directories or spec filepaths)               -> IO PackageGraph -- ^ dependency graph labelled by package paths-createGraph'' = createGraph''' []+createGraph'' = createGraph2  -- | Create a directed dependency graph for a set of packages ----- Like createGraph'' but with additional parameter for any BRs to be ignored.+-- Like createGraph2 but with additional parameter for any BRs to be ignored. ----- @since 0.4.3+-- @since 0.4.6+createGraph3 :: [String] -- ^ ignored BuildRequires+             -> [String] -- ^ rpmspec options+             -> Bool -- ^ verbose+             -> Bool -- ^ lenient (skip rpmspec failures)+             -> Bool -- ^ reverse dependency graph+             -> Maybe FilePath -- ^ look for spec file in a subdirectory+             -> [FilePath] -- ^ package paths (directories or spec filepaths)+             -> IO PackageGraph -- ^ dependency graph labelled by package paths+createGraph3 = createGraph4 True++-- | Alias for createGraph3+--+-- @since 0.4.3 (deprecated) createGraph''' :: [String] -- ^ ignored BuildRequires                -> [String] -- ^ rpmspec options                -> Bool -- ^ verbose@@ -150,23 +191,24 @@                -> Maybe FilePath -- ^ look for spec file in a subdirectory                -> [FilePath] -- ^ package paths (directories or spec filepaths)                -> IO PackageGraph -- ^ dependency graph labelled by package paths-createGraph''' = createGraph'''' True+createGraph''' = createGraph3  -- | Create a directed dependency graph for a set of packages ----- Like createGraph''' but can disable check for cycles+-- Like createGraph3 but can disable check for cycles ----- @since 0.4.4-createGraph'''' :: Bool -- ^ check for cycles-                -> [String] -- ^ ignored BuildRequires-                -> [String] -- ^ rpmspec options-                -> Bool -- ^ verbose-                -> Bool -- ^ lenient (skip rpmspec failures)-                -> Bool -- ^ reverse dependency graph-                -> Maybe FilePath -- ^ look for spec file in a subdirectory-                -> [FilePath] -- ^ package paths (directories or spec filepaths)-                -> IO PackageGraph -- ^ dependency graph labelled by package paths-createGraph'''' checkcycles ignoredBRs rpmopts verbose lenient rev mdir paths = do+-- @since 0.4.6+createGraph4 :: Bool -- ^ check for cycles+             -> [String] -- ^ ignored BuildRequires+             -> [String] -- ^ rpmspec options+             -> Bool -- ^ verbose+             -> Bool -- ^ lenient (skip rpmspec failures)+             -> Bool -- ^ reverse dependency graph+             -> Maybe FilePath -- ^ look for spec file in a subdirectory+             -> [FilePath] -- ^ package paths (directories or spec filepaths)+             -> IO PackageGraph -- ^ dependency graph labelled by package paths+createGraph4 checkcycles ignoredBRs rpmopts verbose lenient rev mdir paths =+  do   metadata <- catMaybes <$> mapM readSpecMetadata paths   let realpkgs = map fst3 metadata       deps = mapMaybe (getDepsSrcResolved metadata) realpkgs@@ -178,21 +220,51 @@   where     readSpecMetadata :: FilePath -> IO (Maybe (FilePath,[String],[String]))     readSpecMetadata path = do-      mspec <- findSpec-      case mspec of+      mspecdir <- findSpec+      case mspecdir of         Nothing -> return Nothing-        Just spec -> do-          when verbose $ warn spec-          mcontent <- rpmspecParse spec-          case mcontent of-            Nothing -> return Nothing-            Just content ->-              let pkg = takeBaseName spec-                  (provs,brs) = extractMetadata pkg ([],[]) $ lines content-              in return (Just (path, provs, brs))+        Just (dir,spec) -> do+          when verbose $ warning spec+          withCurrentDirectory dir $ do+            dynbr <- egrep_ "^\\(%generate_buildrequires\\|%gometa\\)" spec+            mprovbrs <-+              if dynbr+              then do+                brs <- rpmspecDynBuildRequires spec+                provs <- do+                  dynprovs <-+                    if "golang-" `isPrefixOf` takeBaseName spec+                    then do+                      macro <- grep "%global goipath" spec+                      return $+                        case macro of+                          [def] -> ["golang(" ++ last (words def) ++ ")"]+                          _ -> error' $ "failed to find %goipath in " ++ spec+                    else return []+                  prs <- rpmspecProvides spec+                  return $ dynprovs ++ prs+                return $ Just (provs,brs)+              else do+                mcontent <- rpmspecParse spec+                return $ case mcontent of+                           Nothing -> Nothing+                           Just content ->+                             let pkg = takeBaseName spec+                             in Just $ extractMetadata pkg ([],[]) $ lines content+            case mprovbrs of+              Nothing -> return Nothing+              Just (provs,brs) -> do+                when verbose $ do+                  warning $ show $ sort provs+                  warning $ show $ mapMaybe simplifyDep $ sort brs+                return $ Just (path,+                               nub provs, -- FIXME filter 'name(arch)'+                               nub (mapMaybe simplifyDep brs) \\ ignoredBRs)       where-        findSpec :: IO (Maybe FilePath)+        -- (dir,specfile)+        findSpec :: IO (Maybe (FilePath,FilePath))         findSpec =+          fmap splitFileName <$>           if takeExtension path == ".spec"             then checkFile lenient path             else do@@ -210,27 +282,28 @@                     else do                     specs <- filesWithExtension dir ".spec"                     case specs of-                      [spec] -> return $ Just spec+                      [spec] -> return $ Just $ dir </> spec                       _ -> if lenient then return Nothing-                           else errorWithoutStackTrace $+                           else error' $                                 if null specs                                 then "No spec file found in " ++ path                                 else "More than one .spec file found in " ++ dir-              else errorWithoutStackTrace $ "No spec file found for " ++ path+              else error' $ "No spec file found for " ++ path           where             checkFile :: Bool -> FilePath -> IO (Maybe FilePath)             checkFile may f = do               e <- doesFileExist f-              if e-                then return $ Just f-                else return $ if may-                              then Nothing-                              else errorWithoutStackTrace $ f ++ " not found"+              return $ if e+                       then Just f+                       else if may+                            then Nothing+                            else error' $ f ++ " not found" +#if !MIN_VERSION_simple_cmd(0,2,4)             filesWithExtension :: FilePath -> String -> IO [FilePath]             filesWithExtension dir ext =-              map (dir </>) . filter (\ f -> takeExtension f == ext) <$>-              listDirectory dir+              filter (ext `isExtensionOf`) <$> listDirectory dir+#endif          extractMetadata :: FilePath -> ([String],[String]) -> [String] -> ([String],[String])         extractMetadata _ acc [] = acc@@ -271,7 +344,7 @@       let cycles = filter ((>= 2) . length) (scc graph)       unless (null cycles) $ do         let plural = if length cycles > 1 then "s" else ""-        errorWithoutStackTrace $ unlines $+        error' $ unlines $           ("ordering not possible due to build dependency cycle" ++ plural ++ ":\n") : intercalate [""] (map (renderCycles . subcycles) cycles)       where         -- shortest subcycle@@ -300,7 +373,7 @@           case mapMaybe (\ (p,provs,_) -> if br `elem` provs then Just p else Nothing) metadata of             [] -> br             [p] -> p-            ps -> errorWithoutStackTrace $ pkg ++ ": " ++ br ++ " is provided by: " ++ unwords ps+            ps -> error' $ pkg ++ ": " ++ br ++ " is provided by: " ++ unwords ps          thd (_,_,c) = c @@ -314,15 +387,59 @@      rpmspecParse :: FilePath -> IO (Maybe String)     rpmspecParse spec = do-      (res, out, err) <- readProcessWithExitCode "rpmspec" (["-P", "--define", "ghc_version any"] ++ rpmopts ++ [spec]) ""-      unless (null err) $ warn err-      case res of-        ExitFailure _ -> if lenient then return Nothing else exitFailure-        ExitSuccess -> return $ Just out+      (ok, out, err) <- cmdFull "rpmspec" (["-P", "--define", "ghc_version any"] ++ rpmopts ++ [spec]) ""+      unless (null err) $ warning err+      if ok+        then return $ Just out+        else if lenient then return Nothing else exitFailure -    warn :: String -> IO ()-    warn = hPutStrLn stderr+    rpmspecProvides :: FilePath -> IO [String]+    rpmspecProvides spec = do+      (ok, out, err) <- cmdFull "rpmspec" (["--define", "ghc_version any", "-q", "--provides"] ++ rpmopts ++ [spec]) ""+      unless (null err) $ warning err+      if ok+        then return $ map (head . words) $ lines out+        else if lenient then return [] else exitFailure +    rpmspecDynBuildRequires :: FilePath -> IO [String]+    rpmspecDynBuildRequires spec = do+      (out,err) <- cmdStdErr "rpmbuild" ["-br", "--nodeps", spec]+      unless (null err) $+        when verbose $ warning err+      -- Wrote: /current/dir/SRPMS/name-version-release.buildreqs.nosrc.rpm+      cmdLines "rpm" ["-qp", "--requires", last (words out)]++    simplifyDep br =+      case (head . words) br of+        '(':dep -> simplifyDep dep+        dep -> case splitOn "(" (dropSuffix ")" dep) of+          ("rpmlib":_) -> Nothing+          ("crate":[crate]) -> Just $ "rust-" ++ replace "/" "+" crate ++ "-devel"+          ("rubygem":[gem]) -> Just $ "rubygem-" ++ gem+          _ -> Just dep++    -- rpmspecBuildRequires :: FilePath -> IO [String]+    -- rpmspecBuildRequires spec = do+    --   (ok, out, err) <- cmdFull "rpmspec" (["--define", "ghc_version any", "-q", "--buildrequires"] ++ rpmopts ++ [spec]) ""+    --   unless (null err) $ warning err+    --   if ok+    --     then return $ lines out+    --     else if lenient then return [] else exitFailure++-- | Alias for createGraph4+--+-- @since 0.4.4 (deprecated)+createGraph'''' :: Bool -- ^ check for cycles+                -> [String] -- ^ ignored BuildRequires+                -> [String] -- ^ rpmspec options+                -> Bool -- ^ verbose+                -> Bool -- ^ lenient (skip rpmspec failures)+                -> Bool -- ^ reverse dependency graph+                -> Maybe FilePath -- ^ look for spec file in a subdirectory+                -> [FilePath] -- ^ package paths (directories or spec filepaths)+                -> IO PackageGraph -- ^ dependency graph labelled by package paths+createGraph'''' = createGraph4+ -- | A flipped version of subgraph subgraph' :: Gr a b -> [G.Node] -> Gr a b subgraph' = flip G.subgraph@@ -377,4 +494,4 @@     then do     let g = G.emap (const ("" :: String)) graph     runGraphvizCanvas' (setDirectedness graphToDot quickParams g) Xlib-    else errorWithoutStackTrace "please install graphviz first"+    else error' "please install graphviz first"
src/Main.hs view
@@ -45,7 +45,7 @@     depsPackages False <$> rpmOpts <*> verboseOpt <*> excludeOpts <*> ignoredBRopts <*> lenientOpt <*> combineOpt <*> subdirOpt <*> pkgArgs   , Subcommand "rdeps" "sort dependents" $     depsPackages True <$> rpmOpts <*> verboseOpt <*> excludeOpts <*> ignoredBRopts <*> lenientOpt <*> combineOpt <*> subdirOpt <*> pkgArgs-  , Subcommand "layers" "ordered output suitable for a chain-build" $+  , Subcommand "layers" "ordered output of dependency layers" $     layerPackages <$> rpmOpts <*> verboseOpt <*> lenientOpt <*> combineOpt <*> subdirOpt <*> pkgArgs   , Subcommand "chain" "ordered output suitable for a chain-build" $     chainPackages <$> rpmOpts <*> verboseOpt <*> lenientOpt <*> combineOpt <*> subdirOpt <*> pkgArgs@@ -61,7 +61,7 @@     lenientOpt = switchWith 'l' "lenient" "Ignore rpmspec errors"     combineOpt = switchWith 'c' "combine" "Combine independent packages"     subdirOpt = optional (strOptionWith 'd' "dir" "SUBDIR" "Branch directory")-    pkgArgs = some (argumentWith str "PKG...")+    pkgArgs = some (strArg "PKG...")     componentsOpt =       flagWith' Connected 'C' "connected" "Only include connected packages" <|>       flagWith' Separate 'i' "independent" "Only list independent packages" <|>@@ -72,7 +72,7 @@  sortPackages :: [String] -> Bool -> Bool -> Components -> Maybe FilePath -> [FilePath] -> IO () sortPackages rpmopts verbose lenient opts mdir pkgs = do-  createGraph'' rpmopts verbose lenient True mdir pkgs >>= sortGraph opts+  createGraph2 rpmopts verbose lenient True mdir pkgs >>= sortGraph opts  depsPackages :: Bool -> [String] -> Bool-> [String] -> [String] -> Bool ->  Bool -> Maybe FilePath -> [FilePath] -> IO () depsPackages rev rpmopts verbose excludedPkgs ignoredBRs lenient parallel mdir pkgs = do@@ -80,8 +80,8 @@     errorWithoutStackTrace "Please use package directory paths"   listDirectory "." >>=     -- filter out dotfiles-    createGraph''' ignoredBRs rpmopts verbose lenient (not rev) mdir . filter ((/= '.') . head) . filter (`notElem` excludedPkgs) >>=-    createGraph'' rpmopts verbose lenient True mdir . dependencyNodes pkgs >>=+    createGraph3 ignoredBRs rpmopts verbose lenient (not rev) mdir . filter ((/= '.') . head) . filter (`notElem` excludedPkgs) >>=+    createGraph2 rpmopts verbose lenient True mdir . dependencyNodes pkgs >>=     sortGraph (if parallel then Parallel else Combine)  #if (defined(MIN_VERSION_directory) && MIN_VERSION_directory(1,2,5))@@ -94,15 +94,16 @@  layerPackages :: [String] -> Bool -> Bool -> Bool -> Maybe FilePath -> [FilePath] -> IO () layerPackages rpmopts verbose lenient combine mdir pkgs = do-  graph <- createGraph'' rpmopts verbose lenient True mdir pkgs-  if combine then printLayers graph+  graph <- createGraph2 rpmopts verbose lenient True mdir pkgs+  if combine+    then printLayers graph     else mapM_ (printLayers . subgraph' graph) (components graph)   where     printLayers =  putStrLn . unlines . map unwords . packageLayers  chainPackages :: [String] -> Bool -> Bool -> Bool -> Maybe FilePath -> [FilePath] -> IO () chainPackages rpmopts verbose lenient combine mdir pkgs = do-  graph <- createGraph'' rpmopts verbose lenient True mdir pkgs+  graph <- createGraph2 rpmopts verbose lenient True mdir pkgs   if combine then doChain graph     else mapM_ (doChain . subgraph' graph) (components graph)   where@@ -112,16 +113,16 @@  leavesPackages :: [String] -> Bool -> Bool -> Maybe FilePath -> [FilePath] -> IO () leavesPackages rpmopts verbose lenient mdir pkgs = do-  graph <- createGraph'' rpmopts verbose lenient True mdir pkgs+  graph <- createGraph2 rpmopts verbose lenient True mdir pkgs   mapM_ putStrLn $ packageLeaves graph  rootPackages :: [String] -> Bool -> Bool -> Maybe FilePath -> [FilePath] -> IO () rootPackages rpmopts verbose lenient mdir pkgs = do-  graph <- createGraph'' rpmopts verbose lenient True mdir pkgs+  graph <- createGraph2 rpmopts verbose lenient True mdir pkgs   mapM_ putStrLn $ lowestLayer graph  renderPkgGraph :: Bool -> [String] -> Bool -> Bool -> Maybe FilePath                -> [FilePath] -> IO () renderPkgGraph dot rpmopts verbose lenient mdir pkgs =-  createGraph'''' False [] rpmopts verbose lenient False mdir pkgs >>=+  createGraph4 False [] rpmopts verbose lenient False mdir pkgs >>=   if dot then printGraph else renderGraph
test/Spec.hs view
@@ -18,32 +18,32 @@  spec :: Version -> Spec spec rpmver = do-  describe "sorting" $ do-    it "sort A B" $+  describe "sort" $ do+    it "A B" $       dependencySort [pkg "A", pkg "B"] >>=       (`shouldBe` [pkg "B", pkg "A"]) -    it "sort 1 2" $+    it "1 2" $       dependencySort [pkg "1", pkg "2"] >>=       (`shouldBe` [pkg "2", pkg "1"]) -    it "sort A/ B/" $+    it "A/ B/" $       dependencySort [pkg "A/", pkg "B/"] >>=       (`shouldBe` [pkg "B/", pkg "A/"]) -    it "sort 1/ 2/" $+    it "1/ 2/" $       dependencySort [pkg "1/", pkg "2/"] >>=       (`shouldBe` [pkg "2/", pkg "1/"]) -    it "sort A.spec B.spec" $+    it "A.spec B.spec" $       dependencySort [pkg "A/A.spec", pkg "B/B.spec"] >>=       (`shouldBe` [pkg "B/B.spec", pkg "A/A.spec"]) -    it "sort 1.spec 2.spec" $+    it "1.spec 2.spec" $       dependencySort [pkg "1/A.spec", pkg "2/B.spec"] >>=       (`shouldBe` [pkg "2/B.spec", pkg "1/A.spec"]) -    it "sort A/ B.spec" $+    it "A/ B.spec" $       dependencySort [pkg "A/", pkg "B/B.spec"] >>=       (`shouldBe` [pkg "B/B.spec", pkg "A/"]) @@ -51,22 +51,27 @@       dependencySort [pkg "A", pkg "B", pkg "C"]       `shouldThrow` anyException -    it "sort A B D1.0" $+    it "A B D1.0" $       dependencySort [pkg "A", pkg "B/", pkg "D1.0"] >>=       (`shouldBe` [pkg "B/", pkg "D1.0", pkg "A"]) +    when (rpmver > makeVersion [4,15,0]) $+      it "dynbr A B" $+      dependencySort [pkg "dynbr/A", pkg "B"] >>=+      (`shouldBe` [pkg "B", pkg "dynbr/A"])+     when (rpmver > makeVersion [4,15,1]) $       it "circular A B C boot" $       dependencySortRpmOpts ["--with=boot"] [pkg "A", pkg "B", pkg "C"] >>=       (`shouldBe` [pkg "C", pkg "B", pkg "A"])    describe "layers" $-    it "layers A B" $+    it "A B" $       dependencyLayers [pkg "A", pkg "B"] >>=       (`shouldBe` [[pkg "B"], [pkg "A"]])    describe "leaves" $-    it "leaves A B D" $+    it "A B D" $       leafPackages [pkg "A", pkg "B", pkg "D1.0"] >>=       (`shouldBe` [pkg "A", pkg "D1.0"]) 
test/pkgs/A/A.spec view
@@ -3,7 +3,7 @@ Release:        1%{?dist} Summary:        package A License:        GPL-BuildRequires:  B+BuildRequires:  B-devel  %description Test package A