commit:     3d00cad113975b02ece79892eb5f752d818aaa73
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Sun Mar 25 13:57:56 2018 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Sun Mar 25 13:57:56 2018 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=3d00cad1

qdepends_vdb_deep_cb: use atom matching when possible, bug #608960

When the argument is an atom-parsable thing, match whatever we find in
the vdb as atom, such that version and range can be taken into account.

Bug: https://bugs.gentoo.org/608960

 qdepends.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 95 insertions(+), 23 deletions(-)

diff --git a/qdepends.c b/qdepends.c
index d5a8ef5..cd5e851 100644
--- a/qdepends.c
+++ b/qdepends.c
@@ -475,13 +475,17 @@ qdepends_vdb_deep_cb(q_vdb_pkg_ctx *pkg_ctx, void *priv)
        const char *pkgname = pkg_ctx->name;
        size_t len;
        char *ptr;
-       char buf[_Q_PATH_MAX];
+       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;
 
        if (!q_vdb_pkg_eat(pkg_ctx, state->depend_file, &depend, &depend_len))
                return 0;
@@ -508,36 +512,104 @@ qdepends_vdb_deep_cb(q_vdb_pkg_ctx *pkg_ctx, void *priv)
 
        dep_prune_use(dep_tree, use);
 
-       ptr = dep_flatten_tree(dep_tree);
+       if ((ptr = dep_flatten_tree(dep_tree)) == NULL) {
+               dep_burn_tree(dep_tree);
+               return 1;
+       }
 
-       ret = -2;
-       if (ptr && wregcomp(&preg, state->query, REG_EXTENDED) == 0)
-               ret = regexec(&preg, ptr, 1, &match, 0);
-       if (ret > -2)
-               regfree(&preg);
+       snprintf(qbuf, sizeof(qbuf), "%s/%s", catname, pkgname);
+       as = atom_explode(qbuf);
+       if (!as) {
+               dep_burn_tree(dep_tree);
+               return 1;
+       }
 
-       if (ptr && ret == 0) {
-               if (qdep_name_only) {
-                       depend_atom *atom = NULL;
-                       snprintf(buf, sizeof(buf), "%s/%s", catname, pkgname);
-                       if ((atom = atom_explode(buf)) != NULL) {
-                               printf("%s%s/%s%s%s%c", BOLD, catname, BLUE, 
atom->PN, NORM, verbose ? ':' : '\n');
-                               atom_implode(atom);
-                       }
+       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;
+               }
+       }
+
+       match.rm_eo = 0;
+       firstmatch = 1;
+       do {  /* find all matches */
+               if (!aq) {
+                       ret = regexec(&preg, ptr + match.rm_eo, 1, &match, 0);
                } else {
-                       printf("%s%s/%s%s%s%c", BOLD, catname, BLUE, pkgname, 
NORM, verbose ? ':' : '\n');
+                       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 (verbose) {
-                       /* find the boundaries for this atom */
-                       while (match.rm_so > 0 && !isspace(ptr[match.rm_so - 
1]))
-                               match.rm_so--;
-                       while (ptr[match.rm_eo] != '\0' && 
!isspace(ptr[match.rm_eo]))
-                               match.rm_eo++;
-                       printf(" %.*s\n",
+               if (ret != 0)
+                       break;
+
+               /* find the boundaries for matched atom */
+               while (match.rm_so > 0 && !isspace(ptr[match.rm_so - 1]))
+                       match.rm_so--;
+               while (ptr[match.rm_eo] != '\0' && !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);
+
+               ret = atom_compare(ac, aq);
+               if (ret != EQUAL) {
+                       atom_implode(ac);
+                       break;
+               }
+
+               if (firstmatch == 1) {
+                       firstmatch = 0;
+                       printf("%s%s/%s%s%s%c", BOLD, catname, BLUE,
+                                       qdep_name_only ? as->PN : pkgname, NORM,
+                                       verbose ? ':' : '\n');
+               }
+
+               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);
+                       } else {
+                               printf("%s", qbuf);
+                       }
+               } else {
+                       /* if not verbose, we don't care about any extra 
matches */
+                       atom_implode(ac);
+                       break;
                }
+       } while (1);
+       if (verbose && firstmatch == 0)
+               printf("\n");
+
+       if (!aq) {
+               regfree(&preg);
+       } else {
+               atom_implode(aq);
        }
+       atom_implode(as);
        dep_burn_tree(dep_tree);
 
        return 1;

Reply via email to