commit:     659a6f66ea87ba72faab6d24006987c16316cd82
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Tue May 14 20:19:17 2019 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Tue May 14 20:19:17 2019 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=659a6f66

qdepends: allow querying ebuild trees

Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 TODO.md                           |   2 -
 man/include/qdepends.desc         |   4 +-
 man/include/qdepends.optdesc.yaml |   3 +-
 man/qdepends.1                    |  13 +++--
 qdepends.c                        | 109 +++++++++++++++++++++++++++++++-------
 5 files changed, 104 insertions(+), 27 deletions(-)

diff --git a/TODO.md b/TODO.md
index ccff6e0..88d232f 100644
--- a/TODO.md
+++ b/TODO.md
@@ -59,9 +59,7 @@
 
 # qdepends
 
-- support querying uninstalled packages (via libq/cache)
 - add -S/-v/-R behavior like qlist #574934
-- support printing full dep content (with -v?) from libq/cache
 - bring back -k?  (but seems solved by using qlist -IF%{SLOT} pkg)
 
 # qpkg

diff --git a/man/include/qdepends.desc b/man/include/qdepends.desc
index b9954c9..19000d0 100644
--- a/man/include/qdepends.desc
+++ b/man/include/qdepends.desc
@@ -12,8 +12,8 @@ option.
 .P
 Currently,
 .I qdepends
-will only query installed packages.  There is no support for
-querying packages not yet installed (see \fBequery\fR(1) for that).
+defaults to query installed packages.  To query packages from ebuild
+trees, use the \fB-t\fR option.
 .P
 If there is no answer to your query (i.e. you've asked for a package
 that is not installed, or a version that does not match), then you will

diff --git a/man/include/qdepends.optdesc.yaml 
b/man/include/qdepends.optdesc.yaml
index f317227..0c8ef6b 100644
--- a/man/include/qdepends.optdesc.yaml
+++ b/man/include/qdepends.optdesc.yaml
@@ -25,6 +25,7 @@ format: |
 verbose: |
     Pretty-print atoms output, per DEPEND-variable.  This is much like
     the \fB-f\fR option, but uses as input the dependency info from the
-    matches.
+    matches.  When used with \fB-t\fR, the atom highlighting matches
+    what is used by the installed package, if available.
 quiet: Suppress DEPEND= output for \fB\-f\fR.  Only print the matching
     atom for \fB\-Q\fR.

diff --git a/man/qdepends.1 b/man/qdepends.1
index bee3bc1..d498680 100644
--- a/man/qdepends.1
+++ b/man/qdepends.1
@@ -20,8 +20,8 @@ option.
 .P
 Currently,
 .I qdepends
-will only query installed packages.  There is no support for
-querying packages not yet installed (see \fBequery\fR(1) for that).
+defaults to query installed packages.  To query packages from ebuild
+trees, use the \fB-t\fR option.
 .P
 If there is no answer to your query (i.e. you've asked for a package
 that is not installed, or a version that does not match), then you will
@@ -58,6 +58,12 @@ package that references \fI<arg>\fR in DEPEND, RDEPEND, 
PDEPEND or BDEPEND.
 This can be useful to find consumers of a given package, e.g.\ to
 search for packages that have \fIlogwatch\fR in their DEPEND.
 .TP
+\fB\-i\fR, \fB\-\-installed\fR
+Search installed packages using VDB.
+.TP
+\fB\-t\fR, \fB\-\-tree\fR
+Search available ebuilds in the tree.
+.TP
 \fB\-F\fR \fI<arg>\fR, \fB\-\-format\fR \fI<arg>\fR
 Pretty-print DEPEND declaration to be used in an ebuild.  This
 option initiates a very different mode of operation.  Instead of
@@ -78,7 +84,8 @@ Set the ROOT env var.
 \fB\-v\fR, \fB\-\-verbose\fR
 Pretty-print atoms output, per DEPEND-variable.  This is much like
 the \fB-f\fR option, but uses as input the dependency info from the
-matches.
+matches.  When used with \fB-t\fR, the atom highlighting matches
+what is used by the installed package, if available.
 .TP
 \fB\-q\fR, \fB\-\-quiet\fR
 Suppress DEPEND= output for \fB\-f\fR.  Only print the matching atom for 
