[Rpm-maint] [Suse patch] Checking for identical packages on install/upgrade

Panu Matilainen pmatilai at redhat.com
Fri Jun 1 10:08:28 UTC 2007


On Tue, 29 May 2007, Michael Schroeder wrote:

> On Tue, May 29, 2007 at 10:29:45AM +0300, Panu Matilainen wrote:
>> What JBJ does here is checks HDRID for identifying identical packages if
>> present, version comparison if not. But I don't think it's actually
>> identicality of headers (or not) we're really interested in here but
>> upgradability. It's trivial to produce packages with different HDRID
>> but same NEVRA (just rebuild the package and there you have it), I don't
>> think it makes much sense to allow to packages with same NEVRA in the
>> transaction, ever.
>>
>> I'd rather just use rpmdsCompare() for the check rather than add yet
>> another codepath for NEVRA comparison within rpm like the included patch
>> does. Optionally we could check for the HDRID as well (identical packages
>> are never wanted in ts) but dunno if it's worth the couple of more lines
>> because most of the time we'd be doing the version comparison anyway.
>
> The patch is actually about something different: rpm has two modes
> of operation: rpm refresh and rpm update. rpm refresh is done
> (after the patch) when the NEVRA matches. It differs from an update
> because rpm doesn't do an uninstall in that case. As there's no
> uninstall, the code must fake it by deleting the old header from the
> database when doing the install. Unfortunatelly this is detected in a
> different way: there are some some rpmdbSetIteratorRE() calls in
> rpmpsmStage(), stage PSM_PKGINSTALL.

Um, sorry but I'm not following... where does freshen come to play in the 
bug https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=104066 mentioned 
in the patch? Freshen won't even touch the other package there because the 
name differs...

> I think checking the HDRID is actually the right thing to do. The
> patch stems from rpm-3, where there was no HDRID. Maybe there
> should be some rpmSameHeader() function as an abstraction. The
> code in psm.c should be changed to:
>
>    psm->mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmteN(psm->te), 0);
>    while ((psm->oh = rpmdbNextIterator(psm->mi)) != NULL) {
>        if (!rpmSameHeader(fi->h, psm->oh))
> 	    continue;
> 	fi->record = rpmdbGetIteratorOffset(psm->mi);
> 	psm->oh = NULL;
> 	/*@loopbreak@*/ break;
>    }
>
> This doesn't slow down the installation, as all the rpmdbSetIteratorRE()
> are currently also done after fetching the header.

That's pretty much what jbj's version of the patch does, but not in psm.c 
but rpmtsAddInstallElement() much like your original patch. A thinko wrt 
location / mixup with some other patch perhaps?

BTW and here's the fix from jbj's tree, and brief testing shows it also 
fixes the foo-1.1 vs bar-1.1 case from #104066.

 	- Panu -

diff -r 8a1bbb5918b9 lib/depends.c
--- a/lib/depends.c	Tue May 29 13:43:06 2007 +0300
+++ b/lib/depends.c	Fri Jun 01 12:29:16 2007 +0300
@@ -123,6 +123,34 @@ static int removePackage(rpmts ts, Heade

      return 0;
  }
+
+static int rpmHeadersIdentical(Header first, Header second)
+        /*@*/
+{
+    const char * one, * two;
+    rpmds A, B;
+    int rc;
+
+    if (!headerGetEntry(first, RPMTAG_HDRID, NULL, (void **) &one, NULL))
+        one = NULL;
+    if (!headerGetEntry(second, RPMTAG_HDRID, NULL, (void **) &two, NULL))
+        two = NULL;
+
+    if (one && two)
+        return ((strcmp(one, two) == 0) ? 1 : 0);
+    if (one && !two)
+        return 0;
+    if (!one && two)
+        return 0;
+    /* XXX Headers w/o digests case devolves to NEVR comparison. */
+    A = rpmdsThis(first, RPMTAG_REQUIRENAME, RPMSENSE_EQUAL);
+    B = rpmdsThis(second, RPMTAG_REQUIRENAME, RPMSENSE_EQUAL);
+    rc = rpmdsCompare(A, B);
+    A = rpmdsFree(A);
+    B = rpmdsFree(B);
+    return rc;
+}
+

  int rpmtsAddInstallElement(rpmts ts, Header h,
  			fnpyKey key, int upgrade, rpmRelocation * relocs)
@@ -308,9 +336,9 @@ addheader:
  	if (tscolor && hcolor && ohcolor && !(hcolor & ohcolor))
  	    continue;

-	/* Skip packages that contain identical NEVR. */
-	if (rpmVersionCompare(h, oh) == 0)
-	    continue;
+        /* Skip identical packages. */
+        if (rpmHeadersIdentical(h, oh))
+            continue;

  	xx = removePackage(ts, oh, rpmdbGetIteratorOffset(mi), pkgKey);
      }



More information about the Rpm-maint mailing list