From 09e9e164316284365718f9bb01c40af0752f6403 Mon Sep 17 00:00:00 2001 From: Niels Thykier Date: Sun, 11 Aug 2013 15:23:45 +0200 Subject: [PATCH 01/14] Reduce the number of "used-once" lists Where possible, avoid creating a list only to discard immediately afterwards. Example: """ for x in sorted([x for x in ...]): ... """ Creates a list, passes it to sorted, which generates a new list and sorts that copy. Since sorted accepts an iterable, we can avoid the "inner" list and just pass it a generator expression instead. Signed-off-by: Niels Thykier --- britney.py | 46 +++++++++++++++++++++++----------------------- britney_util.py | 3 ++- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/britney.py b/britney.py index f03d988..1346f7e 100755 --- a/britney.py +++ b/britney.py @@ -190,6 +190,7 @@ import urllib import apt_pkg from functools import reduce, partial +from itertools import chain, ifilter from operator import attrgetter if __name__ == '__main__': @@ -623,7 +624,7 @@ class Britney(object): object attribute `bugs'. """ # loop on all the package names from testing and unstable bug summaries - for pkg in set(self.bugs['testing'].keys() + self.bugs['unstable'].keys()): + for pkg in set(chain(self.bugs['testing'], self.bugs['unstable'])): # make sure that the key is present in both dictionaries if pkg not in self.bugs['testing']: @@ -677,7 +678,7 @@ class Britney(object): filename = os.path.join(basedir, "Dates") self.__log("Writing upload data to %s" % filename) f = open(filename, 'w') - for pkg in sorted(dates.keys()): + for pkg in sorted(dates): f.write("%s %s %d\n" % ((pkg,) + dates[pkg])) f.close() @@ -857,7 +858,6 @@ class Britney(object): f.write(output + "\n") f.close() - # Utility methods for package analysis # ------------------------------------ @@ -1028,7 +1028,7 @@ class Britney(object): anyworthdoing = False # for every binary package produced by this source in unstable for this architecture - for pkg in sorted(filter(lambda x: x.endswith("/" + arch), source_u[BINARIES]), key=lambda x: x.split("/")[0]): + for pkg in sorted(ifilter(lambda x: x.endswith("/" + arch), source_u[BINARIES]), key=lambda x: x.split("/")[0]): pkg_name = pkg.split("/")[0] # retrieve the testing (if present) and unstable corresponding binary packages @@ -1096,7 +1096,7 @@ class Britney(object): arch, suite) - for pkg in sorted([x.split("/")[0] for x in source_data[BINARIES] if x.endswith("/"+arch)]): + for pkg in sorted(x.split("/")[0] for x in source_data[BINARIES] if x.endswith("/"+arch)): # if the package is architecture-independent, then ignore it tpkg_data = self.binaries['testing'][arch][0][pkg] if tpkg_data[ARCHITECTURE] == 'all': @@ -1298,7 +1298,7 @@ class Britney(object): for arch in self.options.architectures: oodbins = {} # for every binary package produced by this source in the suite for this architecture - for pkg in sorted([x.split("/")[0] for x in self.sources[suite][src][BINARIES] if x.endswith("/"+arch)]): + for pkg in sorted(x.split("/")[0] for x in self.sources[suite][src][BINARIES] if x.endswith("/"+arch)): if pkg not in pkgs: pkgs[pkg] = [] pkgs[pkg].append(arch) @@ -1349,7 +1349,7 @@ class Britney(object): # updating testing; if the unstable package has RC bugs that do not apply to the testing # one, the check fails and we set update_candidate to False to block the update if suite == 'unstable': - for pkg in pkgs.keys(): + for pkg in pkgs: bugs_t = [] bugs_u = [] if pkg in self.bugs['testing']: @@ -1573,7 +1573,7 @@ class Britney(object): self.invalidate_excuses(upgrade_me, unconsidered) # sort the list of candidates - self.upgrade_me = sorted([ MigrationItem(x) for x in upgrade_me ]) + self.upgrade_me = sorted( MigrationItem(x) for x in upgrade_me ) # write excuses to the output file if not self.options.dry_run: @@ -1932,7 +1932,7 @@ class Britney(object): to_check = [] # broken packages (first round) - for p in [x[0] for x in affected if x[1] == arch]: + for p in (x[0] for x in affected if x[1] == arch): if p not in binaries[arch][0]: continue nuninst_arch = None @@ -1993,7 +1993,7 @@ class Britney(object): if lundo is None: lundo = [] if not hint: - self.output_write("recur: [%s] %s %d/%d\n" % ("", ",".join([x.uvname for x in selected]), len(packages), len(extra))) + self.output_write("recur: [%s] %s %d/%d\n" % ("", ",".join(x.uvname for x in selected), len(packages), len(extra))) # loop on the packages (or better, actions) while packages: @@ -2037,8 +2037,8 @@ class Britney(object): skip_archall = True else: skip_archall = False - nuninst[arch] = set([x for x in nuninst_comp[arch] if x in binaries[arch][0]]) - nuninst[arch + "+all"] = set([x for x in nuninst_comp[arch + "+all"] if x in binaries[arch][0]]) + nuninst[arch] = set(x for x in nuninst_comp[arch] if x in binaries[arch][0]) + nuninst[arch + "+all"] = set(x for x in nuninst_comp[arch + "+all"] if x in binaries[arch][0]) check_packages(arch, affected, skip_archall, nuninst, pkg) @@ -2068,15 +2068,15 @@ class Britney(object): self.output_write(" pre: %s\n" % (self.eval_nuninst(nuninst_comp))) self.output_write(" now: %s\n" % (self.eval_nuninst(nuninst, nuninst_comp))) if len(selected) <= 20: - self.output_write(" all: %s\n" % (" ".join([ x.uvname for x in selected ]))) + self.output_write(" all: %s\n" % (" ".join( x.uvname for x in selected ))) else: - self.output_write(" most: (%d) .. %s\n" % (len(selected), " ".join([x.uvname for x in selected][-20:]))) + self.output_write(" most: (%d) .. %s\n" % (len(selected), " ".join(x.uvname for x in selected[-20:]))) for k in nuninst: nuninst_comp[k] = nuninst[k] else: self.output_write("skipped: %s (%d <- %d)\n" % (pkg, len(extra), len(packages))) self.output_write(" got: %s\n" % (self.eval_nuninst(nuninst, pkg.architecture != 'source' and nuninst_comp or None))) - self.output_write(" * %s: %s\n" % (arch, ", ".join(sorted([b for b in nuninst[arch] if b not in nuninst_comp[arch]])))) + self.output_write(" * %s: %s\n" % (arch, ", ".join(sorted(b for b in nuninst[arch] if b not in nuninst_comp[arch])))) extra.append(pkg) if not mark_passed: @@ -2089,7 +2089,7 @@ class Britney(object): if hint: return (nuninst_comp, []) - self.output_write(" finish: [%s]\n" % ",".join([ x.uvname for x in selected ])) + self.output_write(" finish: [%s]\n" % ",".join( x.uvname for x in selected )) self.output_write("endloop: %s\n" % (self.eval_nuninst(self.nuninst_orig))) self.output_write(" now: %s\n" % (self.eval_nuninst(nuninst_comp))) self.output_write(eval_uninst(self.options.architectures, @@ -2126,7 +2126,7 @@ class Britney(object): if init: if not force: lundo = [] - self.output_write("leading: %s\n" % (",".join([ x.uvname for x in init ]))) + self.output_write("leading: %s\n" % (",".join( x.uvname for x in init ))) for x in init: if x not in upgrade_me: self.output_write("failed: %s\n" % (x.uvname)) @@ -2163,7 +2163,7 @@ class Britney(object): # Result accepted either by force or by being better than the original result. if recurse: self.output_write("Apparently successful\n") - self.output_write("final: %s\n" % ",".join(sorted([ x.uvname for x in selected ]))) + self.output_write("final: %s\n" % ",".join(sorted( x.uvname for x in selected ))) self.output_write("start: %s\n" % self.eval_nuninst(nuninst_start)) if not force: self.output_write(" orig: %s\n" % self.eval_nuninst(self.nuninst_orig)) @@ -2231,7 +2231,7 @@ class Britney(object): allpackages += self.upgrade_me for a in self.options.break_arches.split(): backup = self.options.break_arches - self.options.break_arches = " ".join([x for x in self.options.break_arches.split() if x != a]) + self.options.break_arches = " ".join(x for x in self.options.break_arches.split() if x != a) self.upgrade_me = archpackages[a] self.output_write("info: broken arch run for %s\n" % (a)) self.do_all() @@ -2472,7 +2472,7 @@ class Britney(object): self.__log("> Processing hints from the auto hinter", type="I") # consider only excuses which are valid candidates - excuses = dict([(x.name, x) for x in self.excuses if x.name in [y.uvname for y in self.upgrade_me]]) + excuses = dict((x.name, x) for x in self.excuses if x.name in [y.uvname for y in self.upgrade_me]) def find_related(e, hint, circular_first=False): if e not in excuses: @@ -2506,9 +2506,9 @@ class Britney(object): looped = False for item, ver in items: # excuses which depend on "item" or are depended on by it - items.extend( [ (x, excuses[x].ver[1]) for x in excuses if \ + items.extend( (x, excuses[x].ver[1]) for x in excuses if \ (item in excuses[x].deps or x in excuses[item].deps) \ - and (x, excuses[x].ver[1]) not in items ] ) + and (x, excuses[x].ver[1]) not in items ) if not looped and len(items) > 1: mincands.append(items[:]) looped = True @@ -2563,7 +2563,7 @@ class Britney(object): print '* %s' % (arch,) - for (src, ver), pkgs in sorted(all.items()): + for (src, ver), pkgs in sorted(all.iteritems()): print ' %s (%s): %s' % (src, ver, ' '.join(sorted(pkgs))) print diff --git a/britney_util.py b/britney_util.py index 66d949b..565f732 100644 --- a/britney_util.py +++ b/britney_util.py @@ -273,7 +273,8 @@ def write_nuninst(filename, nuninst): # redundant. f.write("Built on: " + time.strftime("%Y.%m.%d %H:%M:%S %z", time.gmtime(time.time())) + "\n") f.write("Last update: " + time.strftime("%Y.%m.%d %H:%M:%S %z", time.gmtime(time.time())) + "\n\n") - f.write("".join([k + ": " + " ".join(nuninst[k]) + "\n" for k in nuninst])) + for k in nuninst: + f.write("%s: %s\n" % (k, " ".join(nuninst[k]))) def read_nuninst(filename, architectures): From 629c80937d07567c42109d68917faaadc74e1588 Mon Sep 17 00:00:00 2001 From: "Adam D. Barratt" Date: Sat, 7 Sep 2013 16:57:35 +0000 Subject: [PATCH 02/14] britney_util: add make_hintitem() This function allows a textual representation of a package (e.g. "foo/amd64") to be convered to a HintItem(). Signed-off-by: Adam D. Barratt --- britney_util.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/britney_util.py b/britney_util.py index 565f732..d440039 100644 --- a/britney_util.py +++ b/britney_util.py @@ -23,7 +23,7 @@ from functools import partial from itertools import chain, ifilter, ifilterfalse, izip, repeat import re import time - +from migrationitem import HintItem, MigrationItem from consts import (VERSION, BINARIES, PROVIDES, DEPENDS, CONFLICTS, RDEPENDS, RCONFLICTS, ARCHITECTURE, SECTION) @@ -361,3 +361,13 @@ def write_heidi(filename, sources_t, packages_t, srcv = src[VERSION] srcsec = src[SECTION] or 'unknown' f.write('%s %s source %s\n' % (src_name, srcv, srcsec)) + +def make_hintitem(package, sources, VERSION=VERSION): + """Convert a textual package specification to a HintItem + + sources is a list of source packages in each suite, used to determine + the version which should be used for the HintItem. + """ + + item = MigrationItem(package) + return HintItem("%s/%s" % (item.uvname, sources[item.suite][item.package][VERSION])) From 89bc7c8d61fc3170dd8187e23ed368ef1141a9a1 Mon Sep 17 00:00:00 2001 From: "Adam D. Barratt" Date: Sat, 7 Sep 2013 16:59:06 +0000 Subject: [PATCH 03/14] Replace uses of MigrationItem with HintItem Signed-off-by: Adam D. Barratt --- britney.py | 26 +++++++++++++------------- britney_util.py | 7 +++---- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/britney.py b/britney.py index 1346f7e..17f0a5c 100755 --- a/britney.py +++ b/britney.py @@ -215,7 +215,7 @@ from britney import buildSystem from britney_util import (old_libraries_format, same_source, undo_changes, register_reverses, compute_reverse_tree, read_nuninst, write_nuninst, write_heidi, - eval_uninst, newly_uninst) + eval_uninst, newly_uninst, make_hintitem) from consts import (VERSION, SECTION, BINARIES, MAINTAINER, FAKESRC, SOURCE, SOURCEVER, ARCHITECTURE, DEPENDS, CONFLICTS, PROVIDES, RDEPENDS, RCONFLICTS) @@ -1573,7 +1573,7 @@ class Britney(object): self.invalidate_excuses(upgrade_me, unconsidered) # sort the list of candidates - self.upgrade_me = sorted( MigrationItem(x) for x in upgrade_me ) + self.upgrade_me = sorted( make_hintitem(x, self.sources) for x in upgrade_me ) # write excuses to the output file if not self.options.dry_run: @@ -2011,14 +2011,14 @@ class Britney(object): defer = False for p in dependencies.get(pkg, []): if p in skipped: - deferred.append(pkg) - skipped.append(pkg) + deferred.append(make_hintitem(pkg, self.sources)) + skipped.append(make_hintitem(pkg, self.sources)) defer = True break if defer: continue if not hint: - self.output_write("trying: %s\n" % (pkg)) + self.output_write("trying: %s\n" % (pkg.uvname)) better = True nuninst = {} @@ -2040,7 +2040,7 @@ class Britney(object): nuninst[arch] = set(x for x in nuninst_comp[arch] if x in binaries[arch][0]) nuninst[arch + "+all"] = set(x for x in nuninst_comp[arch + "+all"] if x in binaries[arch][0]) - check_packages(arch, affected, skip_archall, nuninst, pkg) + check_packages(arch, affected, skip_archall, nuninst, pkg.uvname) # if we are processing hints, go ahead if hint: @@ -2063,7 +2063,7 @@ class Britney(object): selected.append(pkg) packages.extend(extra) extra = [] - self.output_write("accepted: %s\n" % (pkg)) + self.output_write("accepted: %s\n" % (pkg.uvname)) self.output_write(" ori: %s\n" % (self.eval_nuninst(self.nuninst_orig))) self.output_write(" pre: %s\n" % (self.eval_nuninst(nuninst_comp))) self.output_write(" now: %s\n" % (self.eval_nuninst(nuninst, nuninst_comp))) @@ -2074,13 +2074,13 @@ class Britney(object): for k in nuninst: nuninst_comp[k] = nuninst[k] else: - self.output_write("skipped: %s (%d <- %d)\n" % (pkg, len(extra), len(packages))) + self.output_write("skipped: %s (%d <- %d)\n" % (pkg.uvname, len(extra), len(packages))) self.output_write(" got: %s\n" % (self.eval_nuninst(nuninst, pkg.architecture != 'source' and nuninst_comp or None))) self.output_write(" * %s: %s\n" % (arch, ", ".join(sorted(b for b in nuninst[arch] if b not in nuninst_comp[arch])))) - extra.append(pkg) + extra.append(item) if not mark_passed: - skipped.append(pkg) + skipped.append(item) single_undo = [(undo, item)] # (local-scope) binaries is actually self.binaries["testing"] so we cannot use it here. undo_changes(single_undo, systems, sources, self.binaries) @@ -2281,7 +2281,7 @@ class Britney(object): if len(removals) > 0: self.output_write("Removing packages left in testing for smooth updates (%d):\n%s" % \ (len(removals), old_libraries_format(removals))) - self.do_all(actions=[ MigrationItem(x) for x in removals ]) + self.do_all(actions=removals) removals = self.old_libraries() else: removals = () @@ -2451,7 +2451,7 @@ class Britney(object): self.dependencies[e.name] = e.deps # replace the list of actions with the new one - self.upgrade_me = [ MigrationItem(x) for x in upgrade_me ] + self.upgrade_me = [ make_hintitem(x, self.sources) for x in upgrade_me ] def auto_hinter(self): """Auto-generate "easy" hints. @@ -2551,7 +2551,7 @@ class Britney(object): pkg = testing[arch][0][pkg_name] if pkg_name not in unstable[arch][0] and \ not same_source(sources[pkg[SOURCE]][VERSION], pkg[SOURCEVER]): - removals.append("-" + pkg_name + "/" + arch) + removals.append(HintItem("-" + pkg_name + "/" + arch + "/" + pkg[SOURCEVER])) return removals def nuninst_arch_report(self, nuninst, arch): diff --git a/britney_util.py b/britney_util.py index d440039..40b41eb 100644 --- a/britney_util.py +++ b/britney_util.py @@ -154,12 +154,11 @@ def old_libraries_format(libs): """Format old libraries in a smart table""" libraries = {} for i in libs: - pkg, arch = i.split("/") - pkg = pkg[1:] + pkg = i.package if pkg in libraries: - libraries[pkg].append(arch) + libraries[pkg].append(i.architecture) else: - libraries[pkg] = [arch] + libraries[pkg] = [i.architecture] return "\n".join(" " + k + ": " + " ".join(libraries[k]) for k in libraries) + "\n" From e75c4a48157caec6974827d26e4b513aa8a87afa Mon Sep 17 00:00:00 2001 From: "Adam D. Barratt" Date: Sat, 7 Sep 2013 17:01:58 +0000 Subject: [PATCH 04/14] Make MigrationItems versionned by default As HintItem is now redundant, also replace it with a new class - UnversionnedMigrationItem - and migrate users of the classes to use the new versions. Signed-off-by: Adam D. Barratt --- britney.py | 10 +++++----- britney_util.py | 8 ++++---- migrationitem.py | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/britney.py b/britney.py index 17f0a5c..53a4fba 100755 --- a/britney.py +++ b/britney.py @@ -209,7 +209,7 @@ if __name__ == '__main__': sys.path.insert(0, idir) from excuse import Excuse -from migrationitem import MigrationItem, HintItem +from migrationitem import MigrationItem from hints import HintCollection from britney import buildSystem from britney_util import (old_libraries_format, same_source, undo_changes, @@ -2267,7 +2267,7 @@ class Britney(object): for arch in binaries for binary in binaries[arch][0] ) - removals = [ HintItem("-%s/%s" % (source, sources[source][VERSION])) + removals = [ MigrationItem("-%s/%s" % (source, sources[source][VERSION])) for source in sources if source not in used ] if len(removals) > 0: @@ -2377,7 +2377,7 @@ class Britney(object): """ if isinstance(pkgvers[0], tuple) or isinstance(pkgvers[0], list): - _pkgvers = [ HintItem('%s/%s' % (p, v)) for (p,v) in pkgvers ] + _pkgvers = [ MigrationItem('%s/%s' % (p, v)) for (p,v) in pkgvers ] else: _pkgvers = pkgvers @@ -2530,7 +2530,7 @@ class Britney(object): to_skip.append(i) for i in range(len(l)): if i not in to_skip: - self.do_hint("easy", "autohinter", [ HintItem("%s/%s" % (x[0], x[1])) for x in l[i] ]) + self.do_hint("easy", "autohinter", [ MigrationItem("%s/%s" % (x[0], x[1])) for x in l[i] ]) def old_libraries(self, same_source=same_source): """Detect old libraries left in testing for smooth transitions @@ -2551,7 +2551,7 @@ class Britney(object): pkg = testing[arch][0][pkg_name] if pkg_name not in unstable[arch][0] and \ not same_source(sources[pkg[SOURCE]][VERSION], pkg[SOURCEVER]): - removals.append(HintItem("-" + pkg_name + "/" + arch + "/" + pkg[SOURCEVER])) + removals.append(MigrationItem("-" + pkg_name + "/" + arch + "/" + pkg[SOURCEVER])) return removals def nuninst_arch_report(self, nuninst, arch): diff --git a/britney_util.py b/britney_util.py index 40b41eb..2552a69 100644 --- a/britney_util.py +++ b/britney_util.py @@ -362,11 +362,11 @@ def write_heidi(filename, sources_t, packages_t, f.write('%s %s source %s\n' % (src_name, srcv, srcsec)) def make_hintitem(package, sources, VERSION=VERSION): - """Convert a textual package specification to a HintItem + """Convert a textual package specification to a MigrationItem sources is a list of source packages in each suite, used to determine - the version which should be used for the HintItem. + the version which should be used for the MigrationItem. """ - item = MigrationItem(package) - return HintItem("%s/%s" % (item.uvname, sources[item.suite][item.package][VERSION])) + item = UnversionnedMigrationItem(package) + return MigrationItem("%s/%s" % (item.uvname, sources[item.suite][item.package][VERSION])) diff --git a/migrationitem.py b/migrationitem.py index 1ab50b4..f5b49b2 100644 --- a/migrationitem.py +++ b/migrationitem.py @@ -23,7 +23,7 @@ class MigrationItem(object): def get_architectures(cls): return cls._architectures - def __init__(self, name = None, versionned = False): + def __init__(self, name = None, versionned = True): self._name = None self._uvname = None self._package = None @@ -141,6 +141,6 @@ class MigrationItem(object): def uvname(self): return self._uvname -class HintItem(MigrationItem): +class UnversionnedMigrationItem(MigrationItem): def __init__(self, name = None): - MigrationItem.__init__(self, name = name, versionned = True) + MigrationItem.__init__(self, name = name, versionned = False) From 504c0f9d0a39debd4ebfd6ad9ba1ce867d15ef0d Mon Sep 17 00:00:00 2001 From: "Adam D. Barratt" Date: Sat, 7 Sep 2013 17:07:32 +0000 Subject: [PATCH 05/14] hints: use MigrationItem Signed-off-by: Adam D. Barratt --- hints.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hints.py b/hints.py index 874c1b3..8971b3a 100644 --- a/hints.py +++ b/hints.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright (C) 2011 Adam D. Barratt +# Copyright (C) 2013 Adam D. Barratt # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -12,7 +12,7 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -from migrationitem import HintItem +from migrationitem import MigrationItem class HintCollection(object): def __init__(self): @@ -57,7 +57,7 @@ class Hint(object): if isinstance(self._packages, str): self._packages = self._packages.split(' ') - self._packages = [HintItem(x) for x in self._packages] + self._packages = [MigrationItem(x) for x in self._packages] def set_active(self, active): self._active = active From cf676f410586529faf3c7723b300f8280b52d843 Mon Sep 17 00:00:00 2001 From: "Adam D. Barratt" Date: Sat, 7 Sep 2013 17:08:21 +0000 Subject: [PATCH 06/14] britney_util: fix imports for the MigrationItem class rename Signed-off-by: Adam D. Barratt --- britney_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/britney_util.py b/britney_util.py index 2552a69..5d1c913 100644 --- a/britney_util.py +++ b/britney_util.py @@ -23,7 +23,7 @@ from functools import partial from itertools import chain, ifilter, ifilterfalse, izip, repeat import re import time -from migrationitem import HintItem, MigrationItem +from migrationitem import MigrationItem, UnversionnedMigrationItem from consts import (VERSION, BINARIES, PROVIDES, DEPENDS, CONFLICTS, RDEPENDS, RCONFLICTS, ARCHITECTURE, SECTION) From f1291b74635a0a7d44eeac6c109a2f41c15e602c Mon Sep 17 00:00:00 2001 From: "Adam D. Barratt" Date: Sat, 7 Sep 2013 18:19:17 +0000 Subject: [PATCH 07/14] Rename make_hintitem() to make_migrationitem() Signed-off-by: Adam D. Barratt --- britney.py | 10 +++++----- britney_util.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/britney.py b/britney.py index 53a4fba..c7d4e66 100755 --- a/britney.py +++ b/britney.py @@ -215,7 +215,7 @@ from britney import buildSystem from britney_util import (old_libraries_format, same_source, undo_changes, register_reverses, compute_reverse_tree, read_nuninst, write_nuninst, write_heidi, - eval_uninst, newly_uninst, make_hintitem) + eval_uninst, newly_uninst, make_migrationitem) from consts import (VERSION, SECTION, BINARIES, MAINTAINER, FAKESRC, SOURCE, SOURCEVER, ARCHITECTURE, DEPENDS, CONFLICTS, PROVIDES, RDEPENDS, RCONFLICTS) @@ -1573,7 +1573,7 @@ class Britney(object): self.invalidate_excuses(upgrade_me, unconsidered) # sort the list of candidates - self.upgrade_me = sorted( make_hintitem(x, self.sources) for x in upgrade_me ) + self.upgrade_me = sorted( make_migrationitem(x, self.sources) for x in upgrade_me ) # write excuses to the output file if not self.options.dry_run: @@ -2011,8 +2011,8 @@ class Britney(object): defer = False for p in dependencies.get(pkg, []): if p in skipped: - deferred.append(make_hintitem(pkg, self.sources)) - skipped.append(make_hintitem(pkg, self.sources)) + deferred.append(make_migrationitem(pkg, self.sources)) + skipped.append(make_migrationitem(pkg, self.sources)) defer = True break if defer: continue @@ -2451,7 +2451,7 @@ class Britney(object): self.dependencies[e.name] = e.deps # replace the list of actions with the new one - self.upgrade_me = [ make_hintitem(x, self.sources) for x in upgrade_me ] + self.upgrade_me = [ make_migrationitem(x, self.sources) for x in upgrade_me ] def auto_hinter(self): """Auto-generate "easy" hints. diff --git a/britney_util.py b/britney_util.py index 5d1c913..672bbfa 100644 --- a/britney_util.py +++ b/britney_util.py @@ -361,7 +361,7 @@ def write_heidi(filename, sources_t, packages_t, srcsec = src[SECTION] or 'unknown' f.write('%s %s source %s\n' % (src_name, srcv, srcsec)) -def make_hintitem(package, sources, VERSION=VERSION): +def make_migrationitem(package, sources, VERSION=VERSION): """Convert a textual package specification to a MigrationItem sources is a list of source packages in each suite, used to determine From 54b641945d544611d9ace731a6fdcc2c57535d04 Mon Sep 17 00:00:00 2001 From: "Adam D. Barratt" Date: Sat, 7 Sep 2013 18:21:00 +0000 Subject: [PATCH 08/14] Update copyright Signed-off-by: Adam D. Barratt --- britney.py | 2 +- britney_util.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/britney.py b/britney.py index c7d4e66..25eb6ba 100755 --- a/britney.py +++ b/britney.py @@ -4,7 +4,7 @@ # Copyright (C) 2001-2008 Anthony Towns # Andreas Barth # Fabio Tranchitella -# Copyright (C) 2010-2012 Adam D. Barratt +# Copyright (C) 2010-2013 Adam D. Barratt # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/britney_util.py b/britney_util.py index 672bbfa..4f8a36f 100644 --- a/britney_util.py +++ b/britney_util.py @@ -6,6 +6,9 @@ # Fabio Tranchitella # Copyright (C) 2010-2012 Adam D. Barratt # Copyright (C) 2012 Niels Thykier +# +# New portions +# Copyright (C) 2013 Adam D. Barratt # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by From 0e3d363598df8f0525b35888a9c1b21c1e96b663 Mon Sep 17 00:00:00 2001 From: "Adam D. Barratt" Date: Wed, 11 Sep 2013 19:25:57 +0000 Subject: [PATCH 09/14] Add sanity-checking of hints So far we only check that hints which should have version information do (and those which should not do not). Signed-off-by: Adam D. Barratt --- hints.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/hints.py b/hints.py index 8971b3a..6586e48 100644 --- a/hints.py +++ b/hints.py @@ -36,6 +36,8 @@ class HintCollection(object): self._hints.append(Hint(hint, user)) class Hint(object): + NO_VERSION = [ 'block', 'block-all', 'block-udeb' ] + def __init__(self, hint, user): self._hint = hint self._user = user @@ -58,6 +60,15 @@ class Hint(object): self._packages = self._packages.split(' ') self._packages = [MigrationItem(x) for x in self._packages] + + self.check() + + def check(self): + for package in self.packages: + if self.type in self.__class__.NO_VERSION: + assert package.version is None, package + else: + assert package.version is not None, package def set_active(self, active): self._active = active From 84718b7083d795c04058bd326058a5e25eb0a231 Mon Sep 17 00:00:00 2001 From: "Adam D. Barratt" Date: Wed, 11 Sep 2013 19:50:33 +0000 Subject: [PATCH 10/14] Make hint comparison more intelligent "easy foo/1 bar/2" and "easy bar/2 foo/1" are simply different ways of writing the same hint, so the corresponding Hint objects should compare as equal. Signed-off-by: Adam D. Barratt --- hints.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hints.py b/hints.py index 6586e48..b54584c 100644 --- a/hints.py +++ b/hints.py @@ -77,7 +77,12 @@ class Hint(object): return self._hint def __eq__(self, other): - return str(self) == str(other) + if self.type != other.type: + return False + elif self.type == 'age-days' and self.days != other.days: + return False + else: + return frozenset(self.packages) == frozenset(other.packages) @property def type(self): From 4576882338c2cb1e8b59681e474057019e2c18db Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 17 Sep 2013 20:07:38 +0000 Subject: [PATCH 11/14] Support :any architecture qualifiers for multiarch Multiarch adds a Depends: foo:any syntax, permitted only if the target of the dependency is "Multi-Arch: allowed". This has been supported by dpkg and apt for some time and is now safe to use in unstable. [Adam D. Barratt: adjusted to use consts.py] Signed-off-by: Adam D. Barratt --- britney.py | 20 +++++++++++++++----- consts.py | 13 +++++++------ lib/britney-py.c | 37 +++++++++++++++++++++++++------------ lib/dpkg.c | 32 +++++++++++++++++++++++++------- lib/dpkg.h | 3 +++ 5 files changed, 75 insertions(+), 30 deletions(-) diff --git a/britney.py b/britney.py index 25eb6ba..037645f 100755 --- a/britney.py +++ b/britney.py @@ -218,7 +218,7 @@ from britney_util import (old_libraries_format, same_source, undo_changes, eval_uninst, newly_uninst, make_migrationitem) from consts import (VERSION, SECTION, BINARIES, MAINTAINER, FAKESRC, SOURCE, SOURCEVER, ARCHITECTURE, DEPENDS, CONFLICTS, - PROVIDES, RDEPENDS, RCONFLICTS) + PROVIDES, RDEPENDS, RCONFLICTS, MULTIARCH) __author__ = 'Fabio Tranchitella and the Debian Release Team' __version__ = '2.0' @@ -524,6 +524,7 @@ class Britney(object): pkg, version, get_field('Architecture'), + get_field('Multi-Arch'), None, # Pre-depends - leave as None for the C-code deps, ', '.join(final_conflicts_list) or None, @@ -824,7 +825,7 @@ class Britney(object): binaries = self.binaries[suite][arch][0] for pkg in binaries: output = "Package: %s\n" % pkg - for key, k in ((SECTION, 'Section'), (ARCHITECTURE, 'Architecture'), (SOURCE, 'Source'), (VERSION, 'Version'), + for key, k in ((SECTION, 'Section'), (ARCHITECTURE, 'Architecture'), (MULTIARCH, 'Multi-Arch'), (SOURCE, 'Source'), (VERSION, 'Version'), (DEPENDS, 'Depends'), (PROVIDES, 'Provides'), (CONFLICTS, 'Conflicts')): if not binaries[pkg][key]: continue if key == SOURCE: @@ -880,12 +881,19 @@ class Britney(object): # for every package, version and operation in the block for name, version, op in block: + if ":" in name: + name, archqual = name.split(":", 1) + else: + archqual = None + # look for the package in unstable if name in binaries[0]: package = binaries[0][name] - # check the versioned dependency (if present) + # check the versioned dependency and architecture qualifier + # (if present) if op == '' and version == '' or apt_pkg.check_dep(package[VERSION], op, version): - packages.append(name) + if archqual is None or (archqual == 'any' and package[MULTIARCH] == 'allowed'): + packages.append(name) # look for the package in the virtual packages list and loop on them for prov in binaries[1].get(name, []): @@ -893,7 +901,9 @@ class Britney(object): package = binaries[0][prov] # A provides only satisfies an unversioned dependency # (per Policy Manual §7.5) - if op == '' and version == '': + # A provides only satisfies a dependency without an + # architecture qualifier (per analysis of apt code) + if op == '' and version == '' and archqual is None: packages.append(prov) return (len(packages) > 0, packages) diff --git a/consts.py b/consts.py index 47670b2..eba22d2 100644 --- a/consts.py +++ b/consts.py @@ -29,11 +29,12 @@ FAKESRC = 4 SOURCE = 2 SOURCEVER = 3 ARCHITECTURE = 4 -# PREDEPENDS = 5 - No longer used by the python code +MULTIARCH = 5 +# PREDEPENDS = 6 - No longer used by the python code # - The C-code needs it for alignment reasons and still check it # but ignore it if it is None (so keep it None). -DEPENDS = 6 -CONFLICTS = 7 -PROVIDES = 8 -RDEPENDS = 9 -RCONFLICTS = 10 +DEPENDS = 7 +CONFLICTS = 8 +PROVIDES = 9 +RDEPENDS = 10 +RCONFLICTS = 11 diff --git a/lib/britney-py.c b/lib/britney-py.c index c2d9bf8..28ace3c 100644 --- a/lib/britney-py.c +++ b/lib/britney-py.c @@ -106,23 +106,29 @@ static PyObject *dpkgpackages_add_binary(dpkgpackages *self, PyObject *args) { pyString = PyList_GetItem(value, 5); if (pyString == NULL) return NULL; + if (pyString != Py_None) { + pkg->multiarch = PyString_AsString(pyString); + } else pkg->multiarch = NULL; + + pyString = PyList_GetItem(value, 6); + if (pyString == NULL) return NULL; if (pyString != Py_None) { pkg->depends[0] = read_dep_andor(PyString_AsString(pyString)); } else pkg->depends[0] = NULL; - pyString = PyList_GetItem(value, 6); + pyString = PyList_GetItem(value, 7); if (pyString == NULL) return NULL; if (pyString != Py_None) { pkg->depends[1] = read_dep_andor(PyString_AsString(pyString)); } else pkg->depends[1] = NULL; - pyString = PyList_GetItem(value, 7); + pyString = PyList_GetItem(value, 8); if (pyString == NULL) return NULL; if (pyString != Py_None) { pkg->conflicts = read_dep_and(PyString_AsString(pyString)); } else pkg->conflicts = NULL; - pyString = PyList_GetItem(value, 8); + pyString = PyList_GetItem(value, 9); if (pyString == NULL) return NULL; if (pyString != Py_None) { pkg->provides = read_packagenames(PyString_AsString(pyString)); @@ -204,12 +210,13 @@ static PyObject *build_system(PyObject *self, PyObject *args) { # SOURCE = 2 # SOURCEVER = 3 # ARCHITECTURE = 4 - # PREDEPENDS = 5 - # DEPENDS = 6 - # CONFLICTS = 7 - # PROVIDES = 8 - # RDEPENDS = 9 - # RCONFLICTS = 10 + # MULTIARCH = 5 + # PREDEPENDS = 6 + # DEPENDS = 7 + # CONFLICTS = 8 + # PROVIDES = 9 + # RDEPENDS = 10 + # RCONFLICTS = 11 */ dpkg_packages *dpkg_pkgs = new_packages(arch); @@ -244,23 +251,29 @@ static PyObject *build_system(PyObject *self, PyObject *args) { pyString = PyList_GetItem(value, 5); if (pyString == NULL) continue; + if (pyString != Py_None) { + pkg->multiarch = PyString_AsString(pyString); + } else pkg->multiarch = NULL; + + pyString = PyList_GetItem(value, 6); + if (pyString == NULL) continue; if (pyString != Py_None) { pkg->depends[0] = read_dep_andor(PyString_AsString(pyString)); } else pkg->depends[0] = NULL; - pyString = PyList_GetItem(value, 6); + pyString = PyList_GetItem(value, 7); if (pyString == NULL) continue; if (pyString != Py_None) { pkg->depends[1] = read_dep_andor(PyString_AsString(pyString)); } else pkg->depends[1] = NULL; - pyString = PyList_GetItem(value, 7); + pyString = PyList_GetItem(value, 8); if (pyString == NULL) continue; if (pyString != Py_None) { pkg->conflicts = read_dep_and(PyString_AsString(pyString)); } else pkg->conflicts = NULL; - pyString = PyList_GetItem(value, 8); + pyString = PyList_GetItem(value, 9); if (pyString == NULL) continue; if (pyString != Py_None) { pkg->provides = read_packagenames(PyString_AsString(pyString)); diff --git a/lib/dpkg.c b/lib/dpkg.c index fd6a374..79a707e 100644 --- a/lib/dpkg.c +++ b/lib/dpkg.c @@ -24,7 +24,8 @@ static collpackagelist *get_matching(dpkg_packages *pkgs, deplist *depopts, int static deplist *read_deplist(char **buf, char sep, char end); static dependency *read_dependency(char **buf, char *end); static void add_virtualpackage(virtualpkgtbl *vpkgs, char *package, - char *version, dpkg_collected_package *cpkg); + char *version, char *multiarch, + dpkg_collected_package *cpkg); static void remove_virtualpackage(virtualpkgtbl *vpkgs, char *pkgname, dpkg_collected_package *cpkg); static char *read_packagename(char **buf, char *end); @@ -177,9 +178,9 @@ void add_package(dpkg_packages *pkgs, dpkg_package *pkg) add_packagetbl(pkgs->packages, cpkg->pkg->package, cpkg); add_virtualpackage(pkgs->virtualpkgs, cpkg->pkg->package, - cpkg->pkg->version, cpkg); + cpkg->pkg->version, cpkg->pkg->multiarch, cpkg); for (v = cpkg->pkg->provides; v != NULL; v = v->next) { - add_virtualpackage(pkgs->virtualpkgs, v->value, NULL, cpkg); + add_virtualpackage(pkgs->virtualpkgs, v->value, NULL, NULL, cpkg); } } @@ -246,7 +247,8 @@ static void remove_virtualpackage(virtualpkgtbl *vpkgs, char *pkgname, } static void add_virtualpackage(virtualpkgtbl *vpkgs, char *package, - char *version, dpkg_collected_package *cpkg) + char *version, char *multiarch, + dpkg_collected_package *cpkg) { dpkg_provision value; virtualpkg *list, **addto; @@ -254,6 +256,7 @@ static void add_virtualpackage(virtualpkgtbl *vpkgs, char *package, value.pkg = cpkg; value.version = version; + value.multiarch = multiarch; list = lookup_virtualpkgtbl(vpkgs, package); shouldreplace = (list != NULL); @@ -398,11 +401,11 @@ deplistlist *read_dep_andor(char *buf) { static dependency *read_dependency(char **buf, char *end) { dependency *dep; char *name; - char newend[10]; + char newend[11]; DEBUG_ONLY( char *strend = *buf + strlen(*buf); ) assert(strlen(end) <= 8); - newend[0] = '('; strcpy(newend + 1, end); + newend[0] = '('; newend[1] = ':'; strcpy(newend + 2, end); name = my_strdup(read_until_char(buf, newend)); if (name == NULL) return NULL; @@ -411,6 +414,13 @@ static dependency *read_dependency(char **buf, char *end) { if (dep == NULL) die("read_dependency alloc 1:"); dep->package = name; + + if (**buf == ':') { + (*buf)++; + dep->archqual = my_strdup(read_until_char(buf, newend)); + if (dep->archqual == NULL) return NULL; + } else + dep->archqual = NULL; while(isspace(**buf)) (*buf)++; @@ -465,7 +475,7 @@ static dependency *read_dependency(char **buf, char *end) { } while (isspace(**buf)) (*buf)++; - newend[0] = ')'; + newend[0] = ')'; strcpy(newend + 1, end); dep->version = my_strdup(read_until_char(buf, newend)); while (isspace(**buf)) (*buf)++; @@ -509,6 +519,14 @@ static collpackagelist **get_matching_low(collpackagelist **addto, } } + if (dep->archqual != NULL) { + if (strcmp(dep->archqual, "any") == 0) { + if (strcmp(vpkg->value.multiarch, "allowed") != 0) + add = 0; + } else + add = 0; + } + if (add) { insert_l_collpackagelist(addto, vpkg->value.pkg, line); addto = &(*addto)->next; diff --git a/lib/dpkg.h b/lib/dpkg.h index cff4781..c8a50ed 100644 --- a/lib/dpkg.h +++ b/lib/dpkg.h @@ -33,6 +33,7 @@ extern char *dependency_relation_sym[]; typedef struct dependency dependency; struct dependency { char *package; + char *archqual; dependency_relation op; char *version; }; @@ -48,6 +49,7 @@ typedef struct dpkg_package dpkg_package; struct dpkg_package { char *package; char *version; + char *multiarch; char *source; char *source_ver; @@ -102,6 +104,7 @@ LIST(collpackagelist, dpkg_collected_package *); typedef struct dpkg_provision dpkg_provision; struct dpkg_provision { char *version; + char *multiarch; dpkg_collected_package *pkg; }; From a8812981037d6f0714a6106b662161fa3ac29661 Mon Sep 17 00:00:00 2001 From: "Adam D. Barratt" Date: Wed, 18 Sep 2013 10:00:04 +0000 Subject: [PATCH 12/14] Remove the C library placeholder for "pre-depends" We stopped populating the element with real data some time ago, it's time to drop it entirely. Signed-off-by: Adam D. Barratt --- britney.py | 1 - consts.py | 13 +++++-------- lib/britney-py.c | 29 +++++++++-------------------- 3 files changed, 14 insertions(+), 29 deletions(-) diff --git a/britney.py b/britney.py index 037645f..d2bcbd6 100755 --- a/britney.py +++ b/britney.py @@ -525,7 +525,6 @@ class Britney(object): version, get_field('Architecture'), get_field('Multi-Arch'), - None, # Pre-depends - leave as None for the C-code deps, ', '.join(final_conflicts_list) or None, get_field('Provides'), diff --git a/consts.py b/consts.py index eba22d2..827e7d4 100644 --- a/consts.py +++ b/consts.py @@ -30,11 +30,8 @@ SOURCE = 2 SOURCEVER = 3 ARCHITECTURE = 4 MULTIARCH = 5 -# PREDEPENDS = 6 - No longer used by the python code -# - The C-code needs it for alignment reasons and still check it -# but ignore it if it is None (so keep it None). -DEPENDS = 7 -CONFLICTS = 8 -PROVIDES = 9 -RDEPENDS = 10 -RCONFLICTS = 11 +DEPENDS = 6 +CONFLICTS = 7 +PROVIDES = 8 +RDEPENDS = 9 +RCONFLICTS = 10 diff --git a/lib/britney-py.c b/lib/britney-py.c index 28ace3c..94833cf 100644 --- a/lib/britney-py.c +++ b/lib/britney-py.c @@ -85,6 +85,7 @@ static PyObject *dpkgpackages_add_binary(dpkgpackages *self, PyObject *args) { pkg->package = strdup(pkg_name); pkg->priority = 0; pkg->details = NULL; + pkg->depends[1] = NULL; pkg->depends[2] = NULL; pkg->depends[3] = NULL; @@ -118,17 +119,11 @@ static PyObject *dpkgpackages_add_binary(dpkgpackages *self, PyObject *args) { pyString = PyList_GetItem(value, 7); if (pyString == NULL) return NULL; - if (pyString != Py_None) { - pkg->depends[1] = read_dep_andor(PyString_AsString(pyString)); - } else pkg->depends[1] = NULL; - - pyString = PyList_GetItem(value, 8); - if (pyString == NULL) return NULL; if (pyString != Py_None) { pkg->conflicts = read_dep_and(PyString_AsString(pyString)); } else pkg->conflicts = NULL; - pyString = PyList_GetItem(value, 9); + pyString = PyList_GetItem(value, 8); if (pyString == NULL) return NULL; if (pyString != Py_None) { pkg->provides = read_packagenames(PyString_AsString(pyString)); @@ -211,12 +206,11 @@ static PyObject *build_system(PyObject *self, PyObject *args) { # SOURCEVER = 3 # ARCHITECTURE = 4 # MULTIARCH = 5 - # PREDEPENDS = 6 - # DEPENDS = 7 - # CONFLICTS = 8 - # PROVIDES = 9 - # RDEPENDS = 10 - # RCONFLICTS = 11 + # DEPENDS = 6 + # CONFLICTS = 7 + # PROVIDES = 8 + # RDEPENDS = 9 + # RCONFLICTS = 10 */ dpkg_packages *dpkg_pkgs = new_packages(arch); @@ -230,6 +224,7 @@ static PyObject *build_system(PyObject *self, PyObject *args) { pkg->package = strdup(PyString_AsString(key)); pkg->priority = 0; pkg->details = NULL; + pkg->depends[1] = NULL; pkg->depends[2] = NULL; pkg->depends[3] = NULL; @@ -263,17 +258,11 @@ static PyObject *build_system(PyObject *self, PyObject *args) { pyString = PyList_GetItem(value, 7); if (pyString == NULL) continue; - if (pyString != Py_None) { - pkg->depends[1] = read_dep_andor(PyString_AsString(pyString)); - } else pkg->depends[1] = NULL; - - pyString = PyList_GetItem(value, 8); - if (pyString == NULL) continue; if (pyString != Py_None) { pkg->conflicts = read_dep_and(PyString_AsString(pyString)); } else pkg->conflicts = NULL; - pyString = PyList_GetItem(value, 9); + pyString = PyList_GetItem(value, 8); if (pyString == NULL) continue; if (pyString != Py_None) { pkg->provides = read_packagenames(PyString_AsString(pyString)); From e643daad289411debb04f9aab8d474d6d320080d Mon Sep 17 00:00:00 2001 From: "Adam D. Barratt" Date: Wed, 18 Sep 2013 20:40:00 +0000 Subject: [PATCH 13/14] Apply various typo and clarity fixes Signed-off-by: Adam D. Barratt --- britney.py | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/britney.py b/britney.py index d2bcbd6..efa68b3 100755 --- a/britney.py +++ b/britney.py @@ -24,7 +24,7 @@ This is the Debian testing updater script, also known as "Britney". Packages are usually installed into the `testing' distribution after they have undergone some degree of testing in unstable. The goal of this software is to do this task in a smart way, allowing testing -to be always fully installable and close to being a release candidate. +to always be fully installable and close to being a release candidate. Britney's source code is split between two different but related tasks: the first one is the generation of the update excuses, while the @@ -95,9 +95,9 @@ does for the generation of the update excuses. is ignored: it will be removed and not updated. 2. For every binary package built from the new source, it checks - for unsatisfied dependencies, new binary package and updated - binary package (binNMU) excluding the architecture-independent - ones and the packages not built from the same source. + for unsatisfied dependencies, new binary packages and updated + binary packages (binNMU), excluding the architecture-independent + ones, and packages not built from the same source. 3. For every binary package built from the old source, it checks if it is still built from the new source; if this is not true @@ -146,7 +146,7 @@ does for the generation of the update excuses. If this is not true, then these are called `out-of-date' architectures and the package is ignored. - 9. The source package must have at least a binary package, otherwise + 9. The source package must have at least one binary package, otherwise it is ignored. 10. If the suite is unstable, the new source package must have no @@ -397,7 +397,7 @@ class Britney(object): output. The type parameter controls the urgency of the message, and can be equal to `I' for `Information', `W' for `Warning' and `E' for `Error'. Warnings and errors are always printed, and information is - printed only if the verbose logging is enabled. + printed only if verbose logging is enabled. """ if self.options.verbose or type in ("E", "W"): print "%s: [%s] - %s" % (type, time.asctime(), msg) @@ -463,7 +463,7 @@ class Britney(object): within the directory specified as `basedir' parameter, replacing ${arch} with the value of the arch parameter. Considering the large amount of memory needed, not all the fields are loaded - in memory. The available fields are Version, Source, Pre-Depends, + in memory. The available fields are Version, Source, Multi-Arch, Depends, Conflicts, Provides and Architecture. After reading the packages, reverse dependencies are computed @@ -652,7 +652,7 @@ class Britney(object): - The dates are expressed as days starting from the 1970-01-01. + The dates are expressed as the number of days from 1970-01-01. The method returns a dictionary where the key is the binary package name and the value is a tuple with two items, the version and the date. @@ -890,7 +890,7 @@ class Britney(object): package = binaries[0][name] # check the versioned dependency and architecture qualifier # (if present) - if op == '' and version == '' or apt_pkg.check_dep(package[VERSION], op, version): + if (op == '' and version == '') or apt_pkg.check_dep(package[VERSION], op, version): if archqual is None or (archqual == 'any' and package[MULTIARCH] == 'allowed'): packages.append(name) @@ -898,10 +898,10 @@ class Britney(object): for prov in binaries[1].get(name, []): if prov not in binaries[0]: continue package = binaries[0][prov] - # A provides only satisfies an unversioned dependency - # (per Policy Manual §7.5) - # A provides only satisfies a dependency without an - # architecture qualifier (per analysis of apt code) + # A provides only satisfies: + # - an unversioned dependency (per Policy Manual §7.5) + # - a dependency without an architecture qualifier + # (per analysis of apt code) if op == '' and version == '' and archqual is None: packages.append(prov) @@ -919,7 +919,7 @@ class Britney(object): # retrieve the binary package from the specified suite and arch binary_u = self.binaries[suite][arch][0][pkg] - # local copies for better performances + # local copies for better performance parse_depends = apt_pkg.parse_depends get_dependency_solvers = self.get_dependency_solvers @@ -928,7 +928,7 @@ class Britney(object): return deps = binary_u[DEPENDS] - # for every block of dependency (which is formed as conjunction of disconjunction) + # for every dependency block (formed as conjunction of disjunction) for block, block_txt in zip(parse_depends(deps, False), deps.split(',')): # if the block is satisfied in testing, then skip the block solved, packages = get_dependency_solvers(block, arch, 'testing') @@ -1118,7 +1118,7 @@ class Britney(object): # as otherwise the updated source will already cause the binary packages # to be updated if ssrc: - # Special-case, if the binary is a candidate for smooth update, we do not consider + # Special-case, if the binary is a candidate for a smooth update, we do not consider # it "interesting" on its own. This case happens quite often with smooth updatable # packages, where the old binary "survives" a full run because it still has # reverse dependencies. @@ -1356,7 +1356,7 @@ class Britney(object): # if the suite is unstable, then we have to check the release-critical bug lists before # updating testing; if the unstable package has RC bugs that do not apply to the testing - # one, the check fails and we set update_candidate to False to block the update + # one, the check fails and we set update_candidate to False to block the update if suite == 'unstable': for pkg in pkgs: bugs_t = [] From 8bbdf65d07db840924cef33e8959035b8df7a3f5 Mon Sep 17 00:00:00 2001 From: "Adam D. Barratt" Date: Tue, 24 Sep 2013 04:56:27 +0000 Subject: [PATCH 14/14] lib/dpkg.c: don't try to dereference a NULL pointer Signed-off-by: Adam D. Barratt --- lib/dpkg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/dpkg.c b/lib/dpkg.c index 79a707e..88a3ca5 100644 --- a/lib/dpkg.c +++ b/lib/dpkg.c @@ -521,7 +521,7 @@ static collpackagelist **get_matching_low(collpackagelist **addto, if (dep->archqual != NULL) { if (strcmp(dep->archqual, "any") == 0) { - if (strcmp(vpkg->value.multiarch, "allowed") != 0) + if (vpkg->value.multiarch == NULL || strcmp(vpkg->value.multiarch, "allowed") != 0) add = 0; } else add = 0;