diff --git a/britney.conf b/britney.conf index 158ecf4..2d8d4a8 100644 --- a/britney.conf +++ b/britney.conf @@ -19,13 +19,13 @@ ARCHITECTURES = amd64 arm64 armhf i386 powerpc ppc64el NOBREAKALL_ARCHES = amd64 # if you're in this list, your packages may not stay in sync with the source -OUTOFSYNC_ARCHES = +OUTOFSYNC_ARCHES = # if you're in this list, your uninstallability count may increase -BREAK_ARCHES = +BREAK_ARCHES = # if you're in this list, you are a new architecture -NEW_ARCHES = +NEW_ARCHES = # priorities and delays MINDAYS_LOW = 0 diff --git a/britney.py b/britney.py index fed9e1d..243298f 100755 --- a/britney.py +++ b/britney.py @@ -953,6 +953,11 @@ class Britney(object): l = line.split() if l[0] == 'finished': break + if l[0] == 'remark': + # Ignore "no-op" hint, which sole purpose is to be + # found by hint grep (and show up in "d"'s + # output). + continue elif l[0] not in self.HINTS[who]: continue elif len(l) == 1: @@ -1165,8 +1170,8 @@ class Britney(object): # if the package is blocked, skip it for hint in self.hints.search('block', package=pkg, removal=True): - excuse.addhtml("Not touching package, as requested by %s (contact #ubuntu-release " - "if update is needed)" % hint.user) + excuse.addhtml("Not touching package, as requested by %s " + "(contact #ubuntu-release if update is needed)" % hint.user) excuse.addhtml("Not considered") excuse.addreason("block") self.excuses.append(excuse) @@ -1427,7 +1432,8 @@ class Britney(object): excuse.addhtml("%s request by %s ignored due to version mismatch: %s" % (unblock_cmd.capitalize(), unblocks[0].user, unblocks[0].version)) if suite == 'unstable' or block_cmd == 'block-udeb': - excuse.addhtml("Not touching package due to %s request by %s (contact #ubuntu-release if update is needed)" % + excuse.addhtml("Not touching package due to %s request by %s " + "(contact #ubuntu-release if update is needed)" % (block_cmd, blocked[block_cmd].user)) excuse.addreason("block") else: @@ -1507,6 +1513,8 @@ class Britney(object): run_autopkgtest = False excuse.addreason("arch") excuse.addreason("arch-%s" % arch) + excuse.addreason("build-arch") + excuse.addreason("build-arch-%s" % arch) excuse.addhtml(text) @@ -1516,6 +1524,7 @@ class Britney(object): built_anywhere = False for arch in self.options.architectures: oodbins = {} + uptodatebins = False # 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)): if pkg not in pkgs: pkgs[pkg] = [] @@ -1526,12 +1535,16 @@ class Britney(object): pkgsv = binary_u[SOURCEVER] # if it wasn't built by the same source, it is out-of-date + # it there is at least one binary which is up-to-date, there + # is a build on this arch if not same_source(source_u[VERSION], pkgsv): if pkgsv not in oodbins: oodbins[pkgsv] = [] oodbins[pkgsv].append(pkg) continue - built_anywhere = True + else: + uptodatebins = True + built_anywhere = True # if the package is architecture-dependent or the current arch is `nobreakall' # find unsatisfied dependencies for the binary package @@ -1548,21 +1561,17 @@ class Britney(object): oodtxt = "" for v in oodbins.keys(): if oodtxt: oodtxt = oodtxt + "; " - maybe_nbs = "" - if not source_t or same_source(source_t[VERSION], v): - maxver = None - for pkg in sorted(x.split("/")[0] for x in source_u[BINARIES] if x.endswith("/"+arch)): - pkgv = self.binaries[suite][arch][0][pkg][VERSION] - if maxver is None or apt_pkg.version_compare(pkgv, maxver) > 0: - maxver = pkgv - if maxver is not None and apt_pkg.version_compare(maxver, v) > 0: - maybe_nbs = "; NBS?" oodtxt = oodtxt + "%s (from %s%s)" % \ (", ".join(sorted(oodbins[v])), self.options.distribution, urllib.quote(src.split("/")[0]), urllib.quote(v), v, maybe_nbs) - text = "out of date on %s: %s" % \ - (self.options.distribution, urllib.quote(src.split("/")[0]), urllib.quote(source_u[VERSION]), arch, oodtxt) + if uptodatebins: + text = "old binaries left on %s: %s" % \ + (self.options.distribution, urllib.quote(src.split("/")[0]), urllib.quote(source_u[VERSION]), arch, oodtxt) + else: + text = "missing build on %s: %s" % \ + (self.options.distribution, urllib.quote(src.split("/")[0]), urllib.quote(source_u[VERSION]), arch, oodtxt) if arch in self.options.outofsync_arches.split(): text = text + " (but %s isn't keeping up, so nevermind)" % (arch) @@ -1572,6 +1581,12 @@ class Britney(object): run_autopkgtest = False excuse.addreason("arch") excuse.addreason("arch-%s" % arch) + if uptodatebins: + excuse.addreason("cruft-arch") + excuse.addreason("cruft-arch-%s" % arch) + else: + excuse.addreason("build-arch") + excuse.addreason("build-arch-%s" % arch) excuse.addhtml(text) @@ -2149,7 +2164,17 @@ class Britney(object): for p in ( bin for bin in bins if bin not in smoothbins ): binary, parch = p.split("/") version = binaries_t[parch][0][binary][VERSION] - rms.add((binary, version, parch)) + # if this is a binary migration from *pu, only the arch:any + # packages will be present. ideally dak would also populate + # the arch-indep packages, but as that's not the case we + # must keep them around; they will not be re-added by the + # migration so will end up missing from testing + if migration_architecture != 'source' and \ + suite != 'unstable' and \ + binaries_t[parch][0][binary][ARCHITECTURE] == 'all': + continue + else: + rms.add((binary, version, parch)) # single binary removal; used for clearing up after smooth # updates but not supported as a manual hint @@ -2170,7 +2195,7 @@ class Britney(object): return (adds, rms, set(smoothbins.itervalues())) - def doop_source(self, item, hint_undo=[], removals=frozenset()): + def doop_source(self, item, hint_undo=None, removals=frozenset()): """Apply a change to the testing distribution as requested by `pkg` An optional list of undo actions related to packages processed earlier @@ -2303,7 +2328,7 @@ class Britney(object): affected.update(get_reverse_tree(j, parch)) old_version = old_pkg_data[VERSION] inst_tester.remove_testing_binary(binary, old_version, parch) - else: + elif hint_undo: # the binary isn't in testing, but it may have been at # the start of the current hint and have been removed # by an earlier migration. if that's the case then we @@ -2400,10 +2425,9 @@ class Britney(object): removals = set() all_affected = set() nobreakall_arches = self.options.nobreakall_arches.split() - binaries_t = self.binaries['testing'] - check_packages = partial(self._check_packages, binaries_t) - # Deep copy nuninst (in case the hint is undone) - nuninst = {k:v.copy() for k,v in self.nuninst_orig.iteritems()} + packages_t = self.binaries['testing'] + check_packages = partial(self._check_packages, packages_t) + nuninst = {} for item in hinted_packages: @@ -2420,6 +2444,17 @@ class Britney(object): if lundo is not None: lundo.append((undo,item)) + # deep copy nuninst (in case the hint is undone) + # NB: We do this *after* updating testing and we have to filter out + # removed binaries. Otherwise, uninstallable binaries that were + # removed by the hint would still be counted. + for arch in self.options.architectures: + nuninst_arch = self.nuninst_orig[arch] + nuninst_arch_all = self.nuninst_orig[arch + '+all'] + binaries_t_a = packages_t[arch][0] + nuninst[arch] = set(x for x in nuninst_arch if x in binaries_t_a) + nuninst[arch + '+all'] = set(x for x in nuninst_arch_all if x in binaries_t_a) + for arch in self.options.architectures: if arch not in nobreakall_arches: skip_archall = True @@ -2460,9 +2495,6 @@ class Britney(object): dependencies = self.dependencies check_packages = partial(self._check_packages, binaries) - if lundo is None: - lundo = [] - 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) @@ -2516,7 +2548,8 @@ class Britney(object): # check if the action improved the uninstallability counters if better: - lundo.append((undo, item)) + if lundo is not None: + lundo.append((undo, item)) selected.append(item) packages.extend(extra) extra = [] @@ -2573,7 +2606,7 @@ class Britney(object): lundo = None nuninst_end = None better = True - extra = () # empty tuple + extra = [] if hinttype == "easy" or hinttype == "force-hint": force = hinttype == "force-hint" @@ -2621,7 +2654,12 @@ class Britney(object): newly_uninst(nuninst_start, nuninst_end))) if not force: - break_arches = self.options.break_arches.split() + break_arches = set(self.options.break_arches.split()) + if all(x.architecture in break_arches for x in selected): + # If we only migrated items from break-arches, then we + # do not allow any regressions on these architectures. + # This usually only happens with hints + break_arches = set() better = is_nuninst_asgood_generous(self.options.architectures, self.nuninst_orig, nuninst_end, @@ -2647,10 +2685,10 @@ class Britney(object): self.all_selected += selected if not actions: if recurse: - self.upgrade_me = sorted(extra) + self.upgrade_me = extra + self.sort_actions() else: self.upgrade_me = [x for x in self.upgrade_me if x not in set(selected)] - self.sort_actions() else: self.output_write("FAILED\n") if not lundo: return diff --git a/britney_nobreakall.conf b/britney_nobreakall.conf index 861cbde..eb76959 100644 --- a/britney_nobreakall.conf +++ b/britney_nobreakall.conf @@ -8,9 +8,9 @@ PARTIAL_UNSTABLE = yes # Output NONINST_STATUS = data/%(SERIES)/non-installable-status EXCUSES_OUTPUT = output/%(SERIES)/excuses.html +EXCUSES_YAML_OUTPUT = output/%(SERIES)/excuses.yaml UPGRADE_OUTPUT = output/%(SERIES)/output.txt HEIDI_OUTPUT = output/%(SERIES)/HeidiResult -DELTA_OUTPUT = output/%(SERIES)/Delta # List of release architectures ARCHITECTURES = amd64 arm64 armhf i386 powerpc ppc64el @@ -19,13 +19,13 @@ ARCHITECTURES = amd64 arm64 armhf i386 powerpc ppc64el NOBREAKALL_ARCHES = amd64 arm64 armhf i386 powerpc ppc64el # if you're in this list, your packages may not stay in sync with the source -OUTOFSYNC_ARCHES = +OUTOFSYNC_ARCHES = # if you're in this list, your uninstallability count may increase BREAK_ARCHES = # if you're in this list, you are a new architecture -NEW_ARCHES = +NEW_ARCHES = # priorities and delays MINDAYS_LOW = 0 @@ -33,7 +33,7 @@ MINDAYS_MEDIUM = 0 MINDAYS_HIGH = 0 MINDAYS_CRITICAL = 0 MINDAYS_EMERGENCY = 0 -DEFAULT_URGENCY = low +DEFAULT_URGENCY = medium # hint permissions HINTS_CJWATSON = ALL @@ -55,8 +55,10 @@ HINTS_UBUNTU-TOUCH/OGRA = block unblock # support for old libraries in testing (smooth update) # use ALL to enable smooth updates for all the sections -# SMOOTH_UPDATES = libs oldlibs -SMOOTH_UPDATES = +# +# naming a non-existent section will effectively disable new smooth +# updates but still allow removals to occur +SMOOTH_UPDATES = badgers REMOVE_OBSOLETE = no