aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2013-04-29 04:38:16 +0000
committerMike Frysinger <vapier@gentoo.org>2013-04-29 04:38:16 +0000
commit9ba7e8a90a1735ae016988c4983af8b78a3df203 (patch)
treed86391157bf220e09af37c358e4712e491afc612
parentqatom: check # of args before running main code (diff)
downloadportage-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.c155
-rw-r--r--libq/atom_explode.c62
-rw-r--r--qatom.c8
-rw-r--r--tests/atom_compare/.cvsignore1
-rw-r--r--tests/atom_compare/.gitignore1
-rw-r--r--tests/atom_compare/Makefile21
-rwxr-xr-xtests/atom_compare/atom-compare.py41
-rw-r--r--tests/atom_compare/static.good30
-rw-r--r--tests/atom_compare/static.q.good7
-rw-r--r--tests/atom_compare/static.q.tests12
-rw-r--r--tests/atom_compare/static.tests30
-rw-r--r--tests/subdir.mk2
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;
diff --git a/qatom.c b/qatom.c
index 7694fde..610b98e 100644
--- a/qatom.c
+++ b/qatom.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/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)