[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#801161: anna: handle multiple udeb versions in Packages file



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

Reply to: