From db28221a4a48f6ee3c804c92314330637c808638 Mon Sep 17 00:00:00 2001 From: Michael Schroeder Date: Mon, 23 Apr 2012 11:04:02 +0300 Subject: [PATCH] Add support for dpkg-style sorting of tilde in version/release - This allows much nicer handling some common scenarios such as upstream pre-releases where the pre-release version would normally appear newer than final release, eg 1.0-rc1 vs 1.0. Previously this required mapping the pre-release tag into the release tag to achieve desired sorting, with tild this becomes simply 1.0~rc1 < 1.0. - Add a rpmlib() tracking dependency to prevent older rpm versions from getting confused with packages relying on the new behavior. --- rpm-4.8.0/build/pack.c.tilde 2009-12-07 15:36:49.000000000 +0100 +++ rpm-4.8.0/build/pack.c 2012-10-14 23:01:56.551911086 +0200 @@ -333,6 +333,41 @@ return RPMRC_OK; } +static int depContainsTilde(Header h, rpmTag tagEVR) +{ + struct rpmtd_s evrs; + const char *evr = NULL; + + if (headerGet(h, tagEVR, &evrs, HEADERGET_MINMEM)) { + while ((evr = rpmtdNextString(&evrs)) != NULL) + if (strchr(evr, '~')) + break; + rpmtdFreeData(&evrs); + } + return evr != NULL; +} + +static rpmTag depevrtags[] = { + RPMTAG_PROVIDEVERSION, + RPMTAG_REQUIREVERSION, + RPMTAG_OBSOLETEVERSION, + RPMTAG_CONFLICTVERSION, + RPMTAG_TRIGGERVERSION, + RPMTAG_SUGGESTSVERSION, + RPMTAG_ENHANCESVERSION, + 0 +}; + +static int haveTildeDep(Header h) +{ + int i; + + for (i = 0; depevrtags[i] != 0; i++) + if (depContainsTilde(h, depevrtags[i])) + return 1; + return 0; +} + rpmRC writeRPM(Header *hdrp, unsigned char ** pkgidp, const char *fileName, CSA_t csa, char *passPhrase, char **cookie) { @@ -405,6 +440,10 @@ free(buf); } + /* check if the package has a dependency with a '~' */ + if (haveTildeDep(h)) + (void) rpmlibNeedsFeature(h, "TildeInVersions", "4.10.0-1"); + /* Create and add the cookie */ if (cookie) { rasprintf(cookie, "%s %d", buildHost(), (int) (*getBuildTime())); --- rpm-4.8.0/build/parseReqs.c.tilde 2009-12-17 10:05:55.000000000 +0100 +++ rpm-4.8.0/build/parseReqs.c 2012-10-14 23:01:56.553911076 +0200 @@ -168,7 +168,7 @@ } EVR = xmalloc((ve-v) + 1); rstrlcpy(EVR, v, (ve-v) + 1); - if (rpmCharCheck(spec, EVR, ve-v, ".-_+:%{}")) goto exit; + if (rpmCharCheck(spec, EVR, ve-v, ".-_+:%{}~")) goto exit; re = ve; /* ==> next token after EVR string starts here */ } else EVR = NULL; --- rpm-4.8.0/build/parsePreamble.c.tilde 2009-12-17 10:05:55.000000000 +0100 +++ rpm-4.8.0/build/parsePreamble.c 2012-10-14 23:01:56.552911081 +0200 @@ -523,7 +523,7 @@ case RPMTAG_VERSION: case RPMTAG_RELEASE: SINGLE_TOKEN_ONLY; - if (rpmCharCheck(spec, field, strlen(field), "._+%{}") != RPMRC_OK) return RPMRC_FAIL; + if (rpmCharCheck(spec, field, strlen(field), "._+%{}~") != RPMRC_OK) return RPMRC_FAIL; headerPutString(pkg->header, tag, field); break; case RPMTAG_URL: --- rpm-4.8.0/lib/rpmds.c.tilde 2009-12-07 15:36:49.000000000 +0100 +++ rpm-4.8.0/lib/rpmds.c 2012-10-14 23:01:56.554911071 +0200 @@ -962,6 +962,9 @@ ( RPMSENSE_EQUAL), N_("support for POSIX.1e file capabilities") }, #endif + { "rpmlib(TildeInVersions)", "4.10.0-1", + ( RPMSENSE_EQUAL), + N_("dependency comparison supports versions with tilde.") }, { NULL, NULL, 0, NULL } }; --- rpm-4.8.0/lib/rpmvercmp.c.tilde 2009-12-07 15:36:49.000000000 +0100 +++ rpm-4.8.0/lib/rpmvercmp.c 2012-10-14 23:01:56.555911066 +0200 @@ -32,9 +32,18 @@ two = str2; /* loop through each version segment of str1 and str2 and compare them */ - while (*one && *two) { - while (*one && !risalnum(*one)) one++; - while (*two && !risalnum(*two)) two++; + while (*one || *two) { + while (*one && !risalnum(*one) && *one != '~') one++; + while (*two && !risalnum(*two) && *two != '~') two++; + + /* handle the tilde separator, it sorts before everthing else */ + if (*one == '~' || *two == '~') { + if (*one != '~') return 1; + if (*two != '~') return -1; + one++; + two++; + continue; + } /* If we ran to the end of either, we are finished with the loop */ if (!(*one && *two)) break;