(CCing debian-python in case anyone is wondering what those spurious entries for Python packages in update_excuses.html are about.)
Multiarch adds a Depends: foo:any syntax, permitted only if the target of the dependency is "Multi-Arch: allowed" [1]. This has been supported by dpkg and apt for some time and is now safe to use in unstable. However, britney does not yet understand it. dh-python recently started using this syntax [2], and as a result we're seeing lots of this kind of thing in excuses: i18nspector/i386 unsatisfiable Depends: python3:any (>= 3.2.3-3~) I've fixed this for Ubuntu's britney instance with the following patch. I'm afraid I haven't had a chance to rebase it on top of Debian or to test it there, but that should hopefully not be very much work, and certainly easier than recreating all this from scratch ... [1] https://wiki.ubuntu.com/MultiarchSpec#Extended_semantics_of_per-architecture_package_relationships [2] http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=722045 === modified file 'britney.py' --- britney.py 2013-09-09 11:37:52 +0000 +++ britney.py 2013-09-16 13:25:37 +0000 @@ -230,14 +230,15 @@ 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 class Britney(object): @@ -546,6 +547,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, @@ -1042,7 +1044,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: @@ -1138,12 +1140,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, []): @@ -1151,7 +1160,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) === modified file 'lib/britney-py.c' --- lib/britney-py.c 2012-10-22 12:43:51 +0000 +++ lib/britney-py.c 2013-09-16 12:28:15 +0000 @@ -107,22 +107,28 @@ static PyObject *dpkgpackages_add_binary 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 * # 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); @@ -245,22 +252,28 @@ static PyObject *build_system(PyObject * 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)); === modified file 'lib/dpkg.c' --- lib/dpkg.c 2012-03-05 12:13:21 +0000 +++ lib/dpkg.c 2013-09-16 12:22:59 +0000 @@ -24,7 +24,8 @@ static collpackagelist *get_matching(dpk 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, dp 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(virtua } 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(virtualpk 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 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 } 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_lo } } + 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; === modified file 'lib/dpkg.h' --- lib/dpkg.h 2011-12-27 10:39:57 +0000 +++ lib/dpkg.h 2013-09-16 10:25:34 +0000 @@ -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_pac typedef struct dpkg_provision dpkg_provision; struct dpkg_provision { char *version; + char *multiarch; dpkg_collected_package *pkg; }; === modified file 'lib/example.py' --- lib/example.py 2006-08-20 19:25:21 +0000 +++ lib/example.py 2013-09-09 11:37:56 +0000 @@ -8,20 +8,21 @@ import britney # 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 -packages = {'phpldapadmin': ['1.0', 'web', 'phpldapadmin', '1.0', 'all', '', 'apache2 (>= 2.0)', '', '', [], []], - 'apache2': ['2.0', 'web', 'apache2', '2.0', 'i386', '', '', 'phpldapadmin (<= 1.0~)', '', [], []], +packages = {'phpldapadmin': ['1.0', 'web', 'phpldapadmin', '1.0', 'all', None, '', 'apache2 (>= 2.0)', '', '', [], []], + 'apache2': ['2.0', 'web', 'apache2', '2.0', 'i386', None, '', '', 'phpldapadmin (<= 1.0~)', '', [], []], } system = britney.buildSystem('i386', packages) print system.is_installable('phpldapadmin'), system.packages system.remove_binary('apache2') print system.is_installable('phpldapadmin'), system.packages -system.add_binary('apache2', ['2.0', 'web', 'apache2', '2.0', 'i386', '', '', 'phpldapadmin (<= 1.0~)', '', [], []]) +system.add_binary('apache2', ['2.0', 'web', 'apache2', '2.0', 'i386', None, '', '', 'phpldapadmin (<= 1.0~)', '', [], []]) print system.is_installable('phpldapadmin'), system.packages Thanks, -- Colin Watson [cjwat...@ubuntu.com] -- To UNSUBSCRIBE, email to debian-python-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org Archive: http://lists.debian.org/20130916140255.gf32...@riva.ucam.org