packages feed

rpmbuild-order-0.4.11: src/Main.hs

{-# LANGUAGE CPP #-}

module Main (main) where

import Control.Applicative (
#if !MIN_VERSION_simple_cmd_args(0,1,3)
                            (<|>),
#endif
#if !MIN_VERSION_simple_cmd_args(0,1,4)
                            many, some,
#endif
#if !MIN_VERSION_base(4,8,0)
                            (<$>), (<*>)
#endif
                           )
import Data.Graph.Inductive.Query.DFS (components)
import Data.List (intercalate)
import Data.List.Extra (dropSuffix)

import SimpleCmdArgs

import Distribution.RPM.Build.Graph
import Distribution.RPM.Build.Order
import Paths_rpmbuild_order (version)

main :: IO ()
main =
  simpleCmdArgs (Just version) "Order packages by build dependencies"
  "Sort package sources (spec files) in build dependency order" $
  subcommands
  [ Subcommand "sort" "sort packages" $
    sortPackages <$> rpmOpts <*> verboseOpt <*> lenientOpt <*> componentsOpt <*> subdirOpt <*> pkgArgs
  , Subcommand "deps" "sort dependencies in neighbouring package dirs" $
    depsPackages False <$> rpmOpts <*> verboseOpt <*> excludeOpts <*> ignoredBRopts <*> lenientOpt <*> combineOpt <*> subdirOpt <*> pkgArgs
  , Subcommand "rdeps" "sort dependents in neighbouring package dirs" $
    depsPackages True <$> rpmOpts <*> verboseOpt <*> excludeOpts <*> ignoredBRopts <*> lenientOpt <*> combineOpt <*> subdirOpt <*> pkgArgs
  , 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
  , Subcommand "leaves" "List of the top leaves of package graph" $
    leavesPackages <$> rpmOpts <*> verboseOpt <*> lenientOpt <*> subdirOpt <*> pkgArgs
  , Subcommand "roots" "List lowest root packages" $
    rootPackages <$> rpmOpts <*> verboseOpt <*> lenientOpt <*> subdirOpt <*> pkgArgs
  , Subcommand "render" "Show graph with graphviz" $
    renderPkgGraph <$> switchWith 'g' "gv-output" "Output graph in gv/dot format" <*> rpmOpts <*> verboseOpt <*> lenientOpt <*> subdirOpt <*> pkgArgs
  ]
  where
    verboseOpt = switchWith 'v' "verbose" "Verbose output for debugging"
    lenientOpt = switchWith 'l' "lenient" "Ignore rpmspec errors"
    combineOpt = switchWith 'c' "combine" "Combine independent packages"
    subdirOpt = optional (strOptionWith 'd' "dir" "SUBDIR" "Branch directory")
    pkgArgs = some (strArg "PKG...")
    componentsOpt =
      flagWith' Connected 'C' "connected" "Only include connected packages" <|>
      flagWith' Separate 'i' "independent" "Only list independent packages" <|>
      flagWith Parallel Combine 'c' "combine" "Combine connected and independent packages"
    rpmOpts = many (strOptionWith 'r' "rpmopt" "RPMOPT" "Option for rpmspec")
    ignoredBRopts = many (strOptionWith 'I' "ignore-BR" "PKG" "BuildRequires to exclude from graph")
    excludeOpts = many (dropSuffix "/" <$> strOptionWith 'x' "exclude" "PKG" "Package dirs to exclude from graph")

sortPackages :: [String] -> Bool -> Bool -> Components -> Maybe FilePath
             -> [FilePath] -> IO ()
sortPackages rpmopts verbose lenient opts mdir pkgs = do
  createGraph2 rpmopts verbose lenient True mdir pkgs >>= sortGraph opts

layerPackages :: [String] -> Bool -> Bool -> Bool -> Maybe FilePath
              -> [FilePath] -> IO ()
layerPackages rpmopts verbose lenient combine mdir pkgs = do
  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 <- createGraph2 rpmopts verbose lenient True mdir pkgs
  if combine then doChain graph
    else mapM_ (doChain . subgraph' graph) (components graph)
  where
    doChain graph =
      let chain = intercalate [":"] $ packageLayers graph
      in putStrLn $ unwords chain

leavesPackages :: [String] -> Bool -> Bool -> Maybe FilePath -> [FilePath]
               -> IO ()
leavesPackages rpmopts verbose lenient mdir pkgs = do
  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 <- 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 =
  createGraph4 False [] rpmopts verbose lenient False mdir pkgs >>=
  if dot then printGraph else renderGraph