#! /usr/bin/python -tt import os import sys import time import yum import optparse __show_all_versions__ = False __show_installed_1st__ = False def print_req(req, val, level): indent = '' if level: indent = ' | ' * (level - 1) + ' \_ ' print "%s%s [%s]" % (indent, str(req), str(val)) all_reqs = {} def pkg2req(pkg): """ Turn a pkg into a "unique" req.""" if __show_all_versions__: req = str(pkg) else: arch = pkg.arch if arch == 'i686': arch = 'i386' req = "%s.%s" % (pkg.name, arch) return req def pkg2val(reqs, pkg): reqs = sorted(reqs[pkg2req(pkg)]) return str(len(reqs)) + ": " + ", ".join(reqs) def maybe_add_pkg(loc_reqs, pkgs, pkg, val): global all_reqs req = pkg2req(pkg) if req in loc_reqs: loc_reqs[req].add(val) return if req in all_reqs: pkgs[pkg] = None loc_reqs[req] = set([val]) return pkgs[pkg] = True loc_reqs[req] = set([val]) all_reqs[req] = True return __req2pkgs = {} def req2pkgs(req): global __req2pkgs req = str(req) if req in __req2pkgs: return __req2pkgs[req] providers = [] try: # XXX rhbz#246519, for some reason returnPackagesByDep() fails # to find some root level directories while # searchPackageProvides() does... use that for now matches = yb.searchPackageProvides([req]) providers = matches.keys() # provider.extend(yum.YumBase.returnPackagesByDep(self, depstring)) except yum.Errors.YumBaseError, err: print >>sys.stderr, "No package provides %s" % req return [] __req2pkgs[req] = providers return providers def pkg_eq(pkg, oth): """ compare two packages for equality, ignoring arch. """ upkg = "%s-%s:%s-%s" % (pkg.name, pkg.epoch, pkg.version, pkg.release) uoth = "%s-%s:%s-%s" % (oth.name, oth.epoch, oth.version, oth.release) return upkg == uoth def tree_dep(pkg, val='cmd line', level=0): print_req(pkg, val, level) rpkgs = {} loc_reqs = {} for rptup in pkg.returnPrco('requires'): (rpn, rpf, (rp,rpv,rpr)) = rptup if not rpn.startswith('rpmlib'): rname = yum.misc.prco_tuple_to_string(rptup) for npkg in sorted(req2pkgs(rname), reverse=True): maybe_add_pkg(loc_reqs, rpkgs, npkg, rname) for rpkg in sorted(rpkgs): if pkg_eq(pkg, rpkg): # Remove deps. on self. continue if rpkgs[rpkg] is None: print_req(rpkg, pkg2val(loc_reqs, rpkg), level + 1) continue tree_dep(rpkg, pkg2val(loc_reqs, rpkg), level + 1) def check_pkgs(pkgs): if not len(pkgs): print >>sys.stderr, " No matching pkgs for arg %s" % pname sys.exit(1) names = {} for pkg in pkgs: names[pkg.name] = True if len(names) > 1: print >>sys.stderr, " Different pkgs match for arg %s: %s" % (pname, str(pkgs)) sys.exit(1) assert __name__ == "__main__" # --------------------------------- setup() --------------------------------- version = "0.0.1" vers_txt = "Package Deps tree view version %s" % version usage_txt = "%prog ..." parser = optparse.OptionParser(usage = usage_txt, version = vers_txt) # Mostly pasted from repoquery if True: # Doesn't work # parser.add_option("--archlist", # help="only query packages of certain architecture(s)") parser.add_option("--limit-installed", action="store_true", help="show all versions of packages") parser.add_option("--showduplicates", action="store_true", help="show all versions of packages") parser.add_option("--repoid", action="append", help="specify repoids to query, can be specified multiple times (default is all enabled)") parser.add_option("--enablerepo", action="append", dest="enablerepos", help="specify repoids to query, can be specified multiple times (default is all enabled)") parser.add_option("--disablerepo", action="append", dest="disablerepos", help="specify repoids to disable, can be specified multiple times") parser.add_option("--repofrompath", action="append", help="specify repoid & paths of additional repositories - unique repoid and complete path required, can be specified multiple times. Example. --repofrompath=myrepo,/path/to/repo") parser.add_option("--plugins", action="store_true", default=False, help="enable yum plugin support") parser.add_option("--quiet", action="store_true", help="quiet (no output to stderr)", default=True) parser.add_option("--verbose", action="store_false", help="verbose output", dest="quiet") parser.add_option("-C", "--cache", action="store_true", help="run from cache only") parser.add_option("--tempcache", action="store_true", help="use private cache (default when used as non-root)") parser.add_option("-c", dest="conffile", help="config file location") (opts, args) = parser.parse_args() if len(args) < 1: parser.print_help() sys.exit(1) initnoise = (not opts.quiet) * 2 yb = yum.YumBase() yb.doConfigSetup(debuglevel=0, errorlevel=1) if opts.conffile: yb.doConfigSetup(fn=opts.conffile, debuglevel=initnoise, init_plugins=opts.plugins) else: yb.doConfigSetup(debuglevel=initnoise, init_plugins=opts.plugins) if opts.repofrompath: # setup the fake repos for repo in opts.repofrompath: repoid,repopath = tuple(repo.split(',')) if repopath[0] == '/': baseurl = 'file://' + repopath else: baseurl = repopath repopath = os.path.normpath(repopath) newrepo = yum.yumRepo.YumRepository(repoid) newrepo.name = repopath newrepo.baseurl = baseurl newrepo.basecachedir = yb.conf.cachedir yb.repos.add(newrepo) yb.repos.enableRepo(newrepo.id) yb.logger.info( "Added %s repo from %s" % (repoid,repopath)) # Show what is going on, if --quiet is not set. if not opts.quiet and sys.stdout.isatty(): yb.repos.setProgressBar(TextMeter(fo=sys.stdout)) yb.repos.callback = output.CacheProgressCallback() yumout = output.YumOutput() freport = ( yumout.failureReport, (), {} ) yb.repos.setFailureCallback( freport ) if os.geteuid() != 0 or opts.tempcache: cachedir = yum.misc.getCacheDir() if cachedir is None: yb.logger.error("Error: Could not make cachedir, exiting") sys.exit(50) yb.repos.setCacheDir(cachedir) yb.conf.cache = 0 # yum set cache=1, if uid != 0 if opts.cache: yb.conf.cache = True if not opts.quiet: yb.logger.info('Running from cache, results might be incomplete.') if opts.limit_installed: __show_installed_1st__ = True if opts.showduplicates: yb.conf.showdupesfromrepos = True __show_all_versions__ = True if opts.repoid: for repo in yb.repos.findRepos('*'): if repo.id not in opts.repoid: repo.disable() else: repo.enable() if opts.disablerepos: for repo_match in opts.disablerepos: for repo in yb.repos.findRepos(repo_match): repo.disable() if opts.enablerepos: for repo_match in opts.enablerepos: for repo in yb.repos.findRepos(repo_match): repo.enable() if True: try: yb.doRepoSetup() except yum.Errors.RepoError, e: yb.logger.error("Could not setup repo: %s" % (e)) sys.exit(50) archlist = None if False and opts.archlist: archlist = opts.archlist.split(',') try: yb.doSackSetup(archlist=archlist) except yum.Errors.RepoError, e: yb.logger.error( e) sys.exit(1) # ick.. python assumes ascii encoding if stdout is not a tty, force # it to preferred locale if not sys.stdout.isatty(): import codecs, locale sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout) # --------------------------------- main() --------------------------------- if __show_installed_1st__: all_pkgs = yb.rpmdb.returnPackages() elif __show_all_versions__: all_pkgs = yb.pkgSack.returnPackages() else: all_pkgs = yb.pkgSack.returnNewestByNameArch() done = False for pname in args: exact, match, unmatch = yum.packages.parsePackages(all_pkgs, [pname], casematch=0) pkgs = exact + match # check_pkgs(pkgs) if done: print '' for pkg in sorted(pkgs): if done: print '' done = True tree_dep(pkg)