[Collab-qa-commits] r2404 - / epoch-mismatch-finder
Jakub Wilk
jwilk at alioth.debian.org
Thu Jul 5 21:31:11 UTC 2012
Author: jwilk
Date: 2012-07-05 21:31:10 +0000 (Thu, 05 Jul 2012)
New Revision: 2404
Added:
epoch-mismatch-finder/
epoch-mismatch-finder/epoch-mismatch-finder
Log:
Add epoch mismatch finder.
Added: epoch-mismatch-finder/epoch-mismatch-finder
===================================================================
--- epoch-mismatch-finder/epoch-mismatch-finder (rev 0)
+++ epoch-mismatch-finder/epoch-mismatch-finder 2012-07-05 21:31:10 UTC (rev 2404)
@@ -0,0 +1,197 @@
+#!/usr/bin/python3
+
+# Copyright © 2012 Jakub Wilk <jwilk at debian.org>
+
+# Redistribution and use in source and compiled forms, with or without
+# modification, are permitted under any circumstances. No warranty.
+
+import argparse
+import collections
+import dbm
+import functools
+import itertools
+import os
+import subprocess as ipc
+import sys
+
+import apt_pkg
+
+default_snapshot_host = 'stabile.debian.org'
+snapshot_command = (
+ '''psql --cluster 9.0/snapshot service=snapshot-guest -A -t -q -F " " '''
+ '''-c "select name, version from binpkg where version like '%:%'"'''
+)
+
+default_cache_file = os.path.join((
+ os.getenv('XDG_CACHE_HOME') or
+ os.path.join(os.path.expanduser('~'), '.cache')
+), 'debian', 'epoch-validator')
+
+binary_fields = 'Pre-Depends', 'Depends', 'Recommends', 'Suggests', 'Enhances'
+source_fields = 'Build-Depends', 'Build-Depends-Indep'
+
+ at functools.total_ordering
+class debian_version(object):
+
+ def __init__(self, value):
+ self.__value = str(value)
+
+ def __lt__(self, other):
+ return apt_pkg.version_compare(self.__value, other.__value) < 0
+
+ def __eq__(self, other):
+ return apt_pkg.version_compare(self.__value, other.__value) == 0
+
+ def __str__(self):
+ return self.__value
+
+ def get_epoch(self):
+ return int(str(self).split(':', 1)[0])
+
+ @staticmethod
+ def minimize(versions):
+ versions = sorted(versions, key=debian_version, reverse=1)
+ first = True
+ for epoch, epoch_versions in itertools.groupby(versions, debian_version.get_epoch):
+ epoch_versions = list(epoch_versions)
+ if first:
+ if len(epoch_versions) != 1:
+ yield max(epoch_versions)
+ first = False
+ yield min(epoch_versions)
+
+def do_seed(options):
+ version_data = collections.defaultdict(list)
+ if options.user is not None:
+ target = '{user}@{host}'.format(user=options.user, host=options.host)
+ else:
+ target = options.host
+ child = ipc.Popen(
+ ['ssh'] + (options.ssh_arguments or []) + [target, snapshot_command],
+ stdout=ipc.PIPE,
+ )
+ for line in child.stdout:
+ package, version = line.decode('ASCII', 'replace').split()
+ version_data[package] += [version]
+ if child.wait() != 0:
+ raise IOError
+ cache = dbm.open(options.cache, 'c')
+ try:
+ for package, versions in version_data.items():
+ cache[package] = ' '.join(map(str, debian_version.minimize(versions)))
+ finally:
+ cache.close()
+
+def do_dump(options):
+ cache = dbm.open(options.cache)
+ try:
+ for package in sorted(cache.keys()):
+ versions = cache[package].decode('ASCII', 'replace').split()
+ package = package.decode('ASCII', 'replace')
+ for version in versions:
+ print('{package}\t{version}'.format(package=package, version=version))
+ finally:
+ cache.close()
+
+def do_update(options):
+ raise NotImplementedError
+
+def fix_version(current_version, versions):
+ if ':' in current_version:
+ current_epoch, current_bare_version = current_version.split(':', 1)
+ current_epoch = int(current_epoch)
+ else:
+ current_epoch, current_bare_version = 0, current_version
+ max_version = None
+ for version in versions:
+ if max_version is None:
+ max_version = version
+ epoch, bare_version = version.split(':', 1)
+ epoch = int(epoch)
+ if epoch > current_epoch:
+ if debian_version(bare_version) <= debian_version(current_bare_version):
+ new_version = '{epoch}:{bare_version}'.format(epoch=epoch, bare_version=current_bare_version)
+ if debian_version(new_version) <= debian_version(max_version):
+ return new_version
+ return current_version
+
+def do_check_para(cache, para):
+ package = para['Package']
+ for is_source in False, True:
+ field_list = source_fields if is_source else binary_fields
+ parse_depends = apt_pkg.parse_src_depends if is_source else apt_pkg.parse_depends
+ first = True
+ for field in field_list:
+ first_field = True
+ try:
+ value = para[field]
+ except LookupError:
+ continue
+ for alternative in parse_depends(value):
+ for rel_package, version, relation in alternative:
+ if relation == '>': relation = '>>'
+ if relation == '<': relation = '<<'
+ if not relation.startswith('>'):
+ continue
+ try:
+ versions = cache[rel_package].decode('ASCII', 'replace').split()
+ except KeyError:
+ continue
+ new_version = fix_version(version, versions)
+ if version == new_version:
+ continue
+ if first:
+ if is_source:
+ print('Source: {package}'.format(package=package))
+ else:
+ print('Package: {package}'.format(package=package))
+ first = False
+ if first_field:
+ print('{field}:'.format(field=field))
+ first_field=False
+ print(' {rel_package} ({relation} {version}) ==> {new_version}'.format(**locals()))
+ if not first:
+ print()
+
+def do_check(options):
+ cache = dbm.open(options.cache)
+ try:
+ packages = apt_pkg.TagFile(sys.stdin)
+ for para in packages:
+ do_check_para(cache, para)
+ finally:
+ cache.close()
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--cache', metavar='<file>',
+ default=default_cache_file,
+ help='use cache file (default: {file})'.format(file=default_cache_file)
+ )
+ subparsers = parser.add_subparsers()
+ p_seed = subparsers.add_parser('seed', help='connect to snapshot.d.o database to seed the version cache')
+ p_seed.set_defaults(action=do_seed)
+ p_seed.add_argument('--host', metavar='<host>',
+ default=default_snapshot_host,
+ help='host to connect to (default: {host})'.format(host=default_snapshot_host)
+ )
+ p_seed.add_argument('--user', metavar='<user>', help='username')
+ p_seed.add_argument('--ssh-arguments', metavar='<arg>', nargs='+', help='extra arguments to pass to ssh')
+ p_dump = subparsers.add_parser('dump', help='dump contents of the version cache (for debugging purposes)')
+ p_dump.set_defaults(action=do_dump)
+ p_update = subparsers.add_parser('update', help='update the version cache')
+ p_update.set_defaults(action=do_update)
+ p_check = subparsers.add_parser('check', help='check packages')
+ p_check.set_defaults(action=do_check)
+ options = parser.parse_args()
+ options.action(options)
+
+def setup():
+ apt_pkg.init_config()
+ apt_pkg.init_system()
+
+if __name__ == '__main__':
+ setup()
+ main()
+
+# vim:ts=4 sw=4 et
Property changes on: epoch-mismatch-finder/epoch-mismatch-finder
___________________________________________________________________
Added: svn:executable
+ *
More information about the Collab-qa-commits
mailing list