From Fedora Project Wiki







import rpm
import os
import sys
import getopt

def Usage():
print "Usage: " + os.path.basename(sys.argv[0] ) + "[options]  dir1 dir2"
print "Options:"
print " --set1 pathname                          add pathname to set1"
print " --set2 pathname                          add pathname to set2"
print " --show [same|only1|only2|newer1|newer2]   what info to show"
print " --debug                                  print debugging goop"
print "                                          (default is all but same)"
sys.exit(255)

def debugmsg(msg):
if debuggingflag:
sys.stderr.write(msg)


def getevr(package):
if package['epoch'] ==None:
return ("0", package['version'] , package['release'] , package['buildhost'] )
else:
return (str(package['epoch'] ), package['version'] , package['release'] , package['buildhost'] )

def rpmcompare(package1,package2):
return rpm.labelCompare((str(package1['epoch'] ), package1['version'] , package1['release'] ),
(str(package2['epoch'] ), package2['version'] , package2['release'] ))


def readrpminfo(dirnames,setindicator="#"):
dirrpms={}

for dirname in dirnames:

dirlist=os.listdir(dirname)
dirlist.sort()

for file in dirlist:
if not file.endswith(".rpm"):
continue

debugmsg(setindicator)

fdno = os.open(dirname + "/" + file, os.O_RDONLY)
hdr = ts.hdrFromFdno(fdno)
os.close(fdno)

if hdr['name']  in dirrpms:
if rpmcompare(hdr,dirrpms[hdr['name']  ) == 1:
dirrpms[hdr['name']  =hdr
else:
pass
else:
dirrpms[hdr['name']  =hdr
debugmsg("\n")

return dirrpms

def printprettyrpmlist(rpmlist,altlist=()):

packagelist=rpmlist.keys()
packagelist.sort()

olist=[] 
elist=[] 
vlist=[] 
rlist=[] 
blist=[] 

print
for p in packagelist:
if p not in altlist:
olist.append(p)
elif  rpmlist[p] [0]  != altlist[p] [0] :
elist.append(p)
elif rpmlist[p] [1]  != altlist[p] [1] :
vlist.append(p)
elif rpmlist[p] [2]  != altlist[p] [2] :
if rpmlist[p] [3] .endswith(".bu.edu"):
blist.append(p)
else:
rlist.append(p)
else:
olist.append(p)


for p in elist:
pkgvers = "%16s -> %-16s" % (altlist[p] [0]  + ":" + altlist[p] [1]  + "-" + altlist[p] [2] ,
rpmlist[p] [0]  + ":" + rpmlist[p] [1]  + "-" + rpmlist[p] [2] )
print "E: %-30s %s" % (p,pkgvers)

for p in vlist:
pkgvers = "%16s -> %-16s" % (altlist[p] [1]  + "-" + altlist[p] [2] ,
rpmlist[p] [1]  + "-" + rpmlist[p] [2] )
print "V: %-30s %s" % (p,pkgvers)

for p in rlist:
pkgvers = "%16s -> %-16s" % (altlist[p] [1]  + "-" + altlist[p] [2] ,
rpmlist[p] [1]  + "-" + rpmlist[p] [2] )
print "R: %-30s %s" % (p,pkgvers)

for p in blist:
pkgvers = "%16s -> %-16s" % (altlist[p] [1]  + "-" + altlist[p] [2] ,
rpmlist[p] [1]  + "-" + rpmlist[p] [2] )
print "B: %-30s %s" % (p,pkgvers)








for p in olist:
print "O: %-30s" % (p)
if len(olist)>0:
print

print

try:
optlist, args = getopt.gnu_getopt(sys.argv[1:] ,"1:2:s:d",["set1=","set2=","show=","debug"] )
except getopt.GetoptError, msg:
print "Error: " + str(msg)
sys.exit(255)

set1dirs=[] 
set2dirs=[] 


if len(args) == 2:
set1dirs.append(args[0] )
set2dirs.append(args[1] )
elif len(args) > 0:
Usage()


validreports=( "same","only1","only2","newer1","newer2" )
reportstoshow={}
for r in validreports:
reportstoshow[r] =False
debuggingflag=False
showflagfound=False

for opt, optarg in optlist:
if opt=="--set1" or opt=="-1":
if optarg not in set1dirs:
set1dirs.append(optarg)
elif opt=="--set2" or opt=="-2":
if optarg not in set2dirs:
set2dirs.append(optarg)
elif opt=="--show" or opt=="-s":
if optarg in validreports:
reportstoshow[optarg] =True
showflagfound=True
else:
Usage()
elif opt=="--debug" or opt=="-d":
debuggingflag=True

if not showflagfound:
for r in validreports:
reportstoshow[r] =True
reportstoshow["same"] =False


if len(set1dirs)<1 or len(set2dirs)<1:
Usage()

for dir in set1dirs + set2dirs:
flag=False
if not os.path.isdir(dir):
print "Directory " + dir + " doesn't exist."
flag=True
if flag:
sys.exit(254)


ts = rpm.TransactionSet()
ts.setVSFlags(~(rpm._RPMVSF_NOSIGNATURES|rpm._RPMVSF_NODIGESTS))

set1dirsrpms=readrpminfo(set1dirs,"1")
set2dirsrpms=readrpminfo(set2dirs,"2")

set1dirsonly={}
set2dirsonly={}
set1dirsnewer={}
set2dirsolder={}
set2dirsnewer={}
set1dirsolder={}
bothsame={}

for package in set1dirsrpms:
if not set2dirsrpms.has_key(package):
set1dirsonly[package] =getevr(set1dirsrpms[package] )
debugmsg("+")
else:
rc=rpmcompare(set1dirsrpms[package] ,set2dirsrpms[package] )
if rc==0:
bothsame[package] =getevr(set1dirsrpms[package] )
debugmsg("=")
elif rc>0:
set1dirsnewer[package] =getevr(set1dirsrpms[package] )
set2dirsolder[package] =getevr(set2dirsrpms[package] )
debugmsg(">")
elif rc<0:
set2dirsnewer[package] =getevr(set2dirsrpms[package] )
set1dirsolder[package] =getevr(set1dirsrpms[package] )
debugmsg("<")


for package in set2dirsrpms:
if not set1dirsrpms.has_key(package):
debugmsg("-")
set2dirsonly[package] =getevr(set2dirsrpms[package] )
else:
pass

debugmsg("\n")

returncode=1

if reportstoshow["same"]  and len(bothsame)>0:
print
print "------------------------------------------------------------------------------"
print "In both " + str(set1dirs) + " and " + str(set2dirs) + ":"
printprettyrpmlist(bothsame)
returncode=0

if reportstoshow["only1"]  and len(set1dirsonly)>0:
print
print "------------------------------------------------------------------------------"
print "In " + str(set1dirs) + " only:"
printprettyrpmlist(set1dirsonly)
returncode=0

if reportstoshow["only2"]  and len(set2dirsonly)>0:
print
print "------------------------------------------------------------------------------"
print "In " + str(set2dirs) + " only:"
printprettyrpmlist(set2dirsonly)
returncode=0

if reportstoshow["newer1"]  and len(set1dirsnewer)>0:
print
print "------------------------------------------------------------------------------"
print "Newer in " + str(set1dirs) + ":"
printprettyrpmlist(set1dirsnewer,set2dirsolder)
returncode=0

if reportstoshow["newer2"]  and len(set2dirsnewer)>0:
print "------------------------------------------------------------------------------"
print "Newer in " + str(set2dirs) + ":"
printprettyrpmlist(set2dirsnewer,set1dirsolder)
returncode=0

sys.exit(returncode)