#!/usr/bin/python # import optparse import apt import sys import re import os class PkgEntry(object): def __init__(self, package=None, version=None, filename=None, sourcepkg=None, ucsversion=None): self.package = package self.version = version self.filename = filename self.sourcepkg = sourcepkg self.ucsversion = ucsversion def _get_value(self, line): return line.split(': ', 1)[1] def scan(self, entry, ucsversion): if ucsversion: self.ucsversion = ucsversion for line in entry.splitlines(): if line.startswith('Package: '): self.package = self._get_value(line) elif line.startswith('Version: '): self.version = self._get_value(line) elif line.startswith('Filename: '): self.filename = self._get_value(line) elif line.startswith('Source: '): self.sourcepkg = self._get_value(line) def is_ok(self): return bool(self.package) and bool(self.version) def load_packages_file(filename, target_dict, ucsversion): if not os.path.exists(filename): print 'E: %r does not exist' % (filename,) return # load file content = open(filename, 'r').read() for entry in content.split('\n\n'): # scan each entry item = PkgEntry() item.scan(entry, ucsversion) if item.is_ok(): if item.package in target_dict: if apt.VersionCompare(target_dict[item.package].version, item.version) < 0: target_dict[item.package] = item else: target_dict[item.package] = item def load_version(version): major, minor, patchlevel = [int(x) for x in version.replace('-', '.').split('.', 2)] target = {} for i_minor in xrange(0, minor+1): for i_patchlevel in xrange(0, 99): fn = '/var/univention/buildsystem2/apt/ucs_%d.%d-0' % (major, i_minor) if not i_patchlevel == 0: fn = '/var/univention/buildsystem2/apt/ucs_%d.%d-0-ucs%d.%d-%d' % (major, i_minor, major, i_minor, i_patchlevel) if not os.path.isdir(fn): break print 'Loading', fn for arch in ('all', 'i386', 'amd64'): load_packages_file(os.path.join(fn, arch, 'Packages'), target, os.path.basename(fn)) fn = '/var/univention/buildsystem2/apt/ucs_%d.%d-0-errata%d.%d-%d' % (major, i_minor, major, i_minor, i_patchlevel) if os.path.isdir(fn): print 'Loading', fn for arch in ('all', 'i386', 'amd64'): load_packages_file(os.path.join(fn, arch, 'Packages'), target, os.path.basename(fn)) return target def compare(old, new): errors = 0 pkglist = sorted(new.keys()) srcpkglist = set() for pkg in pkglist: if pkg in old: if apt.VersionCompare(old[pkg].version, new[pkg].version) > 0: if errors == 0: print print '--------------------------------------------------------------------------------------' print ' The following packages use a smaller package version within the newer UCS release:' print '--------------------------------------------------------------------------------------' print print 'PKG: %s' % (pkg,) print ' %s: %s' % (old[pkg].ucsversion, old[pkg].version) print ' %s: %s' % (new[pkg].ucsversion, new[pkg].version) srcpkg = new[pkg].sourcepkg if not srcpkg: srcpkg = pkg srcpkglist.add(srcpkg) print ' Src pkg: %s' % (srcpkg,) print errors += 1 print print 'Affected source packages:' for pkg in sorted(list(srcpkglist)): print ' %s' % (pkg,) print print 'Number of affected binary packages: %d' % (errors,) print 'Number of affected source packages: %d' % (len(srcpkglist),) return 1 if errors else 0 def main(): usage = '''%progname Loads all Packages files up to last major version for both given versions and compares the available package versions.''' parser = optparse.OptionParser(usage=usage) (options, args) = parser.parse_args() if len(args) != 2: parser.print_usage() sys.exit(1) print 'Comparing UCS versions %s and %s:\n' % (args[0], args[1]) old = load_version(args[0]) new = load_version(args[1]) sys.exit(compare(old, new)) if __name__ == '__main__': main()