public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
From: "Fabian Groffen" <grobian@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/portage-utils:master commit in: libq/
Date: Mon, 25 May 2020 10:43:56 +0000 (UTC)	[thread overview]
Message-ID: <1590402894.553eb9afd1a57bbe56bdddd77ddf0bb450ee32b8.grobian@gentoo> (raw)

commit:     553eb9afd1a57bbe56bdddd77ddf0bb450ee32b8
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Mon May 25 10:34:54 2020 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Mon May 25 10:34:54 2020 +0000
URL:        https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=553eb9af

libq/tree: rework tree_match_atom to return a list of results

Major change is that multiple results are returned, somewhat controlled
by flags, and that the results are valid until the tree is closed.  Each
match result needs to be closed individually though.

This required some hoops to make it work with Packages file or binpkg
repos.  The latter are largely simulated now, and do not really benefit
from the cheaper point and lookup approach that tree_match_atom tries to
provide.

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

 libq/tree.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------
 libq/tree.h |  21 ++++++-
 2 files changed, 177 insertions(+), 25 deletions(-)

diff --git a/libq/tree.c b/libq/tree.c
index 4b9109e..d313f3b 100644
--- a/libq/tree.c
+++ b/libq/tree.c
@@ -388,14 +388,11 @@ tree_filter_pkg(const struct dirent *de)
 tree_pkg_ctx *
 tree_open_pkg(tree_cat_ctx *cat_ctx, const char *name)
 {
-	tree_pkg_ctx *pkg_ctx = xmalloc(sizeof(*pkg_ctx));
+	tree_pkg_ctx *pkg_ctx = xzalloc(sizeof(*pkg_ctx));
 	pkg_ctx->name = name;
-	pkg_ctx->slot = NULL;
 	pkg_ctx->repo = cat_ctx->ctx->repo;
 	pkg_ctx->fd = -1;
 	pkg_ctx->cat_ctx = cat_ctx;
-	pkg_ctx->atom = NULL;
-	pkg_ctx->meta = NULL;
 
 	/* see if this pkg matches the query, here we can finally check
 	 * version conditions like >=, etc. */
@@ -1405,12 +1402,14 @@ tree_foreach_packages(tree_ctx *ctx, tree_pkg_cb callback, void *priv)
 		match_key(IUSE);
 		match_key(KEYWORDS);
 		match_key(LICENSE);
-		match_key2(MD5, _md5_);
-		match_key2(SHA1, _eclasses_);
+		match_key(MD5);
+		match_key(SHA1);
 		match_key(RDEPEND);
 		match_key(SLOT);
 		match_key(USE);
 		match_key(PDEPEND);
+		match_key2(REPO, repository);
+		match_key(SIZE);
 #undef match_key
 #undef match_key2
 		}
@@ -1430,6 +1429,7 @@ tree_foreach_packages(tree_ctx *ctx, tree_pkg_cb callback, void *priv)
 	/* ensure we don't free a garbage pointer */
 	ctx->repo = NULL;
 	ctx->do_sort = false;
+	ctx->pkgs[0] = '\0';
 
 	return ret;
 }
@@ -1580,34 +1580,167 @@ tree_get_atoms(tree_ctx *ctx, bool fullcpv, set *satoms)
 	return state.cpf;
 }
 
-tree_pkg_ctx *
-tree_match_atom(tree_ctx *ctx, depend_atom *a)
+struct tree_match_pkgs_cb_ctx {
+	int flags;
+	tree_match_ctx *ret;
+};
+
+static int
+tree_match_atom_packages_cb(tree_pkg_ctx *ctx, void *priv)
+{
+	struct tree_match_pkgs_cb_ctx *rctx = priv;
+	depend_atom *a;
+	tree_match_ctx *n;
+
+	/* skip anything after finding first match */
+	if (rctx->flags & TREE_MATCH_FIRST && rctx->ret != NULL)
+		return 1;
+
+	a = tree_get_atom(ctx, rctx->flags & TREE_MATCH_FULL_ATOM);
+
+	/* skip virtual category if not requested */
+	if (!(rctx->flags & TREE_MATCH_VIRTUAL) &&
+			strcmp(a->CATEGORY, "virtual") == 0)
+		return 1;
+
+	n = xzalloc(sizeof(tree_match_ctx));
+	n->free_atom = true;
+	n->atom = atom_clone(a);
+	if (rctx->flags & TREE_MATCH_METADATA) {
+		n->meta = xmalloc(sizeof(*n->meta));
+		/* for Packages, all pointers to meta here are to the in memory
+		 * copy of the Packages file, so these pointers can just be
+		 * copied since the tree has to remain open, thus the pointers
+		 * will stay valid */
+		memcpy(n->meta, ctx->cat_ctx->ctx->pkgs, sizeof(*n->meta));
+	}
+
+	n->next = rctx->ret;
+	rctx->ret = n;
+
+	return 0;
+}
+
+static int
+tree_match_atom_binpkg_cb(tree_pkg_ctx *ctx, void *priv)
+{
+	struct tree_match_pkgs_cb_ctx *rctx = priv;
+	depend_atom *a;
+	tree_match_ctx *n;
+
+	/* skip anything after finding first match */
+	if (rctx->flags & TREE_MATCH_FIRST && rctx->ret != NULL)
+		return 1;
+
+	a = tree_get_atom(ctx, rctx->flags & TREE_MATCH_FULL_ATOM);
+
+	/* skip virtual category if not requested */
+	if (!(rctx->flags & TREE_MATCH_VIRTUAL) &&
+			strcmp(a->CATEGORY, "virtual") == 0)
+		return 1;
+
+	n = xzalloc(sizeof(tree_match_ctx));
+	n->free_atom = true;
+	n->atom = atom_clone(a);
+	if (rctx->flags & TREE_MATCH_METADATA)
+		n->meta = tree_pkg_read(ctx);
+
+	n->next = rctx->ret;
+	rctx->ret = n;
+
+	return 0;
+}
+
+tree_match_ctx *
+tree_match_atom(tree_ctx *ctx, depend_atom *query, int flags)
 {
 	tree_cat_ctx *cat_ctx;
 	tree_pkg_ctx *pkg_ctx;
+	tree_match_ctx *ret = NULL;
 	depend_atom *atom;
 
+	if (ctx->cachetype == CACHE_PACKAGES) {
+		struct tree_match_pkgs_cb_ctx rctx;
+		/* Packages needs to be serviced separately because it doesn't
+		 * use a tree internally, but reads off of the Packages file */
+		rctx.flags = flags;
+		rctx.ret = NULL;
+		ctx->query_atom = query;
+		tree_foreach_packages(ctx, tree_match_atom_packages_cb, &rctx);
+		ctx->query_atom = NULL;
+		return rctx.ret;
+	} else if (ctx->cachetype == CACHE_BINPKGS) {
+		struct tree_match_pkgs_cb_ctx rctx;
+		/* this sulks, but binpkgs modify the pkg_ctx->name to strip off
+		 * .tbz2, and that makes it non-reusable */
+		rctx.flags = flags;
+		rctx.ret = NULL;
+		tree_foreach_pkg(ctx, tree_match_atom_binpkg_cb, &rctx, true, query);
+		return rctx.ret;
+	}
+
+	/* activate cache for future lookups, tree_match_atom relies on
+	 * cache behaviour from tree, which means all categories and
+	 * packages remain in memory until tree_close is being called */
 	if (ctx->cache.categories == NULL)
 		ctx->cache.categories = create_set();
 
-	if (a->P == NULL) {
-		return NULL;
-	} else if (a->CATEGORY == NULL) {
-		/* loop through all cats and recurse */
-		/* TODO: some day */
-		return NULL;
+	ctx->do_sort = true;     /* sort uses buffer, which cache relies on */
+	ctx->query_atom = NULL;  /* ensure the cache contains ALL pkgs */
+
+#define search_cat(C) \
+{ \
+	while ((pkg_ctx = tree_next_pkg(C)) != NULL) { \
+		atom = tree_get_atom(pkg_ctx, \
+				query->SLOT != NULL || flags & TREE_MATCH_FULL_ATOM); \
+fprintf(stderr, "fbg: %s\n", atom_to_string(atom)); \
+		if (flags & TREE_MATCH_VIRTUAL || \
+				strcmp(atom->CATEGORY, "virtual") != 0) \
+			if (atom_compare(atom, query) == EQUAL) { \
+				tree_match_ctx *n; \
+				n = xzalloc(sizeof(tree_match_ctx)); \
+				n->free_atom = false; \
+				n->atom = atom; \
+				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; \
+	} \
+	C->pkg_cur = 0;  /* reset to allow another traversal */ \
+}
+
+	if (query->CATEGORY == NULL) {
+		/* loop through all cats */
+		while ((cat_ctx = tree_next_cat(ctx)) != NULL) {
+			search_cat(cat_ctx);
+			if (ret != NULL && flags & TREE_MATCH_FIRST)
+				break;
+		}
+		/* allow running again through the cats */
+		ctx->cat_cur = 0;
 	} else {
 		/* try CAT, and PN for latest version */
-		if ((cat_ctx = tree_open_cat(ctx, a->CATEGORY)) == NULL)
-			return NULL;
-		ctx->do_sort = true;     /* sort uses buffer, which cache relies on */
-		ctx->query_atom = NULL;  /* ensure the cache contains ALL pkgs */
-		while ((pkg_ctx = tree_next_pkg(cat_ctx)) != NULL) {
-			atom = tree_get_atom(pkg_ctx, a->SLOT != NULL);
-			if (atom_compare(atom, a) == EQUAL)
-				return pkg_ctx;
-		}
+		if ((cat_ctx = tree_open_cat(ctx, query->CATEGORY)) != NULL)
+			search_cat(cat_ctx);
+	}
 
-		return NULL;
+	return ret;
+}
+
+void
+tree_match_close(tree_match_ctx *match)
+{
+	tree_match_ctx *w;
+
+	for (w = NULL; match != NULL; match = w) {
+		w = match->next;
+		if (match->free_atom)
+			atom_implode(match->atom);
+		if (match->meta != NULL)
+			free(match->meta);
+		free(match);
 	}
 }

diff --git a/libq/tree.h b/libq/tree.h
index eaee7ad..900b998 100644
--- a/libq/tree.h
+++ b/libq/tree.h
@@ -18,6 +18,7 @@ typedef struct tree_cat_ctx      tree_cat_ctx;
 typedef struct tree_pkg_ctx      tree_pkg_ctx;
 typedef struct tree_pkg_meta     tree_pkg_meta;
 typedef struct tree_metadata_xml tree_metadata_xml;
+typedef struct tree_match_ctx    tree_match_ctx;
 
 /* tree context */
 struct tree_ctx {
@@ -100,6 +101,9 @@ struct tree_pkg_meta {
 	char *Q_USE;
 	char *Q_EPREFIX;
 	char *Q_repository;
+	char *Q_MD5;
+	char *Q_SHA1;
+#define Q_SIZE Q_SRC_URI
 	/* These are MD5-Cache only */
 	char *Q__eclasses_;
 	char *Q__md5_;
@@ -113,6 +117,15 @@ struct tree_metadata_xml {
 	} *email;
 };
 
+/* used with tree_match_atom, both atom and meta are fully materialised
+ * (populated and deep copied) when set */
+struct tree_match_ctx {
+	depend_atom *atom;
+	tree_pkg_meta *meta;
+	tree_match_ctx *next;
+	int free_atom;
+};
+
 /* foreach pkg callback function signature */
 typedef int (tree_pkg_cb)(tree_pkg_ctx *, void *priv);
 
@@ -138,6 +151,12 @@ int tree_foreach_pkg(tree_ctx *ctx, tree_pkg_cb callback, void *priv,
 	tree_foreach_pkg(ctx, cb, priv, true, query);
 set *tree_get_atoms(tree_ctx *ctx, bool fullcpv, set *satoms);
 depend_atom *tree_get_atom(tree_pkg_ctx *pkg_ctx, bool complete);
-tree_pkg_ctx *tree_match_atom(tree_ctx *t, depend_atom *a);
+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_DEFAULT     TREE_MATCH_VIRTUAL
+void tree_match_close(tree_match_ctx *t);
 
 #endif


             reply	other threads:[~2020-05-25 10:44 UTC|newest]

Thread overview: 196+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-25 10:43 Fabian Groffen [this message]
  -- strict thread matches above, loose matches on Subject: below --
2024-07-03 19:44 [gentoo-commits] proj/portage-utils:master commit in: libq/ Fabian Groffen
2024-04-08 19:27 Fabian Groffen
2024-02-01  8:21 Fabian Groffen
2024-02-01  8:21 Fabian Groffen
2024-01-31 20:41 Fabian Groffen
2024-01-31 19:30 Fabian Groffen
2024-01-31 19:29 Fabian Groffen
2024-01-27 13:28 Fabian Groffen
2023-04-21 19:11 Fabian Groffen
2023-01-30 14:14 Fabian Groffen
2022-05-26 14:36 Fabian Groffen
2022-05-26 14:36 Fabian Groffen
2022-05-20 17:15 Fabian Groffen
2022-05-20 17:15 Fabian Groffen
2022-05-19  8:32 Fabian Groffen
2022-05-19  8:16 Fabian Groffen
2022-05-19  7:45 Fabian Groffen
2022-02-12 17:13 Fabian Groffen
2022-02-12 17:13 Fabian Groffen
2022-02-06 14:51 Fabian Groffen
2022-02-06 14:29 Fabian Groffen
2022-02-06 13:27 Fabian Groffen
2022-02-06 13:27 Fabian Groffen
2022-02-06 12:22 Fabian Groffen
2021-12-29 12:20 Fabian Groffen
2021-12-26 13:59 Fabian Groffen
2021-12-26 13:59 Fabian Groffen
2021-12-26 13:59 Fabian Groffen
2021-12-26 13:59 Fabian Groffen
2021-12-13  8:39 Fabian Groffen
2021-12-13  8:39 Fabian Groffen
2021-11-13 14:27 Fabian Groffen
2021-10-09 12:13 Fabian Groffen
2021-10-04  6:28 Fabian Groffen
2021-10-04  6:28 Fabian Groffen
2021-10-03 10:49 Fabian Groffen
2021-06-23  7:14 Fabian Groffen
2021-06-14  9:34 Fabian Groffen
2021-06-14  9:34 Fabian Groffen
2021-06-14  9:34 Fabian Groffen
2021-06-14  9:34 Fabian Groffen
2021-06-14  9:34 Fabian Groffen
2021-06-14  9:34 Fabian Groffen
2021-06-01 19:43 Fabian Groffen
2021-05-23 10:54 Fabian Groffen
2021-05-10  9:15 Fabian Groffen
2021-04-29 15:04 Fabian Groffen
2021-04-29 13:47 Fabian Groffen
2021-04-29 13:24 Fabian Groffen
2021-03-13 12:44 Fabian Groffen
2021-02-20 12:06 Fabian Groffen
2021-02-20 11:44 Fabian Groffen
2021-02-17 20:23 Fabian Groffen
2021-02-17 20:23 Fabian Groffen
2021-01-15 20:05 Fabian Groffen
2020-06-27  9:38 Fabian Groffen
2020-06-07 10:41 Fabian Groffen
2020-05-25 18:19 Fabian Groffen
2020-05-25 18:02 Fabian Groffen
2020-05-25 13:26 Fabian Groffen
2020-05-25 11:20 Fabian Groffen
2020-05-25 11:06 Fabian Groffen
2020-05-25 10:43 Fabian Groffen
2020-05-25 10:43 Fabian Groffen
2020-05-25 10:43 Fabian Groffen
2020-05-25 10:43 Fabian Groffen
2020-05-17 12:35 Fabian Groffen
2020-05-17 12:35 Fabian Groffen
2020-02-03 13:17 Fabian Groffen
2020-02-03 13:09 Fabian Groffen
2020-01-26 19:31 Fabian Groffen
2020-01-22 19:54 Fabian Groffen
2020-01-22 19:54 Fabian Groffen
2020-01-20 19:54 Fabian Groffen
2020-01-20 19:34 Fabian Groffen
2020-01-19 19:36 Fabian Groffen
2020-01-19 19:09 Fabian Groffen
2020-01-19 19:09 Fabian Groffen
2020-01-19 19:09 Fabian Groffen
2020-01-19 19:09 Fabian Groffen
2020-01-19 16:37 Fabian Groffen
2020-01-19 12:37 Fabian Groffen
2020-01-19 10:05 Fabian Groffen
2020-01-19  9:49 Fabian Groffen
2020-01-19  9:49 Fabian Groffen
2020-01-17  8:22 Fabian Groffen
2020-01-05 16:08 Fabian Groffen
2020-01-05 16:08 Fabian Groffen
2020-01-05 16:08 Fabian Groffen
2020-01-02 15:09 Fabian Groffen
2020-01-02 14:07 Fabian Groffen
2020-01-02 14:07 Fabian Groffen
2020-01-02 14:07 Fabian Groffen
2020-01-02 11:55 Fabian Groffen
2020-01-02 11:19 Fabian Groffen
2019-12-30 17:24 Fabian Groffen
2019-12-27 21:19 Fabian Groffen
2019-12-27 16:57 Fabian Groffen
2019-12-27 16:57 Fabian Groffen
2019-11-29 13:22 Fabian Groffen
2019-11-20 17:23 Fabian Groffen
2019-11-19 20:28 Fabian Groffen
2019-11-17 15:12 Fabian Groffen
2019-11-17 15:12 Fabian Groffen
2019-11-13 18:19 Fabian Groffen
2019-11-13 15:48 Fabian Groffen
2019-11-13 15:20 Fabian Groffen
2019-11-09 10:29 Fabian Groffen
2019-09-26 14:06 Fabian Groffen
2019-09-26 14:06 Fabian Groffen
2019-09-26 14:06 Fabian Groffen
2019-09-26 14:06 Fabian Groffen
2019-09-26 13:00 Fabian Groffen
2019-09-25 15:05 Fabian Groffen
2019-09-21 19:53 Fabian Groffen
2019-09-21 19:53 Fabian Groffen
2019-07-14 18:51 Fabian Groffen
2019-07-13 15:37 Fabian Groffen
2019-07-13  9:50 Fabian Groffen
2019-07-12 18:04 Fabian Groffen
2019-06-19  7:41 Fabian Groffen
2019-06-10 10:09 Fabian Groffen
2019-06-05  7:57 Fabian Groffen
2019-05-21 14:12 Fabian Groffen
2019-05-14 20:19 Fabian Groffen
2019-05-14 20:19 Fabian Groffen
2019-05-11 11:11 Fabian Groffen
2019-05-11  7:14 Fabian Groffen
2019-05-11  7:14 Fabian Groffen
2019-05-10 15:32 Fabian Groffen
2019-05-10 15:32 Fabian Groffen
2019-05-10 15:32 Fabian Groffen
2019-05-07  6:19 Fabian Groffen
2019-05-06 16:04 Fabian Groffen
2019-05-06 16:04 Fabian Groffen
2019-05-05 20:05 Fabian Groffen
2019-05-05 18:13 Fabian Groffen
2019-05-05  8:58 Fabian Groffen
2019-05-04 11:53 Fabian Groffen
2019-05-03 11:45 Fabian Groffen
2019-05-02 15:17 Fabian Groffen
2019-05-01 19:09 Fabian Groffen
2019-04-30  8:20 Fabian Groffen
2019-04-30  7:54 Fabian Groffen
2019-04-28 17:10 Fabian Groffen
2019-04-28 16:21 Fabian Groffen
2019-04-28 16:02 Fabian Groffen
2019-04-27  8:38 Fabian Groffen
2019-04-25 17:36 Fabian Groffen
2019-04-25  9:22 Fabian Groffen
2019-04-25  9:22 Fabian Groffen
2019-04-25  9:22 Fabian Groffen
2019-04-25  9:22 Fabian Groffen
2019-04-19 11:47 Fabian Groffen
2019-03-27 10:55 Fabian Groffen
2019-03-11 20:55 Fabian Groffen
2019-03-09 18:58 Fabian Groffen
2019-02-27 20:53 Fabian Groffen
2019-02-27 20:53 Fabian Groffen
2019-02-05 14:19 Fabian Groffen
2018-12-20 20:02 Fabian Groffen
2018-12-20 20:02 Fabian Groffen
2018-12-20 18:24 Fabian Groffen
2018-04-09  7:15 Fabian Groffen
2018-04-05 13:31 Fabian Groffen
2018-04-05 12:46 Fabian Groffen
2018-04-03 20:00 Fabian Groffen
2018-03-26 18:41 Fabian Groffen
2018-03-25 14:13 Fabian Groffen
2018-03-25 14:00 Fabian Groffen
2018-03-23 20:17 Fabian Groffen
2018-03-23 11:56 Fabian Groffen
2018-03-23 11:29 Fabian Groffen
2017-12-29 11:45 Fabian Groffen
2017-12-29 11:45 Fabian Groffen
2017-12-29 11:45 Fabian Groffen
2016-12-29  2:25 Mike Frysinger
2016-11-12 17:23 Mike Frysinger
2016-02-14  1:26 Mike Frysinger
2016-02-14  1:26 Mike Frysinger
2015-11-26  8:43 Mike Frysinger
2015-10-15 22:00 Mike Frysinger
2015-10-15 22:00 Mike Frysinger
2015-05-31  8:31 Mike Frysinger
2015-05-19 17:37 Mike Frysinger
2015-02-24  1:26 Mike Frysinger
2015-02-24  1:26 Mike Frysinger
2015-02-24  1:26 Mike Frysinger
2015-02-21 18:06 Mike Frysinger
2015-02-16 11:47 Mike Frysinger
2014-03-11  4:53 Mike Frysinger
2014-03-08  5:51 Mike Frysinger
2014-03-08  5:51 Mike Frysinger
2014-03-08  5:51 Mike Frysinger
2014-03-08  5:51 Mike Frysinger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1590402894.553eb9afd1a57bbe56bdddd77ddf0bb450ee32b8.grobian@gentoo \
    --to=grobian@gentoo.org \
    --cc=gentoo-commits@lists.gentoo.org \
    --cc=gentoo-dev@lists.gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox