#!/usr/bin/python
#
# absdbdiff.py
#
# In parts blatantly copied from check_packages.py
#
# Find and report differences between the ABS tree and the repo DBs.
import tarfile, getopt
from commands import getoutput
from sys import argv, exit
from os.path import isdir,isfile, join, dirname
DBEXT = '.db.tar.gz'
def error(msg):
print(msg)
exit(1)
def splitname(name):
split = name.rsplit('-', 2)
return((split[0],"-".join(split[1:])))
def parsedb(path):
pkgs = {}
try:
db = tarfile.open(path)
except tarfile.TarError:
error("unable to open dbfile %s. Not a valid tar file?" % path)
for name in db.getnames():
# we only want the directories
if '/' not in name:
name, vers = splitname(name)
pkgs[name] = vers
db.close()
return pkgs
def parse_pkgbuilds(repo,arch):
data = getoutput(dirname(argv[0]) + '/parse_pkgbuilds.sh '
+ arch + ' ' + absroot + '/' + repo)
return(parse_data(data))
def parse_data(data):
attrname = None
name = None
pkgs = {}
for line in data.split('\n'):
if line.startswith('%'):
attrname = line.strip('%').lower()
elif line.strip() == '':
attrname = None
elif attrname == "name":
if name != None:
pkgs[name] = version
name = line
elif attrname == "version":
version = line
pkgs[name] = version
return(pkgs)
def print_heading(heading):
print ""
print "=" * (len(heading) + 4)
print "= " + heading + " ="
print "=" * (len(heading) + 4)
def print_subheading(subheading):
print ""
print subheading
print "-" * (len(subheading) + 2)
def printset(set):
list = []
for pkg in set:
list.append(pkg)
list.sort()
for pkg in list:
print("\t%s" % pkg)
def print_result(repo, dbonly, absonly, verdiff, dbpkgs, abspkgs):
print_subheading("Results for %s" % repo)
if len(dbonly) > 0:
print("\nFound in DB but not in ABS tree:\n")
printset(dbonly)
if len(absonly) > 0:
print("\nFound in ABS tree, but not in DB:\n")
printset(absonly)
if vcmp and len(verdiff) > 0:
print("\nVerions differ:\n")
for name in verdiff:
print("\t%s\n\t\tABS:\t%s\n\t\tDB :\t%s" % (name, dbpkgs[name],
abspkgs[name]))
print("\n")
def print_usage():
print ""
print "Usage: ./absdbdiff.py [OPTION]"
print ""
print "Options:"
print " --abs-tree=<path> Check the specified tree (default : /var/abs)"
print " --repos=<r1,r2,...> Check the specified repos (default : core,extra)"
print " --arch=<any|i686|x86_64> Check the specified arch (default : i686)"
print " --repodir=<path> Check DBs in the specified dir (default : /srv/ftp)"
print " --vercmp Report differing package versions."
print " -h, --help Show this help and exit"
print ""
absroot = '/var/abs/'
repos = ['core', 'extra' ]
arch = 'i686'
repodir = '/srv/ftp/'
vcmp = False
try:
opts, args = getopt.getopt(argv[1:], "", ["abs-tree=", "repos=",
"arch=", "repodir=", "vercmp"])
except getopt.GetoptError:
print_usage()
exit()
if opts != []:
for o, a in opts:
if o in ("--abs-tree"):
absroot = a
elif o in ("--repos"):
repos = a.split(",")
elif o in ("--arch"):
arch = a
elif o in ("--repodir"):
repodir = a
elif o in ("--vercmp"):
vcmp = True
else:
print_usage()
exit()
if args != []:
print_usage()
exit()
print_heading("Diff of ABS tree and pkg DBs (arch: %s repos: %s)" % (arch,
','.join(repos)))
for repo in repos:
if not isdir(join(absroot, repo)):
error("Repo %s not found in absroot" % repo)
dbpath = join(repodir,repo,'os',arch,"%s%s" % (repo,DBEXT))
if not isfile(dbpath):
error("dbfile %s not found" % dbpath)
dbpkgs = parsedb(dbpath)
abspkgs = parse_pkgbuilds(repo, arch)
dbnames = set(dbpkgs.keys())
absnames = set(abspkgs.keys())
common = dbnames.intersection(absnames)
dbonly = dbnames.difference(absnames)
absonly = absnames.difference(dbnames)
verdiff = []
if vcmp:
for name in common:
if abspkgs[name] != dbpkgs[name]:
verdiff.append(name)
verdiff.sort()
print_result(repo, dbonly, absonly, verdiff, dbpkgs, abspkgs)
# vim: set ts=4 sw=4 noet: