commit:     90de2c63f3d0d7e546265b02227b96b01dba24f7
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Sat Feb 20 10:54:05 2021 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Sat Feb 20 10:54:05 2021 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=90de2c63

libq/tree: add ability to match latest version per package in tree_match_atom

Allow retrieving the latest version per package matching the input atom.
E.g. a search for dash would return both app-shells/dash as well as
app-emacs/dash using LATEST, while FIRST would only return the app-emacs
one (or whichever came first while traversing).

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

 libq/tree.c | 42 ++++++++++++++++++++++++++----------------
 libq/tree.h |  9 +++++----
 2 files changed, 31 insertions(+), 20 deletions(-)

diff --git a/libq/tree.c b/libq/tree.c
index 293d7f7..df52171 100644
--- a/libq/tree.c
+++ b/libq/tree.c
@@ -1728,26 +1728,36 @@ tree_match_atom(tree_ctx *ctx, depend_atom *query, int 
flags)
 
 #define search_cat(C) \
 { \
+       char *lastpn = NULL; \
        while ((pkg_ctx = tree_next_pkg(C)) != NULL) { \
                atom = tree_get_atom(pkg_ctx, \
                                query->SLOT != NULL || flags & 
TREE_MATCH_FULL_ATOM); \
-               if (flags & TREE_MATCH_VIRTUAL || \
-                               strcmp(atom->CATEGORY, "virtual") != 0) { \
-                       if (atom_compare(atom, query) == EQUAL) { \
-                               tree_match_ctx *n = 
xzalloc(sizeof(tree_match_ctx)); \
-                               n->atom = atom; \
-                               snprintf(n->path, sizeof(n->path), 
"%s/%s/%s%s", \
-                                               (char *)C->ctx->path, C->name, 
pkg_ctx->name, \
-                                               C->ctx->cachetype == 
CACHE_EBUILD ? ".ebuild" : \
-                                               C->ctx->cachetype == 
CACHE_BINPKGS ? ".tbz2" : ""); \
-                               if (flags & TREE_MATCH_METADATA) \
-                                       n->meta = tree_pkg_read(pkg_ctx); \
-                               n->next = ret; \
-                               ret = n; \
-                       } \
-                       if (flags & TREE_MATCH_FIRST && ret != NULL) \
-                               break; \
+               /* skip virtual/ package as requested */ \
+               if (!(flags & TREE_MATCH_VIRTUAL || \
+                               strcmp(atom->CATEGORY, "virtual") != 0)) \
+                       continue; \
+               /* see if this atom matches the query */ \
+               if (atom_compare(atom, query) == EQUAL) { \
+                       tree_match_ctx *n; \
+                       /* skip over additional versions for match latest */ \
+                       if (flags & TREE_MATCH_LATEST && lastpn != NULL && \
+                                       strcmp(lastpn, atom->PN) == 0) \
+                               continue; \
+                       /* create a new match result */ \
+                       n = xzalloc(sizeof(tree_match_ctx)); \
+                       n->atom = atom; \
+                       snprintf(n->path, sizeof(n->path), "%s/%s/%s%s", \
+                                       (char *)C->ctx->path, C->name, 
pkg_ctx->name, \
+                                       C->ctx->cachetype == CACHE_EBUILD ? 
".ebuild" : \
+                                       C->ctx->cachetype == CACHE_BINPKGS ? 
".tbz2" : ""); \
+                       if (flags & TREE_MATCH_METADATA) \
+                               n->meta = tree_pkg_read(pkg_ctx); \
+                       n->next = ret; \
+                       ret = n; \
                } \
+               lastpn = atom->PN; \
+               if (flags & TREE_MATCH_FIRST && ret != NULL) \
+                       break; \
        } \
        C->pkg_cur = 0;  /* reset to allow another traversal */ \
 }

diff --git a/libq/tree.h b/libq/tree.h
index f756fd4..53fee67 100644
--- a/libq/tree.h
+++ b/libq/tree.h
@@ -155,10 +155,11 @@ int tree_foreach_pkg(tree_ctx *ctx, tree_pkg_cb callback, 
void *priv,
 set *tree_get_atoms(tree_ctx *ctx, bool fullcpv, set *satoms);
 depend_atom *tree_get_atom(tree_pkg_ctx *pkg_ctx, bool complete);
 tree_match_ctx *tree_match_atom(tree_ctx *t, depend_atom *q, int flags);
-#define TREE_MATCH_FULL_ATOM   1<<1
-#define TREE_MATCH_METADATA    1<<2
-#define TREE_MATCH_FIRST       1<<3
-#define TREE_MATCH_VIRTUAL     1<<4
+#define TREE_MATCH_FULL_ATOM  (1<<1)
+#define TREE_MATCH_METADATA   (1<<2)
+#define TREE_MATCH_LATEST     (1<<3)
+#define TREE_MATCH_VIRTUAL    (1<<4)
+#define TREE_MATCH_FIRST      (1<<5)
 #define TREE_MATCH_DEFAULT     TREE_MATCH_VIRTUAL
 void tree_match_close(tree_match_ctx *t);
 

Reply via email to