Package: anna Version: 1.52 Severity: wishlist Tags: patch Control: block 345408 by -1
Hi, If we had multiple udeb sources (Bug#345419), it could mean that anna reads a Packages file having multiple versions for some udebs. It's very easy to make net-retriever generate such a file, combining multiple suites, e.g. stable + stable-proposed-updates; or maybe stable + stable-backports. Currently anna can't handle this - it tries to download and install those udebs multiple times. My patch allows anna to disregard duplicates and keep only the last-listed entry for each package. It seems to work great. In the usual situation (only one udeb source) it should make no modification. An earlier version of this patch did try to compare versions and pick the latest one, but libdebian-installer's parsing seems broken so didn't work. (I think it parses hello/1 and hello/2 but returns a linked list having hello/2 and hello/2. So it is necessary anyway for the Packages file to be ordered with preferred versions last, for now). Also not working yet, freeing memory for the orphaned package and node data structures. I think my code was right, but freeing either one triggers an immediate segfault. I went to some lengths to get core dumps and debug symbols, but couldn't get a readable backtrace. I'm just nulling the pointers for now. Would this be suitable for sid as-is or is further work needed? Thanks! -- System Information: Debian Release: 7.8 APT prefers stable-kfreebsd APT policy: (500, 'stable-kfreebsd'), (500, 'oldstable-proposed-updates'), (500, 'oldstable') Architecture: kfreebsd-amd64 (x86_64) Kernel: kFreeBSD 9.0-2-amd64-xenhvm-ipsec Locale: LANG=en_GB.UTF-8, LC_CTYPE=en_GB.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash
diff --git a/anna.c b/anna.c index 4b68816..1dd4461 100644 --- a/anna.c +++ b/anna.c @@ -8,6 +8,49 @@ static char *running_kernel = NULL; static const char *subarchitecture; static int quiet = 0, verbose = 0; +/* If any package name appears more than once in the Packages file, + * keep only the last one. */ +void remove_duplicates (di_packages *packages) { + di_slist_node *n1, *n2, *n2_prev; + di_package *p1, *p2; + + for (n1 = packages->list.head; n1; n1 = n1->next) { + n2_prev = n1; + /* compare n1 to each node after it, as n2 */ + for (n2 = n1->next; n2; n2 = n2->next) { + /* compare package name */ + p1 = n1->data; + p2 = n2->data; + if (strcmp(p1->package, p2->package) != 0) { + /* keep this node; remember the previous one */ + n2_prev = n2; + continue; + } + + di_log (DI_LOG_LEVEL_DEBUG, + "ignoring duplicate Packages entry for %s", + p1->package); + + /* delete p1, move p2 into n1 */ +/* XXX: di_package_destroy(p1); */ + n1->data = p1 = p2; + n2->data = p2 = NULL; + + /* update list bottom, if n2 was the last entry */ + if (packages->list.bottom == n2) { + packages->list.bottom = n2_prev; + } + + /* unlink n2 from the list and delete it */ + n2_prev->next = n2->next; +/* XXX: di_free(n2); */ + + /* rewind to the previous node */ + n2 = n2_prev; + } + } +} + di_packages *get_packages (void) { di_packages_allocator *packages_allocator = di_system_packages_allocator_alloc(); di_packages *packages = retriever_packages(packages_allocator); @@ -26,6 +69,7 @@ di_packages *get_packages (void) { } } + remove_duplicates(packages); return packages; }