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 /qdepends.c
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>
Diffstat (limited to 'qdepends.c')
-rw-r--r--qdepends.c776
1 files changed, 190 insertions, 586 deletions
diff --git a/qdepends.c b/qdepends.c
index ca82f089..df3434e4 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");