Here's a patch set for package-cleanup whose combined result is sorted package list output and query formatting like rpm. My primary use case for these changes is running package-cleanup --leaves --all before and after some package management operation as well as comparing its output between boxes, sorted output and --qf="%{NAME}" makes the output easier to diff. The patches are 0002: ground work, 0003: sorting, 0004: query formatting.
From 8f916d73c19958aa4a431d289185301e933f9171 Mon Sep 17 00:00:00 2001 From: =?utf-8?q?Ville=20Skytt=C3=A4?= <ville.skytta@xxxxxx> Date: Wed, 25 Mar 2009 00:41:22 +0200 Subject: [PATCH] Operate more on yum package objects rather than tuples. --- package-cleanup.py | 60 ++++++++++++++++++++++++--------------------------- 1 files changed, 28 insertions(+), 32 deletions(-) diff --git a/package-cleanup.py b/package-cleanup.py index 11d8415..8c10b87 100755 --- a/package-cleanup.py +++ b/package-cleanup.py @@ -69,14 +69,13 @@ def getLocalRequires(my): """Get a list of all requirements in the local rpmdb""" pkgs = {} for po in my.rpmdb.returnPackages(): - tup = po.pkgtup header = po.hdr requires = zip( header[rpm.RPMTAG_REQUIRENAME], header[rpm.RPMTAG_REQUIREFLAGS], header[rpm.RPMTAG_REQUIREVERSION], ) - pkgs[tup] = requires + pkgs[po] = requires return pkgs def buildProviderList(my, pkgs, reportProblems): @@ -87,7 +86,7 @@ def buildProviderList(my, pkgs, reportProblems): providers = {} # To speed depsolving, don't recheck deps that have # already been checked provsomething = {} - for (pkg,reqs) in pkgs.items(): + for (po,reqs) in pkgs.items(): for (req,flags,ver) in reqs: if ver == '': ver = None @@ -102,13 +101,13 @@ def buildProviderList(my, pkgs, reportProblems): if not errors: print "Missing dependencies:" errors = True - print "Package %s requires %s" % (pkg[0], + print "Package %s requires %s" % (po, miscutils.formatRequire(req,ver,rflags)) else: for rpkg in resolve_sack: # Skip packages that provide something for themselves # as these can still be leaves - if rpkg != pkg: + if rpkg != po.pkgtup: provsomething[rpkg] = 1 # Store the resolve_sack so that we can re-use it if another # package has the same requirement @@ -191,11 +190,8 @@ def printDupes(my): continue dupes.append(po) - for pkg in dupes: - if pkg.epoch != '0': - print '%s:%s-%s-%s.%s' % (pkg.epoch, pkg.name, pkg.ver, pkg.rel, pkg.arch) - else: - print '%s-%s-%s.%s' % (pkg.name, pkg.ver, pkg.rel, pkg.arch) + for po in dupes: + print "%s" % po def cleanOldDupes(my, confirmed): """remove all the older duplicates""" @@ -238,19 +234,14 @@ def cleanOldDupes(my, confirmed): -def _shouldShowLeaf(my, pkg, leaf_regex, exclude_devel, exclude_bin): +def _shouldShowLeaf(my, po, leaf_regex, exclude_devel, exclude_bin): """ Determine if the given pkg should be displayed as a leaf or not. Return True if the pkg should be shown, False if not. """ - if pkg[0] == 'gpg-pubkey': + if po.name == 'gpg-pubkey': return False - pos = my.rpmdb.searchNevra(name=pkg[0], epoch=str(pkg[2]), ver=pkg[3], - rel=pkg[4], arch=pkg[1]) - # This should give us an exact match - assert len(pos) == 1 - po = pos[0] name = po.name if exclude_devel and name.endswith('devel'): return False @@ -263,27 +254,32 @@ def _shouldShowLeaf(my, pkg, leaf_regex, exclude_devel, exclude_bin): return False def listLeaves(my, all_nodes, leaf_regex, exclude_devel, exclude_bin): - """return a packagtuple of any installed packages that - are not required by any other package on the system""" + """Print packages that are not required by any other package + on the system""" + + # Could use my.rpmdb.returnLeafNodes() directly but it's slow ts = transaction.initReadOnlyTransaction() - leaves = ts.returnLeafNodes() - for pkg in leaves: - name = pkg[0] - if all_nodes or _shouldShowLeaf(my, pkg, leaf_regex, exclude_devel, + leaves = [list(x) for x in ts.returnLeafNodes()] + # Epoch can be a number, stringify to work with getInstalledPackageObject + for lst in leaves: + lst[2] = str(lst[2]) + leaves = (my.getInstalledPackageObject(x) for x in leaves) + + for po in leaves: + if all_nodes or _shouldShowLeaf(my, po, leaf_regex, exclude_devel, exclude_bin): - print "%s-%s-%s.%s" % (pkg[0],pkg[3],pkg[4],pkg[1]) + print "%s" % po def listOrphans(my): """ This is "yum list extras". """ avail = my.pkgSack.simplePkgList() avail = set(avail) for po in sorted(my.rpmdb.returnPackages()): - (n,a,e,v,r) = po.pkgtup - if n == "gpg-pubkey": # Not needed as of at least 3.2.19, but meh + if po.name == "gpg-pubkey": # Not needed as of at least 3.2.19, but meh continue if po.pkgtup not in avail: - print "%s-%s-%s.%s" % (n, v, r, a) + print "%s" % po def getKernels(my): """return a list of all installed kernels, sorted newest to oldest""" @@ -384,17 +380,17 @@ def removeKernels(my, count, confirmed, keepdevel): print "No kernel related packages to remove" return + toremove = [my.getInstalledPackageObject(x) for x in toremove] + print "I will remove the following %s kernel related packages:" % len(toremove) - for kernel in toremove: - (n,a,e,v,r) = kernel - print "%s-%s-%s" % (n,v,r) + for po in toremove: + print "%s" % po if not confirmed: if not userconfirm(): sys.exit(0) - for kernel in toremove: - po = my.rpmdb.searchPkgTuple(kernel)[0] + for po in toremove: my.tsInfo.addErase(po) # Now perform the action transaction -- 1.6.0.6
From 9a361719192aa601615446f43a160c7be2e7200d Mon Sep 17 00:00:00 2001 From: =?utf-8?q?Ville=20Skytt=C3=A4?= <ville.skytta@xxxxxx> Date: Wed, 25 Mar 2009 00:54:59 +0200 Subject: [PATCH] Sort package list output. --- package-cleanup.py | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-cleanup.py b/package-cleanup.py index 8c10b87..236590f 100755 --- a/package-cleanup.py +++ b/package-cleanup.py @@ -190,7 +190,7 @@ def printDupes(my): continue dupes.append(po) - for po in dupes: + for po in sorted(dupes): print "%s" % po def cleanOldDupes(my, confirmed): @@ -214,9 +214,9 @@ def cleanOldDupes(my, confirmed): if len(removedupes) == 0: print "No dupes to clean" sys.exit(0) - + print "I will remove the following old duplicate packages:" - for po in removedupes: + for po in sorted(removedupes): print "%s" % po if not confirmed: @@ -263,7 +263,7 @@ def listLeaves(my, all_nodes, leaf_regex, exclude_devel, exclude_bin): # Epoch can be a number, stringify to work with getInstalledPackageObject for lst in leaves: lst[2] = str(lst[2]) - leaves = (my.getInstalledPackageObject(x) for x in leaves) + leaves = sorted((my.getInstalledPackageObject(x) for x in leaves)) for po in leaves: if all_nodes or _shouldShowLeaf(my, po, leaf_regex, exclude_devel, @@ -380,7 +380,7 @@ def removeKernels(my, count, confirmed, keepdevel): print "No kernel related packages to remove" return - toremove = [my.getInstalledPackageObject(x) for x in toremove] + toremove = sorted((my.getInstalledPackageObject(x) for x in toremove)) print "I will remove the following %s kernel related packages:" % len(toremove) for po in toremove: -- 1.6.0.6
From d04e1ba0b7e8918634c66ffa321906a0685d3441 Mon Sep 17 00:00:00 2001 From: =?utf-8?q?Ville=20Skytt=C3=A4?= <ville.skytta@xxxxxx> Date: Wed, 25 Mar 2009 01:01:25 +0200 Subject: [PATCH] Add query formatting. --- package-cleanup.py | 40 ++++++++++++++++++++++------------------ 1 files changed, 22 insertions(+), 18 deletions(-) diff --git a/package-cleanup.py b/package-cleanup.py index 236590f..7f9c878 100755 --- a/package-cleanup.py +++ b/package-cleanup.py @@ -78,7 +78,7 @@ def getLocalRequires(my): pkgs[po] = requires return pkgs -def buildProviderList(my, pkgs, reportProblems): +def buildProviderList(my, pkgs, reportProblems, qf): """Resolve all dependencies in pkgs and build a dictionary of packages that provide something for a package other than itself""" @@ -101,7 +101,7 @@ def buildProviderList(my, pkgs, reportProblems): if not errors: print "Missing dependencies:" errors = True - print "Package %s requires %s" % (po, + print "Package %s requires %s" % (po.hdr.sprintf(qf), miscutils.formatRequire(req,ver,rflags)) else: for rpkg in resolve_sack: @@ -177,7 +177,7 @@ def findDupes(my): return refined -def printDupes(my): +def printDupes(my, qf): """print out the dupe listing""" dupedict = findDupes(my) dupes = [] @@ -191,9 +191,9 @@ def printDupes(my): dupes.append(po) for po in sorted(dupes): - print "%s" % po + print po.hdr.sprintf(qf) -def cleanOldDupes(my, confirmed): +def cleanOldDupes(my, confirmed, qf): """remove all the older duplicates""" dupedict = findDupes(my) removedupes = [] @@ -217,7 +217,7 @@ def cleanOldDupes(my, confirmed): print "I will remove the following old duplicate packages:" for po in sorted(removedupes): - print "%s" % po + print po.hdr.sprintf(qf) if not confirmed: if not userconfirm(): @@ -253,7 +253,7 @@ def _shouldShowLeaf(my, po, leaf_regex, exclude_devel, exclude_bin): return True return False -def listLeaves(my, all_nodes, leaf_regex, exclude_devel, exclude_bin): +def listLeaves(my, all_nodes, leaf_regex, exclude_devel, exclude_bin, qf): """Print packages that are not required by any other package on the system""" @@ -268,9 +268,9 @@ def listLeaves(my, all_nodes, leaf_regex, exclude_devel, exclude_bin): for po in leaves: if all_nodes or _shouldShowLeaf(my, po, leaf_regex, exclude_devel, exclude_bin): - print "%s" % po + print po.hdr.sprintf(qf) -def listOrphans(my): +def listOrphans(my, qf): """ This is "yum list extras". """ avail = my.pkgSack.simplePkgList() avail = set(avail) @@ -279,7 +279,7 @@ def listOrphans(my): continue if po.pkgtup not in avail: - print "%s" % po + print po.hdr.sprintf(qf) def getKernels(my): """return a list of all installed kernels, sorted newest to oldest""" @@ -333,7 +333,7 @@ def userconfirm(): else: return True -def removeKernels(my, count, confirmed, keepdevel): +def removeKernels(my, count, confirmed, keepdevel, qf): """Remove old kernels, keep at most count kernels (and always keep the running kernel""" @@ -384,7 +384,7 @@ def removeKernels(my, count, confirmed, keepdevel): print "I will remove the following %s kernel related packages:" % len(toremove) for po in toremove: - print "%s" % po + print po.hdr.sprintf(qf) if not confirmed: if not userconfirm(): @@ -442,6 +442,9 @@ def parseArgs(): help="Do not remove kernel-devel packages when removing kernels") parser.add_option("-c", dest="conffile", action="store", default='/etc/yum.conf', help="config file location") + parser.add_option("--qf", "--queryformat", dest="qf", action="store", + default='%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}', + help="Query format to use for output.") (opts, args) = parser.parse_args() if not exactlyOne((opts.problems,opts.leaves,opts.kernels,opts.orphans, opts.dupes, opts.cleandupes)): @@ -460,20 +463,21 @@ def main(): if os.geteuid() != 0: print "Error: Cannot remove kernels as a user, must be root" sys.exit(1) - removeKernels(my, opts.kernelcount, opts.confirmed, opts.keepdevel) + removeKernels(my, opts.kernelcount, opts.confirmed, opts.keepdevel, + opts.qf) sys.exit(0) if (opts.leaves): listLeaves(my, opts.all_nodes, re.compile(opts.leaf_regex, re.IGNORECASE), - opts.exclude_devel, opts.exclude_bin) + opts.exclude_devel, opts.exclude_bin, opts.qf) sys.exit(0) if (opts.orphans): - listOrphans(my) + listOrphans(my, opts.qf) sys.exit(0) if opts.dupes: - printDupes(my) + printDupes(my, opts.qf) sys.exit(0) if opts.cleandupes: @@ -481,7 +485,7 @@ def main(): print "Error: Cannot remove packages as a user, must be root" sys.exit(1) - cleanOldDupes(my, opts.confirmed) + cleanOldDupes(my, opts.confirmed, opts.qf) sys.exit(0) if not opts.quiet: @@ -489,7 +493,7 @@ def main(): pkgs = getLocalRequires(my) if not opts.quiet: print "Processing all local requires" - provsomething = buildProviderList(my,pkgs,opts.problems) + provsomething = buildProviderList(my,pkgs,opts.problems,opts.qf) if __name__ == '__main__': main() -- 1.6.0.6
_______________________________________________ Yum mailing list Yum@xxxxxxxxxxxxxxxxx http://lists.baseurl.org/mailman/listinfo/yum