apt/apt-0.5.5cnc4.1-alt-PrioComp.patch
Alex V. Myltsev 94df084ec5 Better pkgname comparison: now automake_1.10 > automake_1.9.
Before this patch, strcmp(3) would be used to select
the best package. This was sometimes counter-intuitive
(for example, APT would choose autoconf_2.5 over
autoconf_2.13).

[NB: fixing this can break some packages that rely
on the historic sort order; e.g. postgresql74
may be preferred to postgresql8.2.]

We considered using rpmvercmp() for package name
comparison, but chose to write a specially-crafted
function that's mostly compatible with strcmp(3),
except for numeric fragments in the names.

As a matter of fact, strtoull usage is suboptimal here.
It may overflow the returned long long, leading to an
incorrect comparison. Fixing the code to avoid strtoull
is, however, left as an exercise to the diligent
maintenance programmer (and you are insane anyway
if you need package names that trigger the overflow).
2007-12-17 17:58:41 +03:00

44 lines
1.4 KiB
Diff

diff --git a/apt/apt-pkg/algorithms.cc b/apt/apt-pkg/algorithms.cc
index e8abff2..a5bf5ca 100644
--- a/apt/apt-pkg/algorithms.cc
+++ b/apt/apt-pkg/algorithms.cc
@@ -1402,6 +1402,27 @@ bool pkgProblemResolver::RemoveDepends()
return true;
}
/*}}}*/
+/* Like strcmp, but compares digit sections by number value.
+ * E.g.: tar-1.10 > tar-1.9 > tar-1.1a
+ * (while strcmp gives tar-1.10 < tar-1.9). */
+static int nameCompare(const char* n1, const char* n2)
+{
+ while(*n1 && *n2) {
+ if(isdigit(*n1) && isdigit(*n2)) {
+ unsigned long long i1, i2;
+ i1 = strtoull(n1, const_cast<char **>(&n1), 10);
+ i2 = strtoull(n2, const_cast<char **>(&n2), 10);
+ if(i1 != i2)
+ return (i1 > i2) ? 1 : -1;
+ } else if(*n1 != *n2) {
+ return (*n1 > *n2) ? 1 : -1;
+ } else {
+ n1++;
+ n2++;
+ }
+ }
+ return 0;
+}
// PrioSortList - Sort a list of versions by priority /*{{{*/
// ---------------------------------------------------------------------
@@ -1423,7 +1444,9 @@ static int PrioComp(const void *A,const void *B)
if (L->Priority != R->Priority)
return L->Priority - R->Priority;
- return strcmp(L.ParentPkg().Name(),R.ParentPkg().Name());
+ // PrioComp("gcc2","gcc3") == 1
+ // PrioComp("gcc2", gcc10") == 1
+ return nameCompare(R.ParentPkg().Name(),L.ParentPkg().Name());
}
void pkgPrioSortList(pkgCache &Cache,pkgCache::Version **List)
{