diff options
author | Mike Frysinger <vapier@gentoo.org> | 2013-04-29 04:38:16 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2013-04-29 04:38:16 +0000 |
commit | 9ba7e8a90a1735ae016988c4983af8b78a3df203 (patch) | |
tree | d86391157bf220e09af37c358e4712e491afc612 | |
parent | qatom: check # of args before running main code (diff) | |
download | portage-utils-9ba7e8a90a1735ae016988c4983af8b78a3df203.tar.gz portage-utils-9ba7e8a90a1735ae016988c4983af8b78a3df203.tar.bz2 portage-utils-9ba7e8a90a1735ae016988c4983af8b78a3df203.zip |
initial support for prefix/suffix operators #369225 by Christian Ruppert
-rw-r--r-- | libq/atom_compare.c | 155 | ||||
-rw-r--r-- | libq/atom_explode.c | 62 | ||||
-rw-r--r-- | qatom.c | 8 | ||||
-rw-r--r-- | tests/atom_compare/.cvsignore | 1 | ||||
-rw-r--r-- | tests/atom_compare/.gitignore | 1 | ||||
-rw-r--r-- | tests/atom_compare/Makefile | 21 | ||||
-rwxr-xr-x | tests/atom_compare/atom-compare.py | 41 | ||||
-rw-r--r-- | tests/atom_compare/static.good | 30 | ||||
-rw-r--r-- | tests/atom_compare/static.q.good | 7 | ||||
-rw-r--r-- | tests/atom_compare/static.q.tests | 12 | ||||
-rw-r--r-- | tests/atom_compare/static.tests | 30 | ||||
-rw-r--r-- | tests/subdir.mk | 2 |
12 files changed, 301 insertions, 69 deletions
diff --git a/libq/atom_compare.c b/libq/atom_compare.c index 18bfe98..41cb115 100644 --- a/libq/atom_compare.c +++ b/libq/atom_compare.c @@ -1,43 +1,73 @@ /* * Copyright 2005-2008 Gentoo Foundation * Distributed under the terms of the GNU General Public License v2 - * $Header: /var/cvsroot/gentoo-projects/portage-utils/libq/atom_compare.c,v 1.7 2011/02/21 01:33:47 vapier Exp $ + * $Header: /var/cvsroot/gentoo-projects/portage-utils/libq/atom_compare.c,v 1.8 2013/04/29 04:38:16 vapier Exp $ * * Copyright 2005-2008 Ned Ludd - <solar@gentoo.org> * Copyright 2005-2008 Mike Frysinger - <vapier@gentoo.org> */ -/* -typedef struct { - char *CATEGORY; - char *PN; - int PR_int; - char *PV, *PVR; - char *P; -} depend_atom; -*/ - const char * const booga[] = {"!!!", "!=", "==", ">", "<"}; enum { ERROR=0, NOT_EQUAL, EQUAL, NEWER, OLDER }; + +static int _atom_compare_match(int ret, atom_operator op) +{ + if (op == ATOM_OP_NONE) + return ret; + +#define E(x) ((x) ? EQUAL : NOT_EQUAL) + switch (op) { + case ATOM_OP_NEWER: + return E(ret == NEWER); + case ATOM_OP_NEWER_EQUAL: + return E(ret != OLDER); + case ATOM_OP_PV_EQUAL: /* we handled this in atom_compare */ + case ATOM_OP_EQUAL: + return E(ret == EQUAL); + case ATOM_OP_OLDER_EQUAL: + return E(ret != NEWER); + case ATOM_OP_OLDER: + return E(ret == OLDER); + default: + /* blockers/etc... */ + return NOT_EQUAL; + } +#undef E +} + /* a1 <return value> a2 * foo-1 <EQUAL> foo-1 * foo-1 <OLDER> foo-2 * foo-1 <NOT_EQUAL> bar-1 */ -int atom_compare(const depend_atom * const a1, const depend_atom * const a2); -int atom_compare(const depend_atom * const a1, const depend_atom * const a2) +static int atom_compare(const depend_atom *a1, const depend_atom *a2) { + /* sanity check that at most one has operators */ + if (a1->pfx_op != ATOM_OP_NONE || a1->sfx_op != ATOM_OP_NONE) { + /* this is bogus, so punt it */ + if (a2->pfx_op != ATOM_OP_NONE || a2->sfx_op != ATOM_OP_NONE) + return NOT_EQUAL; + /* swap a1 & a2 so that a2 is the atom with operators */ + const depend_atom *as = a2; + a2 = a1; + a1 = as; + } + atom_operator pfx_op = a2->pfx_op; + atom_operator sfx_op = a2->sfx_op; + /* check slot */ - if (a1->SLOT && a2->SLOT) - if (strcmp(a1->SLOT, a2->SLOT)) + if (a1->SLOT || a2->SLOT) { + if (!a1->SLOT || !a2->SLOT || strcmp(a1->SLOT, a2->SLOT)) return NOT_EQUAL; + } - /* check category */ + /* Check category, iff both are specified. This way we can match + * atoms like "sys-devel/gcc" and "gcc". + */ if (a1->CATEGORY && a2->CATEGORY) { if (strcmp(a1->CATEGORY, a2->CATEGORY)) return NOT_EQUAL; - } else if (a1->CATEGORY || a2->CATEGORY) - return NOT_EQUAL; + } /* check name */ if (a1->PN && a2->PN) { @@ -46,6 +76,22 @@ int atom_compare(const depend_atom * const a1, const depend_atom * const a2) } else if (a1->PN || a2->PN) return NOT_EQUAL; + /* in order to handle suffix globs, we need to know all of the + * version elements provided in it ahead of time + */ + unsigned int ver_bits = 0; + if (sfx_op == ATOM_OP_STAR) { + if (a2->letter) + ver_bits |= (1 << 0); + if (a2->suffixes[0].suffix != VER_NORM) + ver_bits |= (1 << 1); + /* This doesn't handle things like foo-1.0-r0*, but that atom + * doesn't ever show up in practice, so who cares. + */ + if (a2->PR_int) + ver_bits |= (1 << 2); + } + /* check version */ if (a1->PV && a2->PV) { char *s1, *s2; @@ -61,16 +107,17 @@ int atom_compare(const depend_atom * const a1, const depend_atom * const a2) ++s2; } if (*s1 == '0' && isdigit(*s2)) - return OLDER; + return _atom_compare_match(OLDER, pfx_op); else if (*s2 == '0' && isdigit(*s1)) - return NEWER; - } + return _atom_compare_match(NEWER, pfx_op); + } else if (sfx_op == ATOM_OP_STAR && !s2 && !ver_bits) + return _atom_compare_match(EQUAL, pfx_op); n1 = (s1 ? atoll(s1) : 0); n2 = (s2 ? atoll(s2) : 0); if (n1 < n2) - return OLDER; + return _atom_compare_match(OLDER, pfx_op); else if (n1 > n2) - return NEWER; + return _atom_compare_match(NEWER, pfx_op); if (s1) { s1 = strchr(s1, '.'); if (s1) ++s1; @@ -80,43 +127,61 @@ int atom_compare(const depend_atom * const a1, const depend_atom * const a2) if (s2) ++s2; } } + /* compare trailing letter 1.0[z]_alpha1 */ + if (sfx_op == ATOM_OP_STAR) { + ver_bits >>= 1; + if (!a2->letter && !ver_bits) + return _atom_compare_match(EQUAL, pfx_op); + } if (a1->letter < a2->letter) - return OLDER; - else if (a1->letter > a2->letter) - return NEWER; + return _atom_compare_match(OLDER, pfx_op); + if (a1->letter > a2->letter) + return _atom_compare_match(NEWER, pfx_op); /* find differing suffixes 1.0z[_alpha1] */ - size_t sidx = 0; - while (a1->suffixes[sidx].suffix == a2->suffixes[sidx].suffix) { - if (a1->suffixes[sidx].suffix == VER_NORM || - a2->suffixes[sidx].suffix == VER_NORM) + const atom_suffix *as1 = &a1->suffixes[0]; + const atom_suffix *as2 = &a2->suffixes[0]; + while (as1->suffix == as2->suffix) { + if (as1->suffix == VER_NORM || + as2->suffix == VER_NORM) break; - if (a1->suffixes[sidx].sint != a2->suffixes[sidx].sint) + if (as1->sint != as2->sint) break; - ++sidx; + ++as1; + ++as2; } /* compare suffixes 1.0z[_alpha]1 */ - if (a1->suffixes[sidx].suffix < a2->suffixes[sidx].suffix) - return OLDER; - else if (a1->suffixes[sidx].suffix > a2->suffixes[sidx].suffix) - return NEWER; + if (sfx_op == ATOM_OP_STAR) { + ver_bits >>= 1; + if (as2->suffix == VER_NORM && !ver_bits) + return _atom_compare_match(EQUAL, pfx_op); + } + if (as1->suffix < as2->suffix) + return _atom_compare_match(OLDER, pfx_op); + else if (as1->suffix > as2->suffix) + return _atom_compare_match(NEWER, pfx_op); /* compare suffix number 1.0z_alpha[1] */ - if (a1->suffixes[sidx].sint < a2->suffixes[sidx].sint) - return OLDER; - else if (a1->suffixes[sidx].sint > a2->suffixes[sidx].sint) - return NEWER; + if (sfx_op == ATOM_OP_STAR && !as2->sint && !ver_bits) + return _atom_compare_match(EQUAL, pfx_op); + else if (as1->sint < as2->sint) + return _atom_compare_match(OLDER, pfx_op); + else if (as1->sint > as2->sint) + return _atom_compare_match(NEWER, pfx_op); /* fall through to -r# check below */ } else if (a1->PV || a2->PV) - return NOT_EQUAL; - - if (a1->PR_int == a2->PR_int) return EQUAL; + + /* Make sure the -r# is the same. */ + if ((sfx_op == ATOM_OP_STAR && !a2->PR_int) || + pfx_op == ATOM_OP_PV_EQUAL || + a1->PR_int == a2->PR_int) + return _atom_compare_match(EQUAL, pfx_op); else if (a1->PR_int < a2->PR_int) - return OLDER; + return _atom_compare_match(OLDER, pfx_op); else - return NEWER; + return _atom_compare_match(NEWER, pfx_op); } int atom_compare_str(const char * const s1, const char * const s2); diff --git a/libq/atom_explode.c b/libq/atom_explode.c index 79d854c..8795706 100644 --- a/libq/atom_explode.c +++ b/libq/atom_explode.c @@ -1,7 +1,7 @@ /* * Copyright 2005-2008 Gentoo Foundation * Distributed under the terms of the GNU General Public License v2 - * $Header: /var/cvsroot/gentoo-projects/portage-utils/libq/atom_explode.c,v 1.26 2011/01/18 03:12:19 vapier Exp $ + * $Header: /var/cvsroot/gentoo-projects/portage-utils/libq/atom_explode.c,v 1.27 2013/04/29 04:38:16 vapier Exp $ * * Copyright 2005-2008 Ned Ludd - <solar@gentoo.org> * Copyright 2005-2008 Mike Frysinger - <vapier@gentoo.org> @@ -15,8 +15,23 @@ typedef struct { uint64_t sint; } atom_suffix; +const char * const atom_op_str[] = { "", ">", ">=", "=", "<=", "<", "~", "!", "!!", "*" }; +typedef enum { + /* */ ATOM_OP_NONE = 0, + /* > */ ATOM_OP_NEWER, + /* >= */ ATOM_OP_NEWER_EQUAL, + /* = */ ATOM_OP_EQUAL, + /* <= */ ATOM_OP_OLDER_EQUAL, + /* < */ ATOM_OP_OLDER, + /* ~ */ ATOM_OP_PV_EQUAL, + /* ! */ ATOM_OP_BLOCK, + /* !! */ ATOM_OP_BLOCK_HARD, + /* * */ ATOM_OP_STAR, +} atom_operator; + typedef struct { /* XXX: we don't provide PF ... */ + atom_operator pfx_op, sfx_op; char *CATEGORY; char *PN; unsigned int PR_int; @@ -59,6 +74,42 @@ depend_atom *atom_explode(const char *atom) ret->P = ptr + sizeof(*ret); ret->PVR = ret->P + slen + 1; ret->CATEGORY = ret->PVR + slen + 1 + 3; + + /* eat any prefix operators */ + switch (atom[0]) { + case '>': + ++atom; + if (atom[0] == '=') { + ++atom; + ret->pfx_op = ATOM_OP_NEWER_EQUAL; + } else + ret->pfx_op = ATOM_OP_NEWER; + break; + case '=': + ++atom; + ret->pfx_op = ATOM_OP_EQUAL; + break; + case '<': + ++atom; + if (atom[0] == '=') { + ++atom; + ret->pfx_op = ATOM_OP_OLDER_EQUAL; + } else + ret->pfx_op = ATOM_OP_OLDER; + break; + case '~': + ++atom; + ret->pfx_op = ATOM_OP_PV_EQUAL; + break; + case '!': + ++atom; + if (atom[0] == '!') { + ++atom; + ret->pfx_op = ATOM_OP_BLOCK_HARD; + } else + ret->pfx_op = ATOM_OP_BLOCK; + break; + } strcpy(ret->CATEGORY, atom); /* eat file name crap */ @@ -71,6 +122,15 @@ depend_atom *atom_explode(const char *atom) *ptr = '\0'; } + /* see if we have any suffix operators */ + if ((ptr = strrchr(ret->CATEGORY, '*')) != NULL) { + /* make sure it's the last byte */ + if (ptr[1] == '\0') { + ret->sfx_op = ATOM_OP_STAR; + *ptr = '\0'; + } + } + /* break up the CATEOGRY and PVR */ if ((ptr = strrchr(ret->CATEGORY, '/')) != NULL) { ret->PN = ptr + 1; @@ -1,7 +1,7 @@ /* * Copyright 2005-2008 Gentoo Foundation * Distributed under the terms of the GNU General Public License v2 - * $Header: /var/cvsroot/gentoo-projects/portage-utils/qatom.c,v 1.9 2013/04/22 04:36:28 vapier Exp $ + * $Header: /var/cvsroot/gentoo-projects/portage-utils/qatom.c,v 1.10 2013/04/29 04:38:16 vapier Exp $ * * Copyright 2005-2008 Ned Ludd - <solar@gentoo.org> * Copyright 2005-2008 Mike Frysinger - <vapier@gentoo.org> @@ -19,7 +19,7 @@ static const char * const qatom_opts_help[] = { COMMON_OPTS_HELP }; -static const char qatom_rcsid[] = "$Id: qatom.c,v 1.9 2013/04/22 04:36:28 vapier Exp $"; +static const char qatom_rcsid[] = "$Id: qatom.c,v 1.10 2013/04/29 04:38:16 vapier Exp $"; #define qatom_usage(ret) usage(ret, QATOM_FLAGS, qatom_long_opts, qatom_opts_help, lookup_applet_idx("qatom")) int qatom_main(int argc, char **argv) @@ -61,6 +61,10 @@ int qatom_main(int argc, char **argv) printf(" r%i", atom->PR_int); if (atom->SLOT) printf(" :%s", atom->SLOT); + if (verbose || atom->pfx_op != ATOM_OP_NONE) + printf(" %s", atom->pfx_op == ATOM_OP_NONE ? "-" : atom_op_str[atom->pfx_op]); + if (verbose || atom->sfx_op != ATOM_OP_NONE) + printf(" %s", atom->sfx_op == ATOM_OP_NONE ? "-" : atom_op_str[atom->sfx_op]); if (verbose > 1) printf(" %c", (atom->letter ? : '-')); putchar('\n'); diff --git a/tests/atom_compare/.cvsignore b/tests/atom_compare/.cvsignore index 162f1e7..5a05417 100644 --- a/tests/atom_compare/.cvsignore +++ b/tests/atom_compare/.cvsignore @@ -1,3 +1,4 @@ basic portage static +static.q diff --git a/tests/atom_compare/.gitignore b/tests/atom_compare/.gitignore index 162f1e7..5a05417 100644 --- a/tests/atom_compare/.gitignore +++ b/tests/atom_compare/.gitignore @@ -1,3 +1,4 @@ basic portage static +static.q diff --git a/tests/atom_compare/Makefile b/tests/atom_compare/Makefile index 3d0cae3..8151922 100644 --- a/tests/atom_compare/Makefile +++ b/tests/atom_compare/Makefile @@ -3,20 +3,27 @@ include ../subdir.mk all: test -test check: static portage +test check: static static.q portage diff -u $(s)/static.good $(b)/static + diff -u $(s)/static.q.good $(b)/static.q diff -u $(s)/static.good $(b)/portage +t = \ + set -f && \ + $(call mkdir,$(b)) && \ + $(realpath $(lastword $^)) $(1) `sed 's:\#.*::' $<` \ + > $(@:.tests=) + static: $(s)/static.tests $(atb)/q - mkdir -p $(b) - $(atb)/q atom -c `cat $<` > $(b)/static - #q atom -c `cat static.tests` > static + $(call t,atom -c) + +static.q: $(s)/static.q.tests $(atb)/q + $(call t,atom -c) portage: $(s)/static.tests $(s)/atom-compare.py - mkdir -p $(b) - ./atom-compare.py `cat $<` > $(b)/portage + $(call t) clean: - rm -f $(b)/static $(b)/portage + rm -f $(b)/static $(b)/static.q $(b)/portage .PHONY: all check clean test diff --git a/tests/atom_compare/atom-compare.py b/tests/atom_compare/atom-compare.py index 96f2f34..7a9ce89 100755 --- a/tests/atom_compare/atom-compare.py +++ b/tests/atom_compare/atom-compare.py @@ -2,20 +2,33 @@ import sys,portage -i=1 +i = 1 while i < len(sys.argv): - atom1 = sys.argv[i] - atom2 = sys.argv[i+1] - try: - ret = portage.pkgcmp(portage.pkgsplit(atom1), portage.pkgsplit(atom2)) - if ret == 1: - rel = ">" - elif ret == -1: - rel = "<" + atom1, atom2 = sys.argv[i:i + 2] + if atom2[0] in ('>', '<', '=', '~'): + if '/' not in atom1: + # Portage really wants a category. + a1 = 'c/' + atom1 + pfx = atom2[0] + if atom2[1] == '=': + pfx += atom2[1] + a2 = '%sc/%s' % (pfx, atom2[len(pfx):]) else: - rel = "==" - except: - rel = "!=" - pass - print("%s %s %s" % (atom1, rel, atom2)) + a1, a2 = atom1, atom2 + ret = portage.dep.match_from_list(a2, [a1]) + rel = '==' if ret else '!=' + else: + try: + pkg1 = portage.pkgsplit(atom1) + pkg2 = portage.pkgsplit(atom2) + ret = portage.pkgcmp(pkg1, pkg2) + if ret == 1: + rel = '>' + elif ret == -1: + rel = '<' + else: + rel = '==' + except Exception as e: + rel = '!=' + print('%s %s %s' % (atom1, rel, atom2)) i += 2 diff --git a/tests/atom_compare/static.good b/tests/atom_compare/static.good index c11a5cf..9061ae4 100644 --- a/tests/atom_compare/static.good +++ b/tests/atom_compare/static.good @@ -22,3 +22,33 @@ a-1_alpha_beta < a-1_alpha_beta1 a-1_alpha1_beta2_pre3_rc4_p5 == a-1_alpha1_beta2_pre3_rc4_p5 a-1.2.3.200702020000 == a-1.2.3.200702020000 a-1.2.3.200702020000 < a-1.2.3.200702020001 +a-1 == >a-0 +a-1 != >a-1 +a-1 != >a-2 +a-1 == >=a-0 +a-1 == >=a-1 +a-1 != >=a-2 +a-1 != =a-0 +a-1 == =a-1 +a-1 != =a-2 +a-1 != <a-0 +a-1 != <a-1 +a-1 == <a-2 +a-1 != <=a-0 +a-1 == <=a-1 +a-1 == <=a-2 +a-1 != ~a-0 +a-1 == ~a-1 +a-1 != ~a-2 +a-1-r1 == ~a-1-r0 +a-1-r1 == ~a-1-r1 +a-1-r1 == ~a-1-r2 +a-1 == =a-1* +a-1.0 == =a-1* +a-1z == =a-1* +a-1 != =a-1z* +a-1.2z == =a-1* +a-1 != =a-1.2z* +a-1_alpha1 == =a-1* +a-1 != =a-1_alpha1* +a-1_alpha-r1 == =a-1_alpha* diff --git a/tests/atom_compare/static.q.good b/tests/atom_compare/static.q.good new file mode 100644 index 0000000..08a6635 --- /dev/null +++ b/tests/atom_compare/static.q.good @@ -0,0 +1,7 @@ +a/b == b +a/b-1 == b +a-1 == =a-1.0* +a-1:1234 != a-1 +a-1:0 < a-2:0 +a-1:0 == a-1:0 +a-1_alpha1 != =a-1-r1* diff --git a/tests/atom_compare/static.q.tests b/tests/atom_compare/static.q.tests new file mode 100644 index 0000000..31b5fb5 --- /dev/null +++ b/tests/atom_compare/static.q.tests @@ -0,0 +1,12 @@ +# Certain atom matching styles that portage does not support +# but qatom accepts. Or I can't quite figure out how to get +# portage to do the compare. Not a big deal either way. +a/b b +a/b-1 b +a-1 =a-1.0* +a-1:1234 a-1 +a-1:0 a-2:0 +a-1:0 a-1:0 + +# In this case, it's because portage gets it wrong. #467826 +a-1_alpha1 =a-1-r1* diff --git a/tests/atom_compare/static.tests b/tests/atom_compare/static.tests index 89631b1..2f081c8 100644 --- a/tests/atom_compare/static.tests +++ b/tests/atom_compare/static.tests @@ -22,3 +22,33 @@ a-1_alpha_beta a-1_alpha_beta1 a-1_alpha1_beta2_pre3_rc4_p5 a-1_alpha1_beta2_pre3_rc4_p5 a-1.2.3.200702020000 a-1.2.3.200702020000 a-1.2.3.200702020000 a-1.2.3.200702020001 +a-1 >a-0 +a-1 >a-1 +a-1 >a-2 +a-1 >=a-0 +a-1 >=a-1 +a-1 >=a-2 +a-1 =a-0 +a-1 =a-1 +a-1 =a-2 +a-1 <a-0 +a-1 <a-1 +a-1 <a-2 +a-1 <=a-0 +a-1 <=a-1 +a-1 <=a-2 +a-1 ~a-0 +a-1 ~a-1 +a-1 ~a-2 +a-1-r1 ~a-1-r0 +a-1-r1 ~a-1-r1 +a-1-r1 ~a-1-r2 +a-1 =a-1* +a-1.0 =a-1* +a-1z =a-1* +a-1 =a-1z* +a-1.2z =a-1* +a-1 =a-1.2z* +a-1_alpha1 =a-1* +a-1 =a-1_alpha1* +a-1_alpha-r1 =a-1_alpha* diff --git a/tests/subdir.mk b/tests/subdir.mk index 03dba7d..96307a5 100644 --- a/tests/subdir.mk +++ b/tests/subdir.mk @@ -10,6 +10,8 @@ builddir = . srcdir = . endif +mkdir = $(if $(wildcard $(dir $(1))),:,mkdir -p "$(dir $(1))") + b = $(builddir) s = $(srcdir) atb = $(abs_top_builddir) |