Gentoo Archives: gentoo-commits

From: Fabian Groffen <grobian@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage-utils:master commit in: libq/
Date: Mon, 25 May 2020 10:44:03
Message-Id: 1590402894.553eb9afd1a57bbe56bdddd77ddf0bb450ee32b8.grobian@gentoo
1 commit: 553eb9afd1a57bbe56bdddd77ddf0bb450ee32b8
2 Author: Fabian Groffen <grobian <AT> gentoo <DOT> org>
3 AuthorDate: Mon May 25 10:34:54 2020 +0000
4 Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org>
5 CommitDate: Mon May 25 10:34:54 2020 +0000
6 URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=553eb9af
7
8 libq/tree: rework tree_match_atom to return a list of results
9
10 Major change is that multiple results are returned, somewhat controlled
11 by flags, and that the results are valid until the tree is closed. Each
12 match result needs to be closed individually though.
13
14 This required some hoops to make it work with Packages file or binpkg
15 repos. The latter are largely simulated now, and do not really benefit
16 from the cheaper point and lookup approach that tree_match_atom tries to
17 provide.
18
19 Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>
20
21 libq/tree.c | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------
22 libq/tree.h | 21 ++++++-
23 2 files changed, 177 insertions(+), 25 deletions(-)
24
25 diff --git a/libq/tree.c b/libq/tree.c
26 index 4b9109e..d313f3b 100644
27 --- a/libq/tree.c
28 +++ b/libq/tree.c
29 @@ -388,14 +388,11 @@ tree_filter_pkg(const struct dirent *de)
30 tree_pkg_ctx *
31 tree_open_pkg(tree_cat_ctx *cat_ctx, const char *name)
32 {
33 - tree_pkg_ctx *pkg_ctx = xmalloc(sizeof(*pkg_ctx));
34 + tree_pkg_ctx *pkg_ctx = xzalloc(sizeof(*pkg_ctx));
35 pkg_ctx->name = name;
36 - pkg_ctx->slot = NULL;
37 pkg_ctx->repo = cat_ctx->ctx->repo;
38 pkg_ctx->fd = -1;
39 pkg_ctx->cat_ctx = cat_ctx;
40 - pkg_ctx->atom = NULL;
41 - pkg_ctx->meta = NULL;
42
43 /* see if this pkg matches the query, here we can finally check
44 * version conditions like >=, etc. */
45 @@ -1405,12 +1402,14 @@ tree_foreach_packages(tree_ctx *ctx, tree_pkg_cb callback, void *priv)
46 match_key(IUSE);
47 match_key(KEYWORDS);
48 match_key(LICENSE);
49 - match_key2(MD5, _md5_);
50 - match_key2(SHA1, _eclasses_);
51 + match_key(MD5);
52 + match_key(SHA1);
53 match_key(RDEPEND);
54 match_key(SLOT);
55 match_key(USE);
56 match_key(PDEPEND);
57 + match_key2(REPO, repository);
58 + match_key(SIZE);
59 #undef match_key
60 #undef match_key2
61 }
62 @@ -1430,6 +1429,7 @@ tree_foreach_packages(tree_ctx *ctx, tree_pkg_cb callback, void *priv)
63 /* ensure we don't free a garbage pointer */
64 ctx->repo = NULL;
65 ctx->do_sort = false;
66 + ctx->pkgs[0] = '\0';
67
68 return ret;
69 }
70 @@ -1580,34 +1580,167 @@ tree_get_atoms(tree_ctx *ctx, bool fullcpv, set *satoms)
71 return state.cpf;
72 }
73
74 -tree_pkg_ctx *
75 -tree_match_atom(tree_ctx *ctx, depend_atom *a)
76 +struct tree_match_pkgs_cb_ctx {
77 + int flags;
78 + tree_match_ctx *ret;
79 +};
80 +
81 +static int
82 +tree_match_atom_packages_cb(tree_pkg_ctx *ctx, void *priv)
83 +{
84 + struct tree_match_pkgs_cb_ctx *rctx = priv;
85 + depend_atom *a;
86 + tree_match_ctx *n;
87 +
88 + /* skip anything after finding first match */
89 + if (rctx->flags & TREE_MATCH_FIRST && rctx->ret != NULL)
90 + return 1;
91 +
92 + a = tree_get_atom(ctx, rctx->flags & TREE_MATCH_FULL_ATOM);
93 +
94 + /* skip virtual category if not requested */
95 + if (!(rctx->flags & TREE_MATCH_VIRTUAL) &&
96 + strcmp(a->CATEGORY, "virtual") == 0)
97 + return 1;
98 +
99 + n = xzalloc(sizeof(tree_match_ctx));
100 + n->free_atom = true;
101 + n->atom = atom_clone(a);
102 + if (rctx->flags & TREE_MATCH_METADATA) {
103 + n->meta = xmalloc(sizeof(*n->meta));
104 + /* for Packages, all pointers to meta here are to the in memory
105 + * copy of the Packages file, so these pointers can just be
106 + * copied since the tree has to remain open, thus the pointers
107 + * will stay valid */
108 + memcpy(n->meta, ctx->cat_ctx->ctx->pkgs, sizeof(*n->meta));
109 + }
110 +
111 + n->next = rctx->ret;
112 + rctx->ret = n;
113 +
114 + return 0;
115 +}
116 +
117 +static int
118 +tree_match_atom_binpkg_cb(tree_pkg_ctx *ctx, void *priv)
119 +{
120 + struct tree_match_pkgs_cb_ctx *rctx = priv;
121 + depend_atom *a;
122 + tree_match_ctx *n;
123 +
124 + /* skip anything after finding first match */
125 + if (rctx->flags & TREE_MATCH_FIRST && rctx->ret != NULL)
126 + return 1;
127 +
128 + a = tree_get_atom(ctx, rctx->flags & TREE_MATCH_FULL_ATOM);
129 +
130 + /* skip virtual category if not requested */
131 + if (!(rctx->flags & TREE_MATCH_VIRTUAL) &&
132 + strcmp(a->CATEGORY, "virtual") == 0)
133 + return 1;
134 +
135 + n = xzalloc(sizeof(tree_match_ctx));
136 + n->free_atom = true;
137 + n->atom = atom_clone(a);
138 + if (rctx->flags & TREE_MATCH_METADATA)
139 + n->meta = tree_pkg_read(ctx);
140 +
141 + n->next = rctx->ret;
142 + rctx->ret = n;
143 +
144 + return 0;
145 +}
146 +
147 +tree_match_ctx *
148 +tree_match_atom(tree_ctx *ctx, depend_atom *query, int flags)
149 {
150 tree_cat_ctx *cat_ctx;
151 tree_pkg_ctx *pkg_ctx;
152 + tree_match_ctx *ret = NULL;
153 depend_atom *atom;
154
155 + if (ctx->cachetype == CACHE_PACKAGES) {
156 + struct tree_match_pkgs_cb_ctx rctx;
157 + /* Packages needs to be serviced separately because it doesn't
158 + * use a tree internally, but reads off of the Packages file */
159 + rctx.flags = flags;
160 + rctx.ret = NULL;
161 + ctx->query_atom = query;
162 + tree_foreach_packages(ctx, tree_match_atom_packages_cb, &rctx);
163 + ctx->query_atom = NULL;
164 + return rctx.ret;
165 + } else if (ctx->cachetype == CACHE_BINPKGS) {
166 + struct tree_match_pkgs_cb_ctx rctx;
167 + /* this sulks, but binpkgs modify the pkg_ctx->name to strip off
168 + * .tbz2, and that makes it non-reusable */
169 + rctx.flags = flags;
170 + rctx.ret = NULL;
171 + tree_foreach_pkg(ctx, tree_match_atom_binpkg_cb, &rctx, true, query);
172 + return rctx.ret;
173 + }
174 +
175 + /* activate cache for future lookups, tree_match_atom relies on
176 + * cache behaviour from tree, which means all categories and
177 + * packages remain in memory until tree_close is being called */
178 if (ctx->cache.categories == NULL)
179 ctx->cache.categories = create_set();
180
181 - if (a->P == NULL) {
182 - return NULL;
183 - } else if (a->CATEGORY == NULL) {
184 - /* loop through all cats and recurse */
185 - /* TODO: some day */
186 - return NULL;
187 + ctx->do_sort = true; /* sort uses buffer, which cache relies on */
188 + ctx->query_atom = NULL; /* ensure the cache contains ALL pkgs */
189 +
190 +#define search_cat(C) \
191 +{ \
192 + while ((pkg_ctx = tree_next_pkg(C)) != NULL) { \
193 + atom = tree_get_atom(pkg_ctx, \
194 + query->SLOT != NULL || flags & TREE_MATCH_FULL_ATOM); \
195 +fprintf(stderr, "fbg: %s\n", atom_to_string(atom)); \
196 + if (flags & TREE_MATCH_VIRTUAL || \
197 + strcmp(atom->CATEGORY, "virtual") != 0) \
198 + if (atom_compare(atom, query) == EQUAL) { \
199 + tree_match_ctx *n; \
200 + n = xzalloc(sizeof(tree_match_ctx)); \
201 + n->free_atom = false; \
202 + n->atom = atom; \
203 + if (flags & TREE_MATCH_METADATA) \
204 + n->meta = tree_pkg_read(pkg_ctx); \
205 + n->next = ret; \
206 + ret = n; \
207 + } \
208 + if (flags & TREE_MATCH_FIRST && ret != NULL) \
209 + break; \
210 + } \
211 + C->pkg_cur = 0; /* reset to allow another traversal */ \
212 +}
213 +
214 + if (query->CATEGORY == NULL) {
215 + /* loop through all cats */
216 + while ((cat_ctx = tree_next_cat(ctx)) != NULL) {
217 + search_cat(cat_ctx);
218 + if (ret != NULL && flags & TREE_MATCH_FIRST)
219 + break;
220 + }
221 + /* allow running again through the cats */
222 + ctx->cat_cur = 0;
223 } else {
224 /* try CAT, and PN for latest version */
225 - if ((cat_ctx = tree_open_cat(ctx, a->CATEGORY)) == NULL)
226 - return NULL;
227 - ctx->do_sort = true; /* sort uses buffer, which cache relies on */
228 - ctx->query_atom = NULL; /* ensure the cache contains ALL pkgs */
229 - while ((pkg_ctx = tree_next_pkg(cat_ctx)) != NULL) {
230 - atom = tree_get_atom(pkg_ctx, a->SLOT != NULL);
231 - if (atom_compare(atom, a) == EQUAL)
232 - return pkg_ctx;
233 - }
234 + if ((cat_ctx = tree_open_cat(ctx, query->CATEGORY)) != NULL)
235 + search_cat(cat_ctx);
236 + }
237
238 - return NULL;
239 + return ret;
240 +}
241 +
242 +void
243 +tree_match_close(tree_match_ctx *match)
244 +{
245 + tree_match_ctx *w;
246 +
247 + for (w = NULL; match != NULL; match = w) {
248 + w = match->next;
249 + if (match->free_atom)
250 + atom_implode(match->atom);
251 + if (match->meta != NULL)
252 + free(match->meta);
253 + free(match);
254 }
255 }
256
257 diff --git a/libq/tree.h b/libq/tree.h
258 index eaee7ad..900b998 100644
259 --- a/libq/tree.h
260 +++ b/libq/tree.h
261 @@ -18,6 +18,7 @@ typedef struct tree_cat_ctx tree_cat_ctx;
262 typedef struct tree_pkg_ctx tree_pkg_ctx;
263 typedef struct tree_pkg_meta tree_pkg_meta;
264 typedef struct tree_metadata_xml tree_metadata_xml;
265 +typedef struct tree_match_ctx tree_match_ctx;
266
267 /* tree context */
268 struct tree_ctx {
269 @@ -100,6 +101,9 @@ struct tree_pkg_meta {
270 char *Q_USE;
271 char *Q_EPREFIX;
272 char *Q_repository;
273 + char *Q_MD5;
274 + char *Q_SHA1;
275 +#define Q_SIZE Q_SRC_URI
276 /* These are MD5-Cache only */
277 char *Q__eclasses_;
278 char *Q__md5_;
279 @@ -113,6 +117,15 @@ struct tree_metadata_xml {
280 } *email;
281 };
282
283 +/* used with tree_match_atom, both atom and meta are fully materialised
284 + * (populated and deep copied) when set */
285 +struct tree_match_ctx {
286 + depend_atom *atom;
287 + tree_pkg_meta *meta;
288 + tree_match_ctx *next;
289 + int free_atom;
290 +};
291 +
292 /* foreach pkg callback function signature */
293 typedef int (tree_pkg_cb)(tree_pkg_ctx *, void *priv);
294
295 @@ -138,6 +151,12 @@ int tree_foreach_pkg(tree_ctx *ctx, tree_pkg_cb callback, void *priv,
296 tree_foreach_pkg(ctx, cb, priv, true, query);
297 set *tree_get_atoms(tree_ctx *ctx, bool fullcpv, set *satoms);
298 depend_atom *tree_get_atom(tree_pkg_ctx *pkg_ctx, bool complete);
299 -tree_pkg_ctx *tree_match_atom(tree_ctx *t, depend_atom *a);
300 +tree_match_ctx *tree_match_atom(tree_ctx *t, depend_atom *q, int flags);
301 +#define TREE_MATCH_FULL_ATOM 1<<1
302 +#define TREE_MATCH_METADATA 1<<2
303 +#define TREE_MATCH_FIRST 1<<3
304 +#define TREE_MATCH_VIRTUAL 1<<4
305 +#define TREE_MATCH_DEFAULT TREE_MATCH_VIRTUAL
306 +void tree_match_close(tree_match_ctx *t);
307
308 #endif