\fB\-Q\fR.

diff --git a/qdepends.c b/qdepends.c
index 15d5253..4e6fd43 100644
--- a/qdepends.c
+++ b/qdepends.c
@@ -22,13 +22,15 @@
 #include "xasprintf.h"
 #include "xregex.h"
 
-#define QDEPENDS_FLAGS "drpbQF:S" COMMON_FLAGS
+#define QDEPENDS_FLAGS "drpbQitF:S" 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'},
        {"query",     no_argument, NULL, 'Q'},
+       {"installed", no_argument, NULL, 'i'},
+       {"tree",      no_argument, NULL, 't'},
        {"format",     a_argument, NULL, 'F'},
        {"pretty",    no_argument, NULL, 'S'},
        COMMON_LONG_OPTS
@@ -39,6 +41,8 @@ static const char * const qdepends_opts_help[] = {
        "Show PDEPEND info",
        "Show BDEPEND info",
        "Query reverse deps",
+       "Search installed packages using VDB",
+       "Search available ebuilds in the tree",
        "Print matched atom using given format string",
        "Pretty format specified depend strings",
        COMMON_OPTS_HELP
@@ -54,12 +58,15 @@ struct qdepends_opt_state {
        char *depend;
        size_t depend_len;
        const char *format;
+       tree_ctx *vdb;
 };
 
 #define QMODE_DEPEND     (1<<0)
 #define QMODE_RDEPEND    (1<<1)
 #define QMODE_PDEPEND    (1<<2)
 #define QMODE_BDEPEND    (1<<3)
+#define QMODE_INSTALLED  (1<<5)
+#define QMODE_TREE       (1<<6)
 #define QMODE_REVERSE    (1<<7)
 
 const char *depend_files[] = {  /* keep *DEPEND aligned with above defines */
@@ -107,6 +114,8 @@ qdepends_results_cb(tree_pkg_ctx *pkg_ctx, void *priv)
        int ret = 0;
        dep_node *dep_tree;
        char **d;
+       tree_pkg_meta *meta = NULL;
+       char *depstr;
 
        /* matrix consists of:
         * - QMODE_*DEPEND
@@ -142,19 +151,53 @@ qdepends_results_cb(tree_pkg_ctx *pkg_ctx, void *priv)
        xarrayfree_int(state->deps);
        clear_set(state->udeps);
 
+       if (state->qmode & QMODE_TREE)
+               if ((meta = tree_pkg_read(pkg_ctx)) == NULL)
+                       return ret;
        dfile = depend_files;
        for (i = QMODE_DEPEND; i <= QMODE_BDEPEND; i <<= 1, dfile++) {
                if (!(state->qmode & i))
                        continue;
-               if (!tree_pkg_vdb_eat(pkg_ctx, *dfile,
-                                       &state->depend, &state->depend_len))
-                       continue;
 
-               dep_tree = dep_grow_tree(state->depend);
+               if (state->qmode & QMODE_INSTALLED) {
+                       if (!tree_pkg_vdb_eat(pkg_ctx, *dfile,
+                                               &state->depend, 
&state->depend_len))
+                               continue;
+                       depstr = state->depend;
+               } else {
+                       depstr = i == 1<<0 ? meta->DEPEND :
+                                        i == 1<<1 ? meta->RDEPEND :
+                                        i == 1<<2 ? meta->PDEPEND :
+                                        i == 1<<3 ? meta->BDEPEND : NULL;
+                       if (depstr == NULL)
+                               continue;
+               }
+               dep_tree = dep_grow_tree(depstr);
                if (dep_tree == NULL)
                        continue;
 
-               dep_flatten_tree(dep_tree, state->deps);
+               if (state->qmode & QMODE_TREE && verbose) {
+                       /* pull in flags in use if possible */
+                       tree_cat_ctx *vcat =
+                               tree_open_cat(state->vdb, 
pkg_ctx->cat_ctx->name);
+                       if (vcat != NULL) {
+                               tree_pkg_ctx *vpkg =
+                                       tree_open_pkg(vcat, pkg_ctx->name);
+                               if (vpkg != NULL) {
+                                       if (tree_pkg_vdb_eat(vpkg, *dfile,
+                                                       &state->depend, 
&state->depend_len))
+                                       {
+                                               dep_node *dep_vdb = 
dep_grow_tree(state->depend);
+                                               if (dep_vdb != NULL)
+                                                       
dep_flatten_tree(dep_vdb, state->deps);
+                                       }
+                                       tree_close_pkg(vpkg);
+                               }
+                               tree_close_cat(vcat);
+                       }
+               } else {
+                       dep_flatten_tree(dep_tree, state->deps);
+               }
 
                if (verbose) {
                        if (state->qmode & QMODE_REVERSE) {
@@ -243,7 +286,6 @@ qdepends_results_cb(tree_pkg_ctx *pkg_ctx, void *priv)
 int qdepends_main(int argc, char **argv)
 {
        depend_atom *atom;
-       tree_ctx *vdb;
        DECLARE_ARRAY(atoms);
        DECLARE_ARRAY(deps);
        struct qdepends_opt_state state = {
@@ -254,6 +296,7 @@ int qdepends_main(int argc, char **argv)
                .depend = NULL,
                .depend_len = 0,
                .format = "%[CATEGORY]%[PF]",
+               .vdb = NULL,
        };
        size_t i;
        int ret;
@@ -266,17 +309,19 @@ int qdepends_main(int argc, char **argv)
                switch (ret) {
                COMMON_GETOPTS_CASES(qdepends)
 
-               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 'S': do_pretty = true;             break;
-               case 'F': state.format = 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 'i': state.qmode |= QMODE_INSTALLED; break;
+               case 't': state.qmode |= QMODE_TREE;      break;
+               case 'S': do_pretty = true;               break;
+               case 'F': state.format = optarg;          break;
                }
        }
 
-       if ((state.qmode & ~QMODE_REVERSE) == 0) {
+       if ((state.qmode & ~(QMODE_REVERSE | QMODE_INSTALLED | QMODE_TREE)) == 
0) {
                /* default mode of operation: -qau (also for just -Q) */
                state.qmode |= QMODE_DEPEND  |
                                           QMODE_RDEPEND |
@@ -284,6 +329,16 @@ int qdepends_main(int argc, char **argv)
                                           QMODE_BDEPEND;
        }
 
+       /* default to installed packages */
+       if (!(state.qmode & QMODE_INSTALLED) && !(state.qmode & QMODE_TREE))
+               state.qmode |= QMODE_INSTALLED;
+
+       /* don't allow both installed and froim tree */
+       if (state.qmode & QMODE_INSTALLED && state.qmode & QMODE_TREE) {
+               warn("-i and -t cannot be used together, dropping -i");
+               state.qmode &= ~QMODE_INSTALLED;
+       }
+
        if ((argc == optind) && !do_pretty)
                qdepends_usage(EXIT_FAILURE);
 
@@ -308,12 +363,28 @@ int qdepends_main(int argc, char **argv)
                        xarraypush_ptr(atoms, atom);
        }
 
-       vdb = tree_open_vdb(portroot, portvdb);
-       if (vdb != NULL) {
-               ret = tree_foreach_pkg_fast(vdb, qdepends_results_cb, &state, 
NULL);
-               tree_close(vdb);
+       if (state.qmode & QMODE_INSTALLED || verbose)
+               state.vdb = tree_open_vdb(portroot, portvdb);
+       if (state.qmode & QMODE_TREE) {
+               char *overlay;
+               size_t n;
+               tree_ctx *t;
+
+               array_for_each(overlays, n, overlay) {
+                       t = tree_open(portroot, overlay);
+                       if (t != NULL) {
+                               ret = tree_foreach_pkg_sorted(t,
+                                               qdepends_results_cb, &state);
+                               tree_close(t);
+                       }
+               }
+       } else {
+               ret = tree_foreach_pkg_fast(state.vdb,
+                               qdepends_results_cb, &state, NULL);
        }
 
+       if (state.vdb != NULL)
+               tree_close(state.vdb);
        if (state.depend != NULL)
                free(state.depend);
 

Reply via email to