From 5c46ba14f780474e2b04b54aa7b0c8bf60de2b5b Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Mon, 10 Jan 2011 10:44:25 -0600 Subject: Allow version comparison to contain epoch specifier Adapting from RPM, follow the [epoch:]version[-release] syntax. We can also borrow some of their parsing code for our purposes (thanks!). Add some new tests to our vercmp shell script tester for epoch comparisons, and then make the code work with these newfangled epoch specifiers. Signed-off-by: Dan McGee --- lib/libalpm/version.c | 157 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 117 insertions(+), 40 deletions(-) (limited to 'lib') diff --git a/lib/libalpm/version.c b/lib/libalpm/version.c index 85cc2f57..eba66210 100644 --- a/lib/libalpm/version.c +++ b/lib/libalpm/version.c @@ -23,23 +23,66 @@ /* libalpm */ #include "util.h" -/** Compare two version strings and determine which one is 'newer'. - * Returns a value comparable to the way strcmp works. Returns 1 - * if a is newer than b, 0 if a and b are the same version, or -1 - * if b is newer than a. - * - * This function has been adopted from the rpmvercmp function located - * at lib/rpmvercmp.c, and was most recently updated against rpm - * version 4.4.2.3. Small modifications have been made to make it more - * consistent with the libalpm coding style. - * - * Keep in mind that the pkgrel is only compared if it is available - * on both versions handed to this function. For example, comparing - * 1.5-1 and 1.5 will yield 0; comparing 1.5-1 and 1.5-2 will yield - * -1 as expected. This is mainly for supporting versioned dependencies - * that do not include the pkgrel. +/** + * Some functions in this file have been adopted from the rpm source, notably + * 'rpmvercmp' located at lib/rpmvercmp.c and 'parseEVR' located at + * lib/rpmds.c. It was most recently updated against rpm version 4.8.1. Small + * modifications have been made to make it more consistent with the libalpm + * coding style. */ -int SYMEXPORT alpm_pkg_vercmp(const char *a, const char *b) + +/** + * Split EVR into epoch, version, and release components. + * @param evr [epoch:]version[-release] string + * @retval *ep pointer to epoch + * @retval *vp pointer to version + * @retval *rp pointer to release + */ +static void parseEVR(char *evr, const char **ep, const char **vp, + const char **rp) +{ + const char *epoch; + const char *version; + const char *release; + char *s, *se; + + s = evr; + /* s points to epoch terminator */ + while (*s && isdigit(*s)) s++; + /* se points to version terminator */ + se = strrchr(s, '-'); + + if(*s == ':') { + epoch = evr; + *s++ = '\0'; + version = s; + if(*epoch == '\0') { + epoch = "0"; + } + } else { + /* different from RPM- always assume 0 epoch */ + epoch = "0"; + version = evr; + } + if(se) { + *se++ = '\0'; + release = se; + } else { + release = NULL; + } + + if(ep) *ep = epoch; + if(vp) *vp = version; + if(rp) *rp = release; +} + +/** + * Compare alpha and numeric segments of two versions. + * return 1: a is newer than b + * 0: a and b are the same version + * -1: b is newer than a + */ +static int rpmvercmp(const char *a, const char *b) { char oldch1, oldch2; char *str1, *str2; @@ -49,13 +92,6 @@ int SYMEXPORT alpm_pkg_vercmp(const char *a, const char *b) int isnum; int ret = 0; - /* libalpm added code. ensure our strings are not null */ - if(!a) { - if(!b) return(0); - return(-1); - } - if(!b) return(1); - /* easy comparison to see if versions are identical */ if(strcmp(a, b) == 0) return(0); @@ -147,22 +183,6 @@ int SYMEXPORT alpm_pkg_vercmp(const char *a, const char *b) one = ptr1; *ptr2 = oldch2; two = ptr2; - - /* libalpm added code. check if version strings have hit the pkgrel - * portion. depending on which strings have hit, take correct action. - * this is all based on the premise that we only have one dash in - * the version string, and it separates pkgver from pkgrel. */ - if(*ptr1 == '-' && *ptr2 == '-') { - /* no-op, continue comparing since we are equivalent throughout */ - } else if(*ptr1 == '-') { - /* ptr1 has hit the pkgrel and ptr2 has not. continue version - * comparison after stripping the pkgrel from ptr1. */ - *ptr1 = '\0'; - } else if(*ptr2 == '-') { - /* ptr2 has hit the pkgrel and ptr1 has not. continue version - * comparison after stripping the pkgrel from ptr2. */ - *ptr2 = '\0'; - } } /* this catches the case where all numeric and alpha segments have */ @@ -179,7 +199,7 @@ int SYMEXPORT alpm_pkg_vercmp(const char *a, const char *b) * - if one is an alpha, two is newer. * - otherwise one is newer. * */ - if ( ( !*one && !isalpha((int)*two) ) + if ( (!*one && !isalpha((int)*two)) || isalpha((int)*one) ) { ret = -1; } else { @@ -192,4 +212,61 @@ cleanup: return(ret); } +/** Compare two version strings and determine which one is 'newer'. + * Returns a value comparable to the way strcmp works. Returns 1 + * if a is newer than b, 0 if a and b are the same version, or -1 + * if b is newer than a. + * + * Different epoch values for version strings will override any further + * comparison. If no epoch is provided, 0 is assumed. + * + * Keep in mind that the pkgrel is only compared if it is available + * on both versions handed to this function. For example, comparing + * 1.5-1 and 1.5 will yield 0; comparing 1.5-1 and 1.5-2 will yield + * -1 as expected. This is mainly for supporting versioned dependencies + * that do not include the pkgrel. + */ +int SYMEXPORT alpm_pkg_vercmp(const char *a, const char *b) +{ + char *full1, *full2; + const char *epoch1, *ver1, *rel1; + const char *epoch2, *ver2, *rel2; + int ret; + + /* ensure our strings are not null */ + if(!a && !b) { + return(0); + } else if(!a) { + return(-1); + } else if(!b) { + return(1); + } + /* another quick shortcut- if full version specs are equal */ + if(strcmp(a, b) == 0) { + return(0); + } + + /* Parse both versions into [epoch:]version[-release] triplets. We probably + * don't need epoch and release to support all the same magic, but it is + * easier to just run it all through the same code. */ + full1 = strdup(a); + full2 = strdup(b); + + /* parseEVR modifies passed in version, so have to dupe it first */ + parseEVR(full1, &epoch1, &ver1, &rel1); + parseEVR(full2, &epoch2, &ver2, &rel2); + + ret = rpmvercmp(epoch1, epoch2); + if(ret == 0) { + ret = rpmvercmp(ver1, ver2); + if(ret == 0 && rel1 && rel2) { + ret = rpmvercmp(rel1, rel2); + } + } + + free(full1); + free(full2); + return(ret); +} + /* vim: set ts=2 sw=2 noet: */ -- cgit v1.2.3-24-g4f1b From bf46e04614b3740eea4a5e0d44767f57e1cffa4d Mon Sep 17 00:00:00 2001 From: Dan McGee Date: Mon, 10 Jan 2011 13:40:31 -0600 Subject: Remove epoch as an independent field Instead, go the same route we have always taken with version-release in libalpm and treat it all as one piece of information. Makepkg is the only script that knows about epoch as a distinct value; from there on out we will parse out the components as necessary. This makes the code a lot simpler as far as epoch handling goes. The downside here is that we are tossing some compatibility to the wind; packages using force will have to be rebuilt with an incremented epoch to keep their special status. Signed-off-by: Dan McGee --- lib/libalpm/alpm.h | 1 - lib/libalpm/be_local.c | 16 ---------------- lib/libalpm/be_package.c | 7 ------- lib/libalpm/be_sync.c | 9 --------- lib/libalpm/package.c | 20 -------------------- lib/libalpm/package.h | 2 -- 6 files changed, 55 deletions(-) (limited to 'lib') diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 7c4cd48b..a540bc4f 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -238,7 +238,6 @@ size_t alpm_pkg_changelog_read(void *ptr, size_t size, /*int alpm_pkg_changelog_feof(const pmpkg_t *pkg, void *fp);*/ int alpm_pkg_changelog_close(const pmpkg_t *pkg, void *fp); int alpm_pkg_has_scriptlet(pmpkg_t *pkg); -int alpm_pkg_get_epoch(pmpkg_t *pkg); off_t alpm_pkg_download_size(pmpkg_t *newpkg); alpm_list_t *alpm_pkg_unused_deltas(pmpkg_t *pkg); diff --git a/lib/libalpm/be_local.c b/lib/libalpm/be_local.c index 5471fee4..ea59ceca 100644 --- a/lib/libalpm/be_local.c +++ b/lib/libalpm/be_local.c @@ -156,12 +156,6 @@ static alpm_list_t *_cache_get_groups(pmpkg_t *pkg) return pkg->groups; } -static int _cache_get_epoch(pmpkg_t *pkg) -{ - LAZY_LOAD(INFRQ_DESC, -1); - return pkg->epoch; -} - static int _cache_has_scriptlet(pmpkg_t *pkg) { ALPM_LOG_FUNC; @@ -318,7 +312,6 @@ static struct pkg_operations local_pkg_ops = { .get_size = _cache_get_size, .get_isize = _cache_get_isize, .get_reason = _cache_get_reason, - .get_epoch = _cache_get_epoch, .has_scriptlet = _cache_has_scriptlet, .get_licenses = _cache_get_licenses, .get_groups = _cache_get_groups, @@ -606,11 +599,6 @@ int _alpm_local_db_read(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) STRDUP(linedup, _alpm_strtrim(line), goto error); info->replaces = alpm_list_add(info->replaces, linedup); } - } else if(strcmp(line, "%EPOCH%") == 0) { - if(fgets(line, sizeof(line), fp) == NULL) { - goto error; - } - info->epoch = atoi(_alpm_strtrim(line)); } else if(strcmp(line, "%DEPENDS%") == 0) { while(fgets(line, sizeof(line), fp) && strlen(_alpm_strtrim(line))) { pmdepend_t *dep = _alpm_splitdep(_alpm_strtrim(line)); @@ -767,10 +755,6 @@ int _alpm_local_db_write(pmdb_t *db, pmpkg_t *info, pmdbinfrq_t inforeq) } fprintf(fp, "\n"); } - if(info->epoch) { - fprintf(fp, "%%EPOCH%%\n" - "%d\n\n", info->epoch); - } if(info->url) { fprintf(fp, "%%URL%%\n" "%s\n\n", info->url); diff --git a/lib/libalpm/be_package.c b/lib/libalpm/be_package.c index b69161b4..c272bd47 100644 --- a/lib/libalpm/be_package.c +++ b/lib/libalpm/be_package.c @@ -184,13 +184,6 @@ static int parse_descfile(struct archive *a, pmpkg_t *newpkg) STRDUP(newpkg->version, ptr, RET_ERR(PM_ERR_MEMORY, -1)); } else if(strcmp(key, "pkgdesc") == 0) { STRDUP(newpkg->desc, ptr, RET_ERR(PM_ERR_MEMORY, -1)); - } else if(strcmp(key, "force") == 0) { - /* For backward compatibility, like in sync_db_read */ - if(!newpkg->epoch) { - newpkg->epoch = 1; - } - } else if(strcmp(key, "epoch") == 0) { - newpkg->epoch = atoi(ptr); } else if(strcmp(key, "group") == 0) { newpkg->groups = alpm_list_add(newpkg->groups, strdup(ptr)); } else if(strcmp(key, "url") == 0) { diff --git a/lib/libalpm/be_sync.c b/lib/libalpm/be_sync.c index 1e4b2fde..4676e8a6 100644 --- a/lib/libalpm/be_sync.c +++ b/lib/libalpm/be_sync.c @@ -340,15 +340,6 @@ static int sync_db_read(pmdb_t *db, struct archive *archive, READ_AND_STORE(pkg->md5sum); } else if(strcmp(line, "%REPLACES%") == 0) { READ_AND_STORE_ALL(pkg->replaces); - } else if(strcmp(line, "%EPOCH%") == 0) { - READ_NEXT(line); - pkg->epoch = atoi(line); - } else if(strcmp(line, "%FORCE%") == 0) { - /* For backward compatibility, treat force as a non-zero epoch - * but only if we didn't already have a known epoch value. */ - if(!pkg->epoch) { - pkg->epoch = 1; - } } else if(strcmp(line, "%DEPENDS%") == 0) { /* Different than the rest because of the _alpm_splitdep call. */ while(1) { diff --git a/lib/libalpm/package.c b/lib/libalpm/package.c index 241c41c0..d4b3b9c0 100644 --- a/lib/libalpm/package.c +++ b/lib/libalpm/package.c @@ -110,7 +110,6 @@ static const char *_pkg_get_arch(pmpkg_t *pkg) { return pkg->arch; } static off_t _pkg_get_size(pmpkg_t *pkg) { return pkg->size; } static off_t _pkg_get_isize(pmpkg_t *pkg) { return pkg->isize; } static pmpkgreason_t _pkg_get_reason(pmpkg_t *pkg) { return pkg->reason; } -static int _pkg_get_epoch(pmpkg_t *pkg) { return pkg->epoch; } static int _pkg_has_scriptlet(pmpkg_t *pkg) { return pkg->scriptlet; } static alpm_list_t *_pkg_get_licenses(pmpkg_t *pkg) { return pkg->licenses; } @@ -141,7 +140,6 @@ struct pkg_operations default_pkg_ops = { .get_size = _pkg_get_size, .get_isize = _pkg_get_isize, .get_reason = _pkg_get_reason, - .get_epoch = _pkg_get_epoch, .has_scriptlet = _pkg_has_scriptlet, .get_licenses = _pkg_get_licenses, .get_groups = _pkg_get_groups, @@ -223,11 +221,6 @@ pmpkgreason_t SYMEXPORT alpm_pkg_get_reason(pmpkg_t *pkg) return pkg->ops->get_reason(pkg); } -int SYMEXPORT alpm_pkg_get_epoch(pmpkg_t *pkg) -{ - return pkg->ops->get_epoch(pkg); -} - alpm_list_t SYMEXPORT *alpm_pkg_get_licenses(pmpkg_t *pkg) { return pkg->ops->get_licenses(pkg); @@ -427,7 +420,6 @@ pmpkg_t *_alpm_pkg_dup(pmpkg_t *pkg) newpkg->size = pkg->size; newpkg->isize = pkg->isize; newpkg->scriptlet = pkg->scriptlet; - newpkg->epoch = pkg->epoch; newpkg->reason = pkg->reason; newpkg->licenses = alpm_list_strdup(pkg->licenses); @@ -518,20 +510,8 @@ void _alpm_pkg_free_trans(pmpkg_t *pkg) /* Is spkg an upgrade for localpkg? */ int _alpm_pkg_compare_versions(pmpkg_t *spkg, pmpkg_t *localpkg) { - int spkg_epoch, localpkg_epoch; - ALPM_LOG_FUNC; - spkg_epoch = alpm_pkg_get_epoch(spkg); - localpkg_epoch = alpm_pkg_get_epoch(localpkg); - - if(spkg_epoch > localpkg_epoch) { - return(1); - } else if(spkg_epoch < localpkg_epoch) { - return(-1); - } - - /* equal epoch values, move on to version comparison */ return alpm_pkg_vercmp(alpm_pkg_get_version(spkg), alpm_pkg_get_version(localpkg)); } diff --git a/lib/libalpm/package.h b/lib/libalpm/package.h index 52582d9b..b161d5f1 100644 --- a/lib/libalpm/package.h +++ b/lib/libalpm/package.h @@ -57,7 +57,6 @@ struct pkg_operations { off_t (*get_size) (pmpkg_t *); off_t (*get_isize) (pmpkg_t *); pmpkgreason_t (*get_reason) (pmpkg_t *); - int (*get_epoch) (pmpkg_t *); int (*has_scriptlet) (pmpkg_t *); alpm_list_t *(*get_licenses) (pmpkg_t *); @@ -107,7 +106,6 @@ struct __pmpkg_t { off_t download_size; int scriptlet; - int epoch; pmpkgreason_t reason; pmpkgfrom_t origin; -- cgit v1.2.3-24-g4f1b