britney.py: Fix crash with arch:all packages being shadowed

There was an implicit assumption in Britney that was violated recently
(presumbly in 12d9ae8).  This assumption is that a source package will
reference the *latest* version of an arch:all package; even if that
version is not built by that source (version).

Image the following packages:

  * p-all/1 and p-all/2 are arch:all packages.
    - p-all/1 is generally superseded by p-all/2 except it has not
      been removed yet (regardless of why that happens).
  * src-a/2 builds p-all/2.

When Britney loads the packages (assuming packages are sorted[1]):

 * p-all/1 is read and associated with src-a/2 (despite not being
   built from that source)
 * p-all/2 is read afterwards.  It would replace p-all/1 and be
   assoicated with src-a/2 as well.
   - Prior to 12d9ae8, the assoication would be "pkg, arch" and
     therefore the same.
   - In 12d9ae8a and after, the association would include version
     and both would be associated at the same time.
 * Since p-all/1 is discarded, it is never added to the
   installability tester (nor the solver).  It then promptly throws
   an exception when asked to deal with a package it believe does
   not exist.
   - This can trivially be solved by removing the association
     between p-all/1 and src-a/2 when p-all/2 is read.

So far so good.  Unfortunately, this adds another another problem!

When Britney migrates a binNMU, she currently removes *all* binary
packages on that architecture - *including* the arch:all packages.
This works out in the end because the arch:all packages be re-added
since they associated with the source package.

  At first glance, this appears to be a non-issue until you add
hijacking to the mix.  This is *exactly* the case behind #709460.
However, now we end up in a situation where the arch:all package is
removed during binNMU and not re-added (because the arch:all package
is not associated with *that* source any more).

This commit fixes all of the above by:

 1) Correctly disassociating superseded arch:all packages from their
    source packages
 2) Falsely associating the "new" arch:all package to the source that
    provided the superseded arch:all package (to avoid issues with
    binNMUs and hijacked packages).
    - This should probably be undone at some point when Britney does
      not need this "hack" any more.

This fix is currently relying on the packages being sorted.  But so
did the fix for #709460 (see [1] again).  It might be prudent to fix
that as well (or at least reject the packages file rather than produce
"random" results).

[1] Which is another assumption we have been relying and that is
currently satisfied.

Signed-off-by: Niels Thykier <niels@thykier.net>
master
Niels Thykier 8 years ago
parent 8ab7fc0e89
commit 4ced8a3d41

@ -629,12 +629,26 @@ class Britney(object):
# (in unstable) if some architectures have out-of-date
# binaries. We only ever consider the package with the
# largest version for migration.
if pkg in packages and apt_pkg.version_compare(packages[pkg][0], version) > 0:
continue
pkg = intern(pkg)
version = intern(version)
pkg_id = (pkg, version, arch)
if pkg in packages:
old_pkg_data = packages[pkg]
if apt_pkg.version_compare(old_pkg_data[VERSION], version) > 0:
continue
old_pkg_id = (pkg, old_pkg_data[VERSION], arch)
old_src_binaries = srcdist[old_pkg_data[SOURCE]][BINARIES]
old_src_binaries.remove(old_pkg_id)
# This may seem weird at first glance, but the current code rely
# on this behaviour to avoid issues like #709460. Admittedly it
# is a special case, but Britney will attempt to remove the
# arch:all packages without this. Even then, this particular
# stop-gap relies on the packages files being sorted by name
# and the version, so it is not particularly resilient.
if pkg_id not in old_src_binaries:
old_src_binaries.append(pkg_id)
# Merge Pre-Depends with Depends and Conflicts with
# Breaks. Britney is not interested in the "finer
# semantic differences" of these fields anyway.

Loading…
Cancel
Save