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; };