From 51bee11bfa2249ab4ff52c384d3854b8353a5091 Mon Sep 17 00:00:00 2001 From: Juan RP Date: Sat, 4 Jun 2011 15:42:50 +0200 Subject: [PATCH] Switch xbps_cmpver() to use NetBSD's dewey code. --- lib/Makefile | 2 +- lib/cmpver.c | 284 --------------------------------------------------- lib/dewey.c | 18 +++- 3 files changed, 18 insertions(+), 286 deletions(-) delete mode 100644 lib/cmpver.c diff --git a/lib/Makefile b/lib/Makefile index fb7ba2db..c2ea9f5e 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -42,7 +42,7 @@ OBJS += package_remove.o package_remove_obsoletes.o package_state.o OBJS += package_unpack.o package_requiredby.o package_register.o OBJS += package_purge.o package_replaces.o OBJS += transaction_dictionary.o transaction_sortdeps.o -OBJS += cmpver.o download.o fexec.o humanize_number.o plist.o +OBJS += download.o fexec.o humanize_number.o plist.o OBJS += plist_archive_entry.o plist_find.o plist_remove.o OBJS += plist_fetch.o util.o mkpath.o initend.o OBJS += regpkgdb_dictionary.o match.o dewey.o diff --git a/lib/cmpver.c b/lib/cmpver.c deleted file mode 100644 index 3ae9f5ba..00000000 --- a/lib/cmpver.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * FreeBSD install - a package for the installation and maintenance - * of non-core utilities. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * Maxim Sobolev - * 31 July 2001 - * - * Written by Oliver Eikemeier - * Based on work of Jeremy D. Lea. - * - */ - -#include -#include -#include -#include -#include - -#include "xbps_api_impl.h" - -/* - * split_version(pkgname, endname, epoch, revision) returns a pointer to - * the version portion of a package name and the two special components. - * - * Syntax is: ${PKGNAME}-${VERSION}[_${PKGREVISION}][:${EPOCH}] - * - */ -static const char * -split_version(const char *pkgname, const char **endname, unsigned long *epoch, - unsigned long *revision) -{ - char *ch; - const char *versionstr; - const char *endversionstr; - - assert(pkgname != NULL); - - /* Look for the last '-' the the pkgname */ - ch = strrchr(pkgname, '-'); - /* Cheat if we are just passed a version, not a valid package name */ - versionstr = ch ? ch + 1 : pkgname; - - /* Look for the last '_' in the version string, advancing the end pointer */ - ch = strrchr(versionstr, '_'); - if (revision != NULL) { - *revision = ch ? strtoul(ch + 1, NULL, 10) : 0; - } - endversionstr = ch; - - /* Look for the last ':' in the remaining version string */ - ch = strrchr(endversionstr ? endversionstr + 1 : versionstr, ':'); - if (epoch != NULL) { - *epoch = ch ? strtoul(ch + 1, NULL, 10) : 0; - } - if (ch && !endversionstr) - endversionstr = ch; - - /* - * set the pointer behind the last character of the version without - * revision or epoch - */ - if (endname) - *endname = endversionstr ? endversionstr : strrchr(versionstr, '\0'); - - return versionstr; -} - -/* - * VERSIONs are composed of components separated by dots. A component - * consists of a version number, a letter and a patchlevel number. - */ - -typedef struct { - long n; - long pl; - int a; -} version_component; - -/* - * get_component(position, component) gets the value of the next component - * (number - letter - number triple) and returns a pointer to the next character - * after any leading separators - * - * - components are separated by dots - * - characters !~ [a-zA-Z0-9.+*] are treated as separators - * (1.0:2003.09.16 = 1.0.2003.09.16), this may not be what you expect: - * 1.0.1:2003.09.16 < 1.0:2003.09.16 - * - consecutive separators are collapsed (10..1 = 10.1) - * - missing separators are inserted, essentially - * letter number letter => letter number . letter (10a1b2 = 10a1.b2) - * - missing components are assumed to be equal to 0 (10 = 10.0 = 10.0.0) - * - the letter sort order is: [none], a, b, ..., z; numbers without letters - * sort first (10 < 10a < 10b) - * - missing version numbers (in components starting with a letter) sort as -1 - * (a < 0, 10.a < 10) - * - a separator is inserted before the special strings "pl", "alpha", "beta", - * "pre" and "rc". - * - "pl" sorts before every other letter, "alpha", "beta", "pre" and "rc" - * sort as a, b, p and r. (10alpha = 10.a < 10, but 10 < 10a; pl11 < alpha3 - * < 0.1beta2 = 0.1.b2 < 0.1) - * - other strings use only the first letter for sorting, case is ignored - * (1.d2 = 1.dev2 = 1.Development2) - * - The special component `*' is guaranteed to be the smallest possible - * component (2.* < 2pl1 < 2alpha3 < 2.9f7 < 3.*) - * - components separated by `+' are handled by version_cmp below - */ - -static const struct { - const char *name; - size_t namelen; - int value; -} stage[] = { - { "pl", 2, 0 }, - { "alpha", 5, 'a'-'a'+1 }, - { "beta", 4, 'b'-'a'+1 }, - { "pre", 3, 'p'-'a'+1 }, - { "rc", 2, 'r'-'a'+1 }, - { NULL, 0, -1 } -}; - -static const char * -get_component(const char *position, version_component *component) -{ - const char *pos = position; - int hasstage = 0, haspatchlevel = 0; - - assert(pos != NULL); - - /* handle version number */ - if (isdigit((unsigned char)*pos)) { - char *endptr; - component->n = strtol(pos, &endptr, 10); - /* should we test for errno == ERANGE? */ - pos = endptr; - } else if (*pos == '*') { - component->n = -2; - do { - pos++; - } while(*pos && *pos != '+'); - } else { - component->n = -1; - hasstage = 1; - } - - /* handle letter */ - if (isalpha((unsigned char)*pos)) { - int c = tolower((unsigned char)*pos); - haspatchlevel = 1; - /* handle special suffixes */ - if (isalpha((unsigned char)pos[1])) { - int i; - for (i = 0; stage[i].name; i++) { - if (strncasecmp(pos, stage[i].name, stage[i].namelen) == 0 - && !isalpha((unsigned char)pos[stage[i].namelen])) { - if (hasstage) { - /* stage to value */ - component->a = stage[i].value; - pos += stage[i].namelen; - } else { - /* insert dot */ - component->a = 0; - haspatchlevel = 0; - } - c = 0; - break; - } - } - } - /* unhandled above */ - if (c) { - /* use the first letter and skip following */ - component->a = c - 'a' + 1; - do { - ++pos; - } while (isalpha((unsigned char)*pos)); - } - } else { - component->a = 0; - haspatchlevel = 0; - } - - if (haspatchlevel) { - /* handle patch number */ - if (isdigit((unsigned char)*pos)) { - char *endptr; - component->pl = strtol(pos, &endptr, 10); - /* should we test for errno == ERANGE? */ - pos = endptr; - } else { - component->pl = -1; - } - } else { - component->pl = 0; - } - - /* skip trailing separators */ - while (*pos && !isdigit((unsigned char)*pos) && - !isalpha((unsigned char)*pos) && - *pos != '+' && *pos != '*') { - pos++; - } - - return pos; -} - -/* - * version_cmp(pkg1, pkg2) returns -1, 0 or 1 depending on if the version - * components of pkg1 is less than, equal to or greater than pkg2. No - * comparison of the basenames is done. - * - * The port version is defined by: - * ${VERSION}[_${PKGREVISION}][:${EPOCH}] - * ${EPOCH} supersedes ${VERSION} supersedes ${PKGREVISION}. - * - * The epoch and revision are defined to be a single number, while the rest - * of the version should conform to the porting guidelines. It can contain - * multiple components, separated by a period, including letters. - */ -int -xbps_cmpver(const char *pkg1, const char *pkg2) -{ - const char *v1, *v2, *ve1, *ve2; - unsigned long e1, e2, r1, r2; - int result = 0; - - v1 = split_version(pkg1, &ve1, &e1, &r1); - v2 = split_version(pkg2, &ve2, &e2, &r2); - - /* Check epoch, version, and pkgrevision, in that order. */ - if (e1 != e2) { - result = (e1 < e2 ? -1 : 1); - } - - /* Shortcut check for equality before invoking the parsing routines. */ - if (result == 0 && (ve1 - v1 != ve2 - v2 || - strncasecmp(v1, v2, (size_t)ve1 - (size_t)v1) != 0)) { - /* Loop over different components (the parts separated by dots). - * If any component differs, we have the basis for an inequality. */ - while(result == 0 && (v1 < ve1 || v2 < ve2)) { - int block_v1 = 0; - int block_v2 = 0; - version_component vc1 = {0, 0, 0}; - version_component vc2 = {0, 0, 0}; - if (v1 < ve1 && *v1 != '+') { - v1 = get_component(v1, &vc1); - } else { - block_v1 = 1; - } - if (v2 < ve2 && *v2 != '+') { - v2 = get_component(v2, &vc2); - } else { - block_v2 = 1; - } - if (block_v1 && block_v2) { - if (v1 < ve1) - v1++; - if (v2 < ve2) - v2++; - } else if (vc1.n != vc2.n) { - result = (vc1.n < vc2.n ? -1 : 1); - } else if (vc1.a != vc2.a) { - result = (vc1.a < vc2.a ? -1 : 1); - } else if (vc1.pl != vc2.pl) { - result = (vc1.pl < vc2.pl ? -1 : 1); - } - } - } - - /* Compare revision numbers. */ - if (result == 0 && r1 != r2) { - result = (r1 < r2 ? -1 : 1); - } - - return result; -} diff --git a/lib/dewey.c b/lib/dewey.c index 5720baaf..ed9348cf 100644 --- a/lib/dewey.c +++ b/lib/dewey.c @@ -254,7 +254,7 @@ vtest(arr_t *lhs, int tst, arr_t *rhs) } /* - * Compare two dewey decimal numbers + * Compare two dewey decimal numbers. */ static int dewey_cmp(const char *lhs, int op, const char *rhs) @@ -275,6 +275,22 @@ dewey_cmp(const char *lhs, int op, const char *rhs) return retval; } +/* + * Returns -1, 0 or 1 depending on if the version components of + * pkg1 is less than, equal to or greater than pkg2. No comparison + * comparison of the basenames is done. + */ +int +xbps_cmpver(const char *pkg1, const char *pkg2) +{ + if (dewey_cmp(pkg1, DEWEY_LT, pkg2)) + return -1; + else if (dewey_cmp(pkg1, DEWEY_GT, pkg2)) + return 1; + else + return 0; +} + /* * Perform dewey match on "pkg" against "pattern". * Return 1 on match, 0 on non-match, -1 on error.