aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Groffen <grobian@gentoo.org>2019-04-07 22:15:31 +0200
committerFabian Groffen <grobian@gentoo.org>2019-04-07 22:15:31 +0200
commitf74766218c33e762e272f9f0129128a9f8ffd4a9 (patch)
tree117df1f80f3af16e4179c990c5d777ad2ebe5142
parentatoms: add proper support for blockers and USE dependencies (diff)
downloadportage-utils-f74766218c33e762e272f9f0129128a9f8ffd4a9.tar.gz
portage-utils-f74766218c33e762e272f9f0129128a9f8ffd4a9.tar.bz2
portage-utils-f74766218c33e762e272f9f0129128a9f8ffd4a9.zip
qdepends: rewrite to better match forward/backward dependencies
- dep: extract dependency functions into separate files for later reuse - by default, report all deps for all *DEPEND combined (duplicates removed) - allow listing per *DEPEND using -v, pretty-print and highlight the atoms seleted or queried for (-Q) - support reverse querying multiple atoms - make -Q output match forward output, highlight the match, to just print the match, use -q Bug: https://bugs.gentoo.org/682056 Signed-off-by: Fabian Groffen <grobian@gentoo.org>
-rw-r--r--TODO.md3
-rw-r--r--libq/Makefile.am1
-rw-r--r--libq/Makefile.in11
-rw-r--r--libq/dep.c334
-rw-r--r--libq/dep.h54
-rw-r--r--libq/set.c22
-rw-r--r--libq/set.h1
-rw-r--r--qdepends.c776
-rwxr-xr-xtests/qdepends/dotest11
-rw-r--r--tests/qdepends/list02.good2
-rw-r--r--tests/qdepends/list03.good6
-rw-r--r--tests/qdepends/list04.good6
-rw-r--r--tests/qdepends/list05.good16
-rw-r--r--tests/qdepends/list06.good2
-rw-r--r--tests/qdepends/list07.good2
-rw-r--r--tests/qdepends/list08.good2
16 files changed, 639 insertions, 610 deletions
diff --git a/TODO.md b/TODO.md
index 5ebd9ea..3841a8e 100644
--- a/TODO.md
+++ b/TODO.md
@@ -24,6 +24,9 @@
we end up getting just:<br>
`ACCEPT_LICENSE=" bar"`
+- q\_vdb\_foreach\_pkg should have variant that takes an atom (or just
+ cat?) to reduce search space
+
# Atoms
- only 32bit values are supported for revision (-r#)
diff --git a/libq/Makefile.am b/libq/Makefile.am
index 734a78f..765347f 100644
--- a/libq/Makefile.am
+++ b/libq/Makefile.am
@@ -7,6 +7,7 @@ QFILES = \
colors.c colors.h \
contents.c contents.h \
copy_file.c copy_file.h \
+ dep.c dep.h \
eat_file.c eat_file.h \
hash_fd.c hash_fd.h \
human_readable.c human_readable.h \
diff --git a/libq/Makefile.in b/libq/Makefile.in
index ab7012f..935747e 100644
--- a/libq/Makefile.in
+++ b/libq/Makefile.in
@@ -243,7 +243,7 @@ LTLIBRARIES = $(noinst_LTLIBRARIES)
libq_la_LIBADD =
am__objects_1 = libq_la-atom.lo libq_la-basename.lo libq_la-cache.lo \
libq_la-colors.lo libq_la-contents.lo libq_la-copy_file.lo \
- libq_la-eat_file.lo libq_la-hash_fd.lo \
+ libq_la-dep.lo libq_la-eat_file.lo libq_la-hash_fd.lo \
libq_la-human_readable.lo libq_la-md5_sha1_sum.lo \
libq_la-prelink.lo libq_la-profile.lo libq_la-rmspace.lo \
libq_la-safe_io.lo libq_la-scandirat.lo libq_la-set.lo \
@@ -1450,6 +1450,7 @@ QFILES = \
colors.c colors.h \
contents.c contents.h \
copy_file.c copy_file.h \
+ dep.c dep.h \
eat_file.c eat_file.h \
hash_fd.c hash_fd.h \
human_readable.c human_readable.h \
@@ -1537,6 +1538,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libq_la-colors.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libq_la-contents.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libq_la-copy_file.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libq_la-dep.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libq_la-eat_file.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libq_la-hash_fd.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libq_la-human_readable.Plo@am__quote@
@@ -1618,6 +1620,13 @@ libq_la-copy_file.lo: copy_file.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libq_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libq_la-copy_file.lo `test -f 'copy_file.c' || echo '$(srcdir)/'`copy_file.c
+libq_la-dep.lo: dep.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libq_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libq_la-dep.lo -MD -MP -MF $(DEPDIR)/libq_la-dep.Tpo -c -o libq_la-dep.lo `test -f 'dep.c' || echo '$(srcdir)/'`dep.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libq_la-dep.Tpo $(DEPDIR)/libq_la-dep.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='dep.c' object='libq_la-dep.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libq_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libq_la-dep.lo `test -f 'dep.c' || echo '$(srcdir)/'`dep.c
+
libq_la-eat_file.lo: eat_file.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libq_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libq_la-eat_file.lo -MD -MP -MF $(DEPDIR)/libq_la-eat_file.Tpo -c -o libq_la-eat_file.lo `test -f 'eat_file.c' || echo '$(srcdir)/'`eat_file.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libq_la-eat_file.Tpo $(DEPDIR)/libq_la-eat_file.Plo
diff --git a/libq/dep.c b/libq/dep.c
new file mode 100644
index 0000000..76d7b1e
--- /dev/null
+++ b/libq/dep.c
@@ -0,0 +1,334 @@
+/*
+ * Copyright 2005-2019 Gentoo Foundation
+ * Distributed under the terms of the GNU General Public License v2
+ *
+ * Copyright 2005-2010 Ned Ludd - <solar@gentoo.org>
+ * Copyright 2005-2014 Mike Frysinger - <vapier@gentoo.org>
+ * Copyright 2019- Fabian Groffen - <grobian@gentoo.org>
+ */
+
+#include "main.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <xalloc.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include "atom.h"
+#include "dep.h"
+#include "set.h"
+#include "xarray.h"
+#include "xasprintf.h"
+
+static const dep_node null_node = {
+ .type = DEP_NULL,
+};
+
+static void _dep_attach(dep_node *root, dep_node *attach_me, int type);
+static void _dep_burn_node(dep_node *node);
+
+static dep_node *
+_dep_grow_node(dep_type type, const char *info, size_t info_len)
+{
+ dep_node *ret;
+ size_t len;
+
+ if (type == DEP_OR || type == DEP_GROUP)
+ info = NULL;
+
+ len = sizeof(*ret);
+ if (info) {
+ if (!info_len)
+ info_len = strlen(info);
+ len += info_len + 1;
+ }
+ ret = xzalloc(len);
+
+ ret->type = type;
+ if (info) {
+ ret->info = ((char*)ret) + sizeof(*ret);
+ memcpy(ret->info, info, info_len);
+ if (type == DEP_NORM)
+ ret->atom = atom_explode(ret->info);
+ }
+
+ return ret;
+}
+
+static void
+_dep_burn_node(dep_node *node)
+{
+ assert(node);
+ if (node->info_on_heap)
+ free(node->info);
+ if (node->atom)
+ atom_implode(node->atom);
+ free(node);
+}
+
+enum {
+ _DEP_NEIGH = 1,
+ _DEP_CHILD = 2
+};
+
+static void
+_dep_attach(dep_node *root, dep_node *attach_me, int type)
+{
+ if (type == _DEP_NEIGH) {
+ if (!root->neighbor) {
+ root->neighbor = attach_me;
+ attach_me->parent = root->parent;
+ } else
+ _dep_attach(root->neighbor, attach_me, _DEP_NEIGH);
+ } else {
+ if (!root->children) {
+ root->children = attach_me;
+ attach_me->parent = root;
+ } else
+ _dep_attach(root->children, attach_me, _DEP_NEIGH);
+ }
+}
+
+dep_node *
+dep_grow_tree(const char *depend)
+{
+ bool saw_whitespace;
+ signed long paren_balanced;
+ const char *ptr, *word;
+ int curr_attach;
+ dep_node *ret, *curr_node, *new_node;
+ dep_type prev_type;
+
+ ret = curr_node = new_node = NULL;
+ prev_type = DEP_NULL;
+ paren_balanced = 0;
+ curr_attach = _DEP_NEIGH;
+ word = NULL;
+
+#define _maybe_consume_word(t) \
+ do { \
+ if (!word) break; \
+ new_node = _dep_grow_node(t, word, ptr-word); \
+ if (!ret) \
+ ret = curr_node = new_node; \
+ else { \
+ _dep_attach(curr_node, new_node, curr_attach); \
+ curr_attach = _DEP_NEIGH; \
+ curr_node = new_node; \
+ } \
+ prev_type = t; \
+ word = NULL; \
+ } while (0)
+
+ saw_whitespace = true;
+ for (ptr = depend; *ptr; ++ptr) {
+ if (isspace(*ptr)) {
+ saw_whitespace = true;
+ _maybe_consume_word(DEP_NORM);
+ continue;
+ }
+
+ switch (*ptr) {
+ case '?': {
+ if (word == NULL) {
+ warnf("Found a ? but no USE flag");
+ goto error_out;
+ }
+ _maybe_consume_word(DEP_USE);
+ curr_attach = _DEP_CHILD;
+ continue;
+ }
+ case '|': {
+ if (!saw_whitespace)
+ break;
+ if (ptr[1] != '|') {
+ warnf("Found a | but not ||");
+ goto error_out;
+ }
+ word = ptr++;
+ _maybe_consume_word(DEP_OR);
+ curr_attach = _DEP_CHILD;
+ continue;
+ }
+ case '(': {
+ ++paren_balanced;
+ if (!saw_whitespace)
+ break;
+ if (prev_type == DEP_OR || prev_type == DEP_USE) {
+ _maybe_consume_word(DEP_NORM);
+ prev_type = DEP_NULL;
+ } else {
+ if (word) {
+ warnf("New group has word in queue");
+ goto error_out;
+ }
+ word = ptr;
+ _maybe_consume_word(DEP_GROUP);
+ curr_attach = _DEP_CHILD;
+ }
+ break;
+ }
+ case ')': {
+ --paren_balanced;
+ if (!saw_whitespace)
+ break;
+ _maybe_consume_word(DEP_NORM);
+
+ if (curr_node->parent == NULL) {
+ warnf("Group lacks a parent");
+ goto error_out;
+ }
+ curr_node = curr_node->parent;
+ curr_attach = _DEP_NEIGH;
+ break;
+ }
+ default:
+ if (!word)
+ word = ptr;
+ }
+ saw_whitespace = false;
+
+ /* fall through to the paren failure below */
+ if (paren_balanced < 0)
+ break;
+ }
+
+ if (paren_balanced != 0) {
+ warnf("Parenthesis unbalanced");
+ goto error_out;
+ }
+
+ /* if the depend buffer wasnt terminated with a space,
+ * we may have a word sitting in the buffer to consume */
+ _maybe_consume_word(DEP_NORM);
+
+#undef _maybe_consume_word
+
+ return ret ? : xmemdup(&null_node, sizeof(null_node));
+
+error_out:
+ warnf("DEPEND: %s", depend);
+ if (ret) {
+ dep_dump_tree(ret);
+ dep_burn_tree(ret);
+ }
+ return NULL;
+}
+
+void
+dep_print_tree(
+ FILE *fp,
+ const dep_node *root,
+ size_t space,
+ array_t *hlatoms,
+ const char *hlcolor,
+ int verbose)
+{
+ size_t s;
+ int indent = 4; /* Gentoo 4-wide indent standard */
+ depend_atom *d = NULL;
+
+ assert(root);
+ if (root->type == DEP_NULL)
+ goto this_node_sucks;
+
+ for (s = space; s; --s)
+ fprintf(fp, "%*s", indent, "");
+
+ if (verbose > 0)
+ fprintf(fp, "Node [%s]: ", _dep_names[root->type]);
+ /*printf("Node %p [%s] %p %p %p: ", root, _dep_names[root->type], root->parent, root->neighbor, root->children);*/
+ if (root->type == DEP_OR)
+ fprintf(fp, "|| (");
+ if (root->info) {
+ if (hlatoms != NULL && root->type == DEP_NORM) {
+ size_t i;
+ depend_atom *m;
+ char *oslot;
+
+ d = root->atom;
+ d->pfx_op = d->sfx_op = ATOM_OP_NONE;
+
+ array_for_each(hlatoms, i, m) {
+ oslot = d->SLOT;
+ if (m->SLOT == NULL)
+ d->SLOT = NULL;
+
+ if (atom_compare(m, d) == EQUAL) {
+ m = NULL;
+ break;
+ }
+ d->SLOT = oslot;
+ }
+
+ if (m == NULL) { /* match found */
+ fprintf(fp, "%s%s%s", hlcolor, root->info, NORM);
+ } else {
+ fprintf(fp, "%s", root->info);
+ }
+ } else {
+ fprintf(fp, "%s", root->info);
+ }
+ /* If there is only one child, be nice to one-line: foo? ( pkg ) */
+ if (root->type == DEP_USE)
+ fprintf(fp, "? (");
+ }
+ fprintf(fp, "\n");
+
+ if (root->children)
+ dep_print_tree(fp, root->children, space+1, hlatoms, hlcolor, verbose);
+
+ if (root->type == DEP_OR || root->type == DEP_USE) {
+ for (s = space; s; --s)
+ fprintf(fp, "%*s", indent, "");
+ fprintf(fp, ")\n");
+ }
+ this_node_sucks:
+ if (root->neighbor)
+ dep_print_tree(fp, root->neighbor, space, hlatoms, hlcolor, verbose);
+}
+
+void
+dep_burn_tree(dep_node *root)
+{
+ assert(root);
+ if (root->children)
+ dep_burn_tree(root->children);
+ if (root->neighbor)
+ dep_burn_tree(root->neighbor);
+ _dep_burn_node(root);
+}
+
+void
+dep_prune_use(dep_node *root, set *use)
+{
+ if (root->neighbor)
+ dep_prune_use(root->neighbor, use);
+ if (root->type == DEP_USE) {
+ bool invert = (root->info[0] == '!' ? 1 : 0);
+ bool notfound = contains_set(root->info + (invert ? 1 : 0), use);
+
+ if (notfound ^ invert) {
+ root->type = DEP_NULL;
+ return;
+ }
+ }
+ if (root->children)
+ dep_prune_use(root->children, use);
+}
+
+void
+dep_flatten_tree(const dep_node *root, array_t *out)
+{
+ if (root->type != DEP_NULL) {
+ if (root->type == DEP_NORM)
+ xarraypush_ptr(out, root->atom);
+ if (root->children)
+ dep_flatten_tree(root->children, out);
+ }
+ if (root->neighbor)
+ dep_flatten_tree(root->neighbor, out);
+}
diff --git a/libq/dep.h b/libq/dep.h
new file mode 100644
index 0000000..1055d29
--- /dev/null
+++ b/libq/dep.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2005-2019 Gentoo Foundation
+ * Distributed under the terms of the GNU General Public License v2
+ */
+
+#ifndef _DEP_H
+#define _DEP_H 1
+
+#include "atom.h"
+#include "colors.h"
+#include "set.h"
+#include "xarray.h"
+
+typedef enum {
+ DEP_NULL = 0,
+ DEP_NORM = 1,
+ DEP_USE = 2,
+ DEP_OR = 3,
+ DEP_GROUP = 4
+} dep_type;
+
+static const char * const _dep_names[] = {
+ "NULL",
+ "NORM",
+ "USE",
+ "OR",
+ "GROUP"
+};
+
+struct _dep_node {
+ dep_type type;
+ char *info;
+ char info_on_heap;
+ depend_atom *atom;
+ struct _dep_node *parent;
+ struct _dep_node *neighbor;
+ struct _dep_node *children;
+};
+typedef struct _dep_node dep_node;
+
+/* prototypes */
+#ifdef NDEBUG
+# define dep_dump_tree(r)
+#else
+# define dep_dump_tree(r) dep_print_tree(stdout, r, 0, NULL, NORM, 0)
+#endif
+
+dep_node *dep_grow_tree(const char *depend);
+void dep_print_tree(FILE *fp, const dep_node *root, size_t space, array_t *m, const char *c, int verbose);
+void dep_burn_tree(dep_node *root);
+void dep_prune_use(dep_node *root, set *use);
+void dep_flatten_tree(const dep_node *root, array_t *out);
+
+#endif
diff --git a/libq/set.c b/libq/set.c
index 7adbce7..de60410 100644
--- a/libq/set.c
+++ b/libq/set.c
@@ -72,6 +72,7 @@ add_set_unique(const char *name, set *q, bool *unique)
int pos;
elem *ll;
elem *w;
+ bool uniq = false;
if (q == NULL)
q = create_set();
@@ -85,13 +86,13 @@ add_set_unique(const char *name, set *q, bool *unique)
ll->next = NULL;
ll->name = mname;
ll->hash = hash;
- *unique = true;
+ uniq = true;
} else {
ll = NULL;
for (w = q->buckets[pos]; w != NULL; ll = w, w = w->next) {
if (w->hash == hash && strcmp(w->name, mname) == 0) {
free(mname);
- *unique = false;
+ uniq = false;
break;
}
}
@@ -100,12 +101,14 @@ add_set_unique(const char *name, set *q, bool *unique)
ll->next = NULL;
ll->name = mname;
ll->hash = hash;
- *unique = true;
+ uniq = true;
}
}
- if (*unique)
+ if (uniq)
q->len++;
+ if (unique)
+ *unique = uniq;
return q;
}
@@ -199,7 +202,7 @@ list_set(set *q, char ***l)
/* clear out a set */
void
-free_set(set *q)
+clear_set(set *q)
{
int i;
elem *w;
@@ -211,7 +214,16 @@ free_set(set *q)
free(w->name);
free(w);
}
+ q->buckets[i] = NULL;
}
+ q->len = 0;
+}
+
+/* clear and free a set */
+void
+free_set(set *q)
+{
+ clear_set(q);
free(q);
}
diff --git a/libq/set.h b/libq/set.h
index 27e30ad..7ca5f65 100644
--- a/libq/set.h
+++ b/libq/set.h
@@ -32,5 +32,6 @@ bool contains_set(char *s, set *q);
set *del_set(char *s, set *q, bool *removed);
size_t list_set(set *q, char ***l);
void free_set(set *q);
+void clear_set(set *q);
#endif
diff --git a/qdepends.c b/qdepends.c
index ca82f08..df3434e 100644
--- a/qdepends.c
+++ b/qdepends.c
@@ -15,34 +15,31 @@
#include <assert.h>
#include "atom.h"
+#include "dep.h"
#include "set.h"
#include "vdb.h"
#include "xarray.h"
#include "xasprintf.h"
#include "xregex.h"
-#define QDEPENDS_FLAGS "drpbafNk:Q:" COMMON_FLAGS
+#define QDEPENDS_FLAGS "drpbfNQu" COMMON_FLAGS
static struct option const qdepends_long_opts[] = {
{"depend", no_argument, NULL, 'd'},
{"rdepend", no_argument, NULL, 'r'},
{"pdepend", no_argument, NULL, 'p'},
{"bdepend", no_argument, NULL, 'b'},
- {"key", a_argument, NULL, 'k'},
- {"query", a_argument, NULL, 'Q'},
+ {"query", no_argument, NULL, 'Q'},
{"name-only", no_argument, NULL, 'N'},
- {"all", no_argument, NULL, 'a'},
{"format", no_argument, NULL, 'f'},
COMMON_LONG_OPTS
};
static const char * const qdepends_opts_help[] = {
- "Show DEPEND info (default)",
+ "Show DEPEND info",
"Show RDEPEND info",
"Show PDEPEND info",
"Show BDEPEND info",
- "User defined vdb key",
"Query reverse deps",
"Only show package name",
- "Show all DEPEND info",
"Pretty format specified depend strings",
COMMON_OPTS_HELP
};
@@ -51,278 +48,31 @@ static const char * const qdepends_opts_help[] = {
static char qdep_name_only = 0;
/* structures / types / etc ... */
-typedef enum {
- DEP_NULL = 0,
- DEP_NORM = 1,
- DEP_USE = 2,
- DEP_OR = 3,
- DEP_GROUP = 4
-} dep_type;
-static const char * const _dep_names[] = { "NULL", "NORM", "USE", "OR", "GROUP" };
-
-struct _dep_node {
- dep_type type;
- char *info;
- char info_on_heap;
- depend_atom *atom;
- struct _dep_node *parent;
- struct _dep_node *neighbor;
- struct _dep_node *children;
-};
-typedef struct _dep_node dep_node;
-
-static const dep_node null_node = {
- .type = DEP_NULL,
+struct qdepends_opt_state {
+ unsigned char qmode;
+ array_t *atoms;
+ array_t *deps;
+ set *udeps;
+ char *depend;
+ size_t depend_len;
};
-/* prototypes */
-#ifdef NDEBUG
-# define dep_dump_tree(r)
-#else
-# define dep_dump_tree(r) _dep_print_tree(stdout, r, 0)
-#endif
-static void _dep_print_tree(FILE *fp, const dep_node *root, size_t space);
-static void dep_burn_tree(dep_node *root);
-static char *dep_flatten_tree(const dep_node *root);
-static void _dep_attach(dep_node *root, dep_node *attach_me, int type);
-static void _dep_burn_node(dep_node *node);
-
-#ifdef EBUG
-static void
-print_word(const char *ptr, size_t num)
-{
- while (num--)
- printf("%c", *ptr++);
- printf("\n");
-}
-#endif
-
-static dep_node *
-_dep_grow_node(dep_type type, const char *info, size_t info_len)
-{
- dep_node *ret;
- size_t len;
-
- if (type == DEP_OR || type == DEP_GROUP)
- info = NULL;
-
- len = sizeof(*ret);
- if (info) {
- if (!info_len)
- info_len = strlen(info);
- len += info_len + 1;
- }
- ret = xzalloc(len);
-
- ret->type = type;
- if (info) {
- ret->info = ((char*)ret) + sizeof(*ret);
- memcpy(ret->info, info, info_len);
- if (type == DEP_NORM)
- ret->atom = atom_explode(info);
- }
-
- return ret;
-}
-
-static void
-_dep_burn_node(dep_node *node)
-{
- assert(node);
- if (node->info_on_heap) free(node->info);
- if (node->atom) atom_implode(node->atom);
- free(node);
-}
-
-enum {
- _DEP_NEIGH = 1,
- _DEP_CHILD = 2
+#define QMODE_DEPEND (1<<0)
+#define QMODE_RDEPEND (1<<1)
+#define QMODE_PDEPEND (1<<2)
+#define QMODE_BDEPEND (1<<3)
+#define QMODE_REVERSE (1<<7)
+
+const char *depend_files[] = { /* keep *DEPEND aligned with above defines */
+ /* 0 */ "DEPEND",
+ /* 1 */ "RDEPEND",
+ /* 2 */ "PDEPEND",
+ /* 3 */ "BDEPEND",
+ /* 4 */ NULL
};
-static void
-_dep_attach(dep_node *root, dep_node *attach_me, int type)
-{
- if (type == _DEP_NEIGH) {
- if (!root->neighbor) {
- root->neighbor = attach_me;
- attach_me->parent = root->parent;
- } else
- _dep_attach(root->neighbor, attach_me, _DEP_NEIGH);
- } else {
- if (!root->children) {
- root->children = attach_me;
- attach_me->parent = root;
- } else
- _dep_attach(root->children, attach_me, _DEP_NEIGH);
- }
-}
-
-static dep_node *
-dep_grow_tree(const char *depend)
-{
- bool saw_whitespace;
- signed long paren_balanced;
- const char *ptr, *word;
- int curr_attach;
- dep_node *ret, *curr_node, *new_node;
- dep_type prev_type;
-
- ret = curr_node = new_node = NULL;
- prev_type = DEP_NULL;
- paren_balanced = 0;
- curr_attach = _DEP_NEIGH;
- word = NULL;
-
-#define _maybe_consume_word(t) \
- do { \
- if (!word) break; \
- new_node = _dep_grow_node(t, word, ptr-word); \
- if (!ret) \
- ret = curr_node = new_node; \
- else { \
- _dep_attach(curr_node, new_node, curr_attach); \
- curr_attach = _DEP_NEIGH; \
- curr_node = new_node; \
- } \
- prev_type = t; \
- word = NULL; \
- } while (0)
-
- saw_whitespace = true;
- for (ptr = depend; *ptr; ++ptr) {
- if (isspace(*ptr)) {
- saw_whitespace = true;
- _maybe_consume_word(DEP_NORM);
- continue;
- }
-
- switch (*ptr) {
- case '?': {
- if (word == NULL) {
- warnf("Found a ? but no USE flag");
- goto error_out;
- }
- _maybe_consume_word(DEP_USE);
- curr_attach = _DEP_CHILD;
- continue;
- }
- case '|': {
- if (!saw_whitespace)
- break;
- if (ptr[1] != '|') {
- warnf("Found a | but not ||");
- goto error_out;
- }
- word = ptr++;
- _maybe_consume_word(DEP_OR);
- curr_attach = _DEP_CHILD;
- continue;
- }
- case '(': {
- ++paren_balanced;
- if (!saw_whitespace)
- break;
- if (prev_type == DEP_OR || prev_type == DEP_USE) {
- _maybe_consume_word(DEP_NORM);
- prev_type = DEP_NULL;
- } else {
- if (word) {
- warnf("New group has word in queue");
- goto error_out;
- }
- word = ptr;
- _maybe_consume_word(DEP_GROUP);
- curr_attach = _DEP_CHILD;
- }
- break;
- }
- case ')': {
- --paren_balanced;
- if (!saw_whitespace)
- break;
- _maybe_consume_word(DEP_NORM);
-
- if (curr_node->parent == NULL) {
- warnf("Group lacks a parent");
- goto error_out;
- }
- curr_node = curr_node->parent;
- curr_attach = _DEP_NEIGH;
- break;
- }
- default:
- if (!word)
- word = ptr;
- }
- saw_whitespace = false;
-
- /* fall through to the paren failure below */
- if (paren_balanced < 0)
- break;
- }
-
- if (paren_balanced != 0) {
- warnf("Parenthesis unbalanced");
- goto error_out;
- }
-
- /* if the depend buffer wasnt terminated with a space,
- * we may have a word sitting in the buffer to consume */
- _maybe_consume_word(DEP_NORM);
-
-#undef _maybe_consume_word
-
- return ret ? : xmemdup(&null_node, sizeof(null_node));
-
-error_out:
- warnf("DEPEND: %s", depend);
- if (ret) {
- dep_dump_tree(ret);
- dep_burn_tree(ret);
- }
- return NULL;
-}
-
-static void
-_dep_print_tree(FILE *fp, const dep_node *root, size_t space)
-{
- size_t s;
-
- assert(root);
- if (root->type == DEP_NULL)
- goto this_node_sucks;
-
- for (s = space; s; --s)
- fprintf(fp, "\t");
-
- if (verbose > 1)
- fprintf(fp, "Node [%s]: ", _dep_names[root->type]);
- /*printf("Node %p [%s] %p %p %p: ", root, _dep_names[root->type], root->parent, root->neighbor, root->children);*/
- if (root->type == DEP_OR)
- fprintf(fp, "|| (");
- if (root->info) {
- fprintf(fp, "%s", root->info);
- /* If there is only one child, be nice to one-line: foo? ( pkg ) */
- if (root->type == DEP_USE)
- fprintf(fp, "? (");
- }
- fprintf(fp, "\n");
-
- if (root->children)
- _dep_print_tree(fp, root->children, space+1);
-
- if (root->type == DEP_OR || root->type == DEP_USE) {
- for (s = space; s; --s)
- fprintf(fp, "\t");
- fprintf(fp, ")\n");
- }
- this_node_sucks:
- if (root->neighbor)
- _dep_print_tree(fp, root->neighbor, space);
-}
-
static bool
-dep_print_depend(FILE *fp, const char *depend)
+qdepends_print_depend(FILE *fp, const char *depend)
{
dep_node *dep_tree;
@@ -333,7 +83,7 @@ dep_print_depend(FILE *fp, const char *depend)
if (!quiet)
fprintf(fp, "DEPEND=\"\n");
- _dep_print_tree(fp, dep_tree, 1);
+ dep_print_tree(fp, dep_tree, 1, NULL, NORM, verbose > 1);
dep_burn_tree(dep_tree);
if (!quiet)
@@ -342,346 +92,210 @@ dep_print_depend(FILE *fp, const char *depend)
return true;
}
-static void
-dep_burn_tree(dep_node *root)
-{
- assert(root);
- if (root->children) dep_burn_tree(root->children);
- if (root->neighbor) dep_burn_tree(root->neighbor);
- _dep_burn_node(root);
-}
-
-static void
-dep_prune_use(dep_node *root, const char *use)
-{
- if (root->neighbor) dep_prune_use(root->neighbor, use);
- if (root->type == DEP_USE) {
- char *useflag = NULL;
- int notfound, invert = (root->info[0] == '!' ? 1 : 0);
- xasprintf(&useflag, " %s ", root->info+invert);
- notfound = (strstr(use, useflag) == NULL ? 1 : 0);
- free(useflag);
- if (notfound ^ invert) {
- root->type = DEP_NULL;
- return;
- }
- }
- if (root->children) dep_prune_use(root->children, use);
-}
-
-static char *
-_dep_flatten_tree(const dep_node *root, char *buf)
-{
- if (root->type != DEP_NULL) {
- if (root->type == DEP_NORM)
- buf += sprintf(buf, " %s", root->info);
- if (root->children)
- buf = _dep_flatten_tree(root->children, buf);
- }
- if (root->neighbor)
- buf = _dep_flatten_tree(root->neighbor, buf);
- return buf;
-}
-
-static char *
-dep_flatten_tree(const dep_node *root)
-{
- static char flat[1024 * 1024];
- char *buf = _dep_flatten_tree(root, flat);
- if (buf == flat) {
- /* all the nodes were squashed ... for example:
- * USE=-selinux RDEPEND="selinux? ( sys-libs/libselinux )"
- */
- return NULL;
- }
- return flat + 1;
-}
-
-struct qdepends_opt_state {
- array_t *atoms;
- const char *depend_file;
- const char *query;
-};
-
static int
-qdepends_main_vdb_cb(q_vdb_pkg_ctx *pkg_ctx, void *priv)
+qdepends_results_cb(q_vdb_pkg_ctx *pkg_ctx, void *priv)
{
struct qdepends_opt_state *state = priv;
const char *catname = pkg_ctx->cat_ctx->name;
const char *pkgname = pkg_ctx->name;
- size_t i, len;
- int ret;
- char *ptr;
+ depend_atom *atom;
+ depend_atom *datom;
+ depend_atom *fatom;
+ bool firstmatch = false;
char buf[_Q_PATH_MAX];
- static char *depend, *use;
- static size_t depend_len, use_len;
- depend_atom *atom, *datom;
+ const char **dfile;
+ size_t i;
+ size_t n;
+ size_t m;
+ int ret = 0;
dep_node *dep_tree;
-
- datom = NULL;
- ret = 0;
-
- /* see if this cat/pkg is requested */
- array_for_each(state->atoms, i, atom) {
- bool matched = false;
- snprintf(buf, sizeof(buf), "%s/%s", catname, pkgname);
- datom = atom_explode(buf);
- if (datom) {
- matched = (atom_compare(atom, datom) == EQUAL);
- if (matched)
- goto matched;
+ char **d;
+
+ /* matrix consists of:
+ * - QMODE_*DEPEND
+ * - QMODE_REVERSE or not
+ *
+ * REVERSE vs forward mode requires a different search strategy,
+ * *DEPEND alters the search somewhat and affects results printing.
+ */
+
+ snprintf(buf, sizeof(buf), "%s/%s", catname, pkgname);
+ datom = atom_explode(buf);
+ if (datom == NULL)
+ return ret;
+
+ if ((state->qmode & QMODE_REVERSE) == 0) {
+ /* see if this cat/pkg is requested */
+ array_for_each(state->atoms, i, atom) {
+ if (atom_compare(atom, datom) == EQUAL) {
+ atom = NULL;
+ break;
+ }
}
- atom_implode(datom);
- }
- return ret;
- matched:
- if (!q_vdb_pkg_eat(pkg_ctx, state->depend_file, &depend, &depend_len))
- goto done;
-
- dep_tree = dep_grow_tree(depend);
- if (dep_tree == NULL)
- goto done;
-
- if (qdep_name_only)
- printf("%s%s/%s%s%s: ", BOLD, catname, BLUE, atom->PN, NORM);
- else
- printf("%s%s/%s%s%s: ", BOLD, catname, BLUE, pkgname, NORM);
-
- if (!q_vdb_pkg_eat(pkg_ctx, "USE", &use, &use_len)) {
- warn("Could not eat_file(%s), you'll prob have incorrect output", buf);
- } else {
- for (ptr = use; *ptr; ++ptr)
- if (*ptr == '\n' || *ptr == '\t')
- *ptr = ' ';
- len = ptr - use;
- if (len + 1 >= use_len) {
- use_len += BUFSIZE;
- use = xrealloc(use, use_len);
+ /* nothing matched */
+ if (atom != NULL) {
+ atom_implode(datom);
+ return ret;
}
- use[len] = ' ';
- use[len+1] = '\0';
- memmove(use+1, use, len);
- use[0] = ' ';
-
- dep_prune_use(dep_tree, use);
- }
-
- /*dep_dump_tree(dep_tree);*/
- ptr = dep_flatten_tree(dep_tree);
- printf("%s\n", (ptr == NULL ? "" : ptr));
-
- dep_burn_tree(dep_tree);
-
- ret = 1;
- done:
- atom_implode(datom);
- return ret;
-}
+ ret = 1;
-static int
-qdepends_vdb_deep_cb(q_vdb_pkg_ctx *pkg_ctx, void *priv)
-{
- struct qdepends_opt_state *state = priv;
- const char *catname = pkg_ctx->cat_ctx->name;
- const char *pkgname = pkg_ctx->name;
- size_t len;
- char *ptr;
- char qbuf[_Q_PATH_MAX];
- static char *depend, *use;
- static size_t depend_len, use_len;
- dep_node *dep_tree;
- int ret;
- regex_t preg;
- regmatch_t match;
- depend_atom *aq;
- depend_atom *as;
- depend_atom *ac;
- char firstmatch = 0;
- char *sslot;
-
- if (!q_vdb_pkg_eat(pkg_ctx, state->depend_file, &depend, &depend_len))
- return 0;
-
- dep_tree = dep_grow_tree(depend);
- if (dep_tree == NULL)
- return 0;
-
- if (q_vdb_pkg_eat(pkg_ctx, "USE", &use, &use_len))
- use[0] = '\0';
-
- for (ptr = use; *ptr; ++ptr)
- if (*ptr == '\n' || *ptr == '\t')
- *ptr = ' ';
- len = ptr - use;
- if (len + 1 >= use_len) {
- use_len += BUFSIZE;
- use = xrealloc(use, use_len);
+ printf("%s%s/%s%s%s:", BOLD, catname, BLUE,
+ qdep_name_only ? datom->PN : pkgname, NORM);
}
- use[len] = ' ';
- use[len+1] = '\0';
- memmove(use+1, use, len);
- use[0] = ' ';
- dep_prune_use(dep_tree, use);
+ xarrayfree_int(state->deps);
+ clear_set(state->udeps);
- if ((ptr = dep_flatten_tree(dep_tree)) == NULL) {
- dep_burn_tree(dep_tree);
- return 1;
- }
-
- snprintf(qbuf, sizeof(qbuf), "%s/%s", catname, pkgname);
- as = atom_explode(qbuf);
- if (!as) {
- dep_burn_tree(dep_tree);
- return 1;
- }
-
- aq = atom_explode(state->query);
- if (!aq) {
- /* "fall" back to old behaviour of just performing an extended
- * regular expression match */
- if (wregcomp(&preg, state->query, REG_EXTENDED) != 0) {
- dep_burn_tree(dep_tree);
- return 1;
- }
- }
+ dfile = depend_files;
+ for (i = QMODE_DEPEND; i <= QMODE_BDEPEND; i <<= 1, dfile++) {
+ if (!(state->qmode & i))
+ continue;
+ if (!q_vdb_pkg_eat(pkg_ctx, *dfile,
+ &state->depend, &state->depend_len))
+ continue;
- match.rm_eo = 0;
- firstmatch = 1;
- do { /* find all matches */
- if (!aq) {
- ret = regexec(&preg, ptr + match.rm_eo, 1, &match, 0);
- } else {
- char *loc;
- ret = -1;
- snprintf(qbuf, sizeof(qbuf), "%s%s%s",
- aq->CATEGORY ? aq->CATEGORY : "",
- aq->CATEGORY ? "/" : "",
- aq->PN);
- if ((loc = strstr(ptr + match.rm_eo, qbuf)) != NULL) {
- ret = 0;
- match.rm_so = loc - ptr;
- match.rm_eo = match.rm_so + strlen(qbuf);
- }
- }
- if (ret != 0)
- break;
-
- /* find the boundaries for matched atom, dep specifications can
- * include built-with-use deps using [xxx] notation, so ensure
- * we exclude that as part of the atom */
- while (match.rm_so > 0 && !isspace(ptr[match.rm_so - 1]))
- match.rm_so--;
- while (ptr[match.rm_eo] != '\0' && ptr[match.rm_eo] != '[' &&
- !isspace(ptr[match.rm_eo]))
- match.rm_eo++;
-
- snprintf(qbuf, sizeof(qbuf), "%.*s",
- (int)(match.rm_eo - match.rm_so),
- ptr + match.rm_so);
- ac = atom_explode(qbuf);
-
- /* drop SLOT when not present in aq so we can match atoms
- * regardless */
- sslot = ac->SLOT;
- if (aq->SLOT == NULL && ac->SLOT != NULL)
- ac->SLOT = NULL;
- ret = atom_compare(ac, aq);
- ac->SLOT = sslot;
- if (ret != EQUAL) {
- atom_implode(ac);
- break;
- }
+ dep_tree = dep_grow_tree(state->depend);
+ if (dep_tree == NULL)
+ continue;
- if (firstmatch == 1) {
- firstmatch = 0;
- printf("%s%s/%s%s%s%c", BOLD, catname, BLUE,
- qdep_name_only ? as->PN : pkgname, NORM,
- verbose ? ':' : '\n');
- }
+ dep_flatten_tree(dep_tree, state->deps);
if (verbose) {
- printf(" ");
- if (ac) {
- printf("%s", atom_op_str[ac->pfx_op]);
- if (ac->CATEGORY)
- printf("%s/", ac->CATEGORY);
- printf("%s", ac->P);
- if (ac->PR_int)
- printf("-r%i", ac->PR_int);
- printf("%s", atom_op_str[ac->sfx_op]);
- if (ac->SLOT)
- printf(":%s", ac->SLOT);
- atom_implode(ac);
+ if (state->qmode & QMODE_REVERSE) {
+ array_for_each(state->atoms, m, atom) {
+ array_for_each(state->deps, n, fatom) {
+ if (atom_compare(atom, fatom) == EQUAL) {
+ fatom = NULL;
+ break;
+ }
+ }
+ if (fatom == NULL) {
+ atom = NULL;
+ break;
+ }
+ }
+ if (atom == NULL) {
+ ret = 1;
+
+ if (!firstmatch) {
+ printf("%s%s/%s%s%s:",
+ BOLD, catname, BLUE,
+ qdep_name_only ? datom->PN : pkgname, NORM);
+ }
+ firstmatch = true;
+
+ printf("\n%s=\"\n", *dfile);
+ dep_print_tree(stdout, dep_tree, 1, state->atoms,
+ RED, verbose > 1);
+ printf("\"");
+ }
} else {
- printf("%s", qbuf);
+ printf("\n%s=\"\n", *dfile);
+ dep_print_tree(stdout, dep_tree, 1, state->deps,
+ GREEN, verbose > 1);
+ printf("\"");
}
} else {
- /* if not verbose, we don't care about any extra matches */
- atom_implode(ac);
- break;
+ if (state->qmode & QMODE_REVERSE) {
+ array_for_each(state->deps, m, atom) {
+ array_for_each(state->atoms, n, fatom) {
+ if (atom_compare(atom, fatom) == EQUAL) {
+ fatom = NULL;
+ break;
+ }
+ }
+ if (fatom == NULL) {
+ ret = 1;
+
+ if (!firstmatch) {
+ printf("%s%s/%s%s%s%s",
+ BOLD, catname, BLUE,
+ qdep_name_only ? datom->PN : pkgname, NORM,
+ quiet ? "" : ":");
+ }
+ firstmatch = true;
+
+ snprintf(buf, sizeof(buf), "%s%s%s",
+ RED, atom_to_string(atom), NORM);
+ add_set_unique(buf, state->udeps, NULL);
+ } else if (!quiet) {
+ add_set_unique(atom_to_string(atom),
+ state->udeps, NULL);
+ }
+ }
+ } else {
+ array_for_each(state->deps, m, atom)
+ add_set_unique(atom_to_string(atom), state->udeps, NULL);
+ }
}
- } while (1);
- if (verbose && firstmatch == 0)
+
+ xarrayfree_int(state->deps);
+ dep_burn_tree(dep_tree);
+ }
+ if (verbose && ret == 1)
printf("\n");
- if (!aq) {
- regfree(&preg);
- } else {
- atom_implode(aq);
+ if (!verbose) {
+ if ((state->qmode & QMODE_REVERSE) == 0 || ret == 1) {
+ for (n = list_set(state->udeps, &d); n > 0; n--)
+ printf(" %s", d[n -1]);
+ free(d);
+ printf("\n");
+ }
}
- atom_implode(as);
- dep_burn_tree(dep_tree);
- return 1;
+ atom_implode(datom);
+
+ return ret;
}
int qdepends_main(int argc, char **argv)
{
depend_atom *atom;
DECLARE_ARRAY(atoms);
+ DECLARE_ARRAY(deps);
struct qdepends_opt_state state = {
.atoms = atoms,
+ .deps = deps,
+ .udeps = create_set(),
+ .qmode = 0,
+ .depend = NULL,
+ .depend_len = 0,
};
- q_vdb_pkg_cb *cb;
size_t i;
int ret;
bool do_format = false;
- const char *query = NULL;
- const char *depend_file;
- const char *depend_files[] = {
- /* 0 */ "DEPEND",
- /* 1 */ "RDEPEND",
- /* 2 */ "PDEPEND",
- /* 3 */ "BDEPEND",
- /* 4 */ NULL
- };
-
- depend_file = depend_files[0];
while ((ret = GETOPT_LONG(QDEPENDS, qdepends, "")) != -1) {
switch (ret) {
COMMON_GETOPTS_CASES(qdepends)
- case 'd': depend_file = depend_files[0]; break;
- case 'r': depend_file = depend_files[1]; break;
- case 'p': depend_file = depend_files[2]; break;
- case 'b': depend_file = depend_files[3]; break;
- case 'k': depend_file = optarg; break;
- case 'a': depend_file = NULL; break;
- case 'Q': query = optarg; break;
+ case 'd': state.qmode |= QMODE_DEPEND; break;
+ case 'r': state.qmode |= QMODE_RDEPEND; break;
+ case 'p': state.qmode |= QMODE_PDEPEND; break;
+ case 'b': state.qmode |= QMODE_BDEPEND; break;
+ case 'Q': state.qmode |= QMODE_REVERSE; break;
case 'N': qdep_name_only = 1; break;
case 'f': do_format = true; break;
}
}
- if ((argc == optind) && (query == NULL) && !do_format)
+
+ if ((state.qmode & ~QMODE_REVERSE) == 0) {
+ /* default mode of operation: -qau (also for just -Q) */
+ state.qmode |= QMODE_DEPEND |
+ QMODE_RDEPEND |
+ QMODE_PDEPEND |
+ QMODE_BDEPEND;
+ }
+
+ if ((argc == optind) && !do_format)
qdepends_usage(EXIT_FAILURE);
if (do_format) {
while (optind < argc) {
- if (!dep_print_depend(stdout, argv[optind++]))
+ if (!qdepends_print_depend(stdout, argv[optind++]))
return EXIT_FAILURE;
if (optind < argc)
fprintf(stdout, "\n");
@@ -692,35 +306,25 @@ int qdepends_main(int argc, char **argv)
argc -= optind;
argv += optind;
- state.depend_file = depend_file;
- state.query = query;
- if (query)
- cb = qdepends_vdb_deep_cb;
- else {
- cb = qdepends_main_vdb_cb;
-
- for (i = 0; i < (size_t)argc; ++i) {
- atom = atom_explode(argv[i]);
- if (!atom)
- warn("invalid atom: %s", argv[i]);
- else
- xarraypush_ptr(atoms, atom);
- }
+ for (i = 0; i < (size_t)argc; ++i) {
+ atom = atom_explode(argv[i]);
+ if (!atom)
+ warn("invalid atom: %s", argv[i]);
+ else
+ xarraypush_ptr(atoms, atom);
}
- if (!depend_file) {
- ret = 0;
- for (i = 0; depend_files[i]; ++i) {
- printf(" %s*%s %s\n", GREEN, NORM, depend_files[i]);
- state.depend_file = depend_files[i];
- ret |= q_vdb_foreach_pkg(portroot, portvdb, cb, &state, NULL);
- }
- } else
- ret = q_vdb_foreach_pkg(portroot, portvdb, cb, &state, NULL);
+ ret = q_vdb_foreach_pkg(portroot, portvdb,
+ qdepends_results_cb, &state, NULL);
+
+ if (state.depend != NULL)
+ free(state.depend);
array_for_each(atoms, i, atom)
atom_implode(atom);
xarrayfree_int(atoms);
+ xarrayfree_int(state.deps);
+ free_set(state.udeps);
if (!ret)
warn("no matches found for your query");
diff --git a/tests/qdepends/dotest b/tests/qdepends/dotest
index 672fb15..41a4edd 100755
--- a/tests/qdepends/dotest
+++ b/tests/qdepends/dotest
@@ -21,6 +21,17 @@ test() {
return
fi
+ # qdepends output is based on a hash, which may differ based on
+ # endiannes, so sort the output so we get a deterministic set
+ while IFS= read -r line ; do
+ if [[ ${line} == *:* ]] ; then
+ pkg=${line%%:*}
+ echo "${pkg}: $(echo ${line#*:} | xargs -n1 | sort | xargs)"
+ else
+ echo "${line}"
+ fi
+ done < list | diff list - | patch -s list
+
local good="${as}/list${num}.good"
if [[ ! -e ${good} ]] ; then
cp list "${good}"
diff --git a/tests/qdepends/list02.good b/tests/qdepends/list02.good
index 14d0134..7d2631b 100644
--- a/tests/qdepends/list02.good
+++ b/tests/qdepends/list02.good
@@ -1,3 +1,3 @@
DEPEND="
- a/b
+ a/b
"
diff --git a/tests/qdepends/list03.good b/tests/qdepends/list03.good
index 017c839..f66b636 100644
--- a/tests/qdepends/list03.good
+++ b/tests/qdepends/list03.good
@@ -1,5 +1,5 @@
DEPEND="
- foo? (
- a/b
- )
+ foo? (
+ a/b
+ )
"
diff --git a/tests/qdepends/list04.good b/tests/qdepends/list04.good
index 6d9f24e..2457caf 100644
--- a/tests/qdepends/list04.good
+++ b/tests/qdepends/list04.good
@@ -1,5 +1,5 @@
DEPEND="
- || (
- a/b
- )
+ || (
+ a/b
+ )
"
diff --git a/tests/qdepends/list05.good b/tests/qdepends/list05.good
index 1d38431..0b7d420 100644
--- a/tests/qdepends/list05.good
+++ b/tests/qdepends/list05.good
@@ -1,10 +1,10 @@
DEPEND="
- || (
- || (
- || (
- x
- )
- a
- )
- )
+ || (
+ || (
+ || (
+ x
+ )
+ a
+ )
+ )
"
diff --git a/tests/qdepends/list06.good b/tests/qdepends/list06.good
index 6bcf3af..34cc4c9 100644
--- a/tests/qdepends/list06.good
+++ b/tests/qdepends/list06.good
@@ -1,3 +1,3 @@
DEPEND="
- a[foo(+)]
+ a[foo(+)]
"
diff --git a/tests/qdepends/list07.good b/tests/qdepends/list07.good
index 4aaea04..9aaf42d 100644
--- a/tests/qdepends/list07.good
+++ b/tests/qdepends/list07.good
@@ -1 +1 @@
-x11-apps/xdm-1.1.11-r3
+x11-apps/xdm-1.1.11-r3: !<sys-apps/systemd-187 >=media-fonts/font-util-1.2.0 >=sys-devel/autoconf-2.68 >=sys-devel/automake-1.12:1.12 >=sys-devel/automake-1.13:1.13 >=sys-devel/libtool-2.2.6a >=x11-apps/xinit-1.0.2-r3 >=x11-misc/util-macros-1.17 sys-devel/libtool sys-devel/m4 virtual/pkgconfig x11-apps/sessreg x11-apps/xconsole x11-apps/xrdb x11-libs/libX11 x11-libs/libXaw x11-libs/libXdmcp x11-libs/libXinerama x11-libs/libXmu x11-libs/libXt x11-proto/xineramaproto x11-proto/xproto
diff --git a/tests/qdepends/list08.good b/tests/qdepends/list08.good
index bad1799..9aaf42d 100644
--- a/tests/qdepends/list08.good
+++ b/tests/qdepends/list08.good
@@ -1 +1 @@
-x11-apps/xdm-1.1.11-r3: x11-apps/xrdb x11-libs/libXdmcp x11-libs/libXaw >=x11-apps/xinit-1.0.2-r3 x11-libs/libXinerama x11-libs/libXmu x11-libs/libX11 x11-libs/libXt x11-apps/sessreg x11-apps/xconsole !<sys-apps/systemd-187 x11-proto/xineramaproto x11-proto/xproto >=sys-devel/automake-1.12:1.12 >=sys-devel/automake-1.13:1.13 >=sys-devel/autoconf-2.68 sys-devel/libtool >=sys-devel/libtool-2.2.6a sys-devel/m4 >=x11-misc/util-macros-1.17 >=media-fonts/font-util-1.2.0 virtual/pkgconfig virtual/pkgconfig
+x11-apps/xdm-1.1.11-r3: !<sys-apps/systemd-187 >=media-fonts/font-util-1.2.0 >=sys-devel/autoconf-2.68 >=sys-devel/automake-1.12:1.12 >=sys-devel/automake-1.13:1.13 >=sys-devel/libtool-2.2.6a >=x11-apps/xinit-1.0.2-r3 >=x11-misc/util-macros-1.17 sys-devel/libtool sys-devel/m4 virtual/pkgconfig x11-apps/sessreg x11-apps/xconsole x11-apps/xrdb x11-libs/libX11 x11-libs/libXaw x11-libs/libXdmcp x11-libs/libXinerama x11-libs/libXmu x11-libs/libXt x11-proto/xineramaproto x11-proto/xproto