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: /
Date: Mon, 25 May 2020 10:44:04
Message-Id: 1590403145.f2e63b4a1280d0a2c18cb1a66ceffd9699d1b9ac.grobian@gentoo
1 commit: f2e63b4a1280d0a2c18cb1a66ceffd9699d1b9ac
2 Author: Fabian Groffen <grobian <AT> gentoo <DOT> org>
3 AuthorDate: Mon May 25 10:39:05 2020 +0000
4 Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org>
5 CommitDate: Mon May 25 10:39:05 2020 +0000
6 URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=f2e63b4a
7
8 qmerge: use libq/tree for binpkg/Packages needs
9
10 Instead of manual parsing of Packages file and traversing binpkgs, use
11 the functionality provided by libq/tree, most notably tree_match_atom().
12
13 This is just phase one, where we replace the custom code with libq/tree
14 code and then fill in the Pkg structure. In a next phase we should skip
15 this and directly use tree_match_ctx, with atom and meta in there.
16
17 Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>
18
19 qmerge.c | 596 +++++++++++++--------------------------------------------------
20 1 file changed, 116 insertions(+), 480 deletions(-)
21
22 diff --git a/qmerge.c b/qmerge.c
23 index 087c5f2..554e3dc 100644
24 --- a/qmerge.c
25 +++ b/qmerge.c
26 @@ -120,8 +120,7 @@ typedef struct llist_char_t llist_char;
27 static void pkg_fetch(int, const depend_atom *, const struct pkg_t *);
28 static void pkg_merge(int, const depend_atom *, const struct pkg_t *);
29 static int pkg_unmerge(tree_pkg_ctx *, set *, int, char **, int, char **);
30 -static struct pkg_t *grab_binpkg_info(const char *);
31 -static char *find_binpkg(const char *);
32 +static struct pkg_t *grab_binpkg_info(depend_atom *);
33
34 static bool
35 prompt(const char *p)
36 @@ -129,12 +128,12 @@ prompt(const char *p)
37 printf("%s? [Y/n] ", p);
38 fflush(stdout);
39 switch (getc(stdin)) {
40 - case '\n':
41 - case 'y':
42 - case 'Y':
43 - return true;
44 - default:
45 - return false;
46 + case '\n':
47 + case 'y':
48 + case 'Y':
49 + return true;
50 + default:
51 + return false;
52 }
53 }
54
55 @@ -579,7 +578,7 @@ qprint_tree_node(int level, const depend_atom *atom, const struct pkg_t *pkg)
56 } else {
57 depend_atom *subatom = atom_explode(p);
58 if (subatom != NULL) {
59 - ret = atom_compare(atom, subatom);
60 + ret = atom_compare(subatom, atom);
61 switch (ret) {
62 case EQUAL: c = 'R'; break;
63 case NEWER: c = 'U'; break;
64 @@ -1009,7 +1008,7 @@ pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg)
65 if (((c == 'R') || (c == 'D')) && update_only)
66 return;
67
68 - if (pkg->RDEPEND[0] && follow_rdepends) {
69 + if (pkg->RDEPEND[0] != '\0' && follow_rdepends) {
70 const char *rdepend;
71
72 IF_DEBUG(fprintf(stderr, "\n+Parent: %s/%s\n", pkg->CATEGORY, pkg->PF));
73 @@ -1040,30 +1039,17 @@ pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg)
74 case '\0':
75 break;
76 default:
77 - if (*name == '~') {
78 - name = ARGV[i] + 1;
79 - /* warn("newname = %s", name); */
80 - }
81 if ((subatom = atom_explode(name)) != NULL) {
82 struct pkg_t *subpkg;
83 - char *resolved = NULL;
84 -
85 - resolved = find_binpkg(name);
86
87 - IF_DEBUG(fprintf(stderr,
88 - "+Atom: argv0(%s) resolved(%s)\n",
89 - name, resolved));
90 -
91 - if (strlen(resolved) < 1) {
92 - warn("Cant find a binpkg for %s from rdepend(%s)",
93 + subpkg = grab_binpkg_info(subatom); /* free me later */
94 + if (subpkg == NULL) {
95 + warn("Cannot find a binpkg for %s from rdepend(%s)",
96 name, pkg->RDEPEND);
97 atom_implode(subatom);
98 continue;
99 }
100
101 - /* ratom = atom_explode(resolved); */
102 - subpkg = grab_binpkg_info(resolved); /* free me later */
103 -
104 assert(subpkg != NULL);
105 IF_DEBUG(fprintf(stderr, "+Subpkg: %s/%s\n",
106 subpkg->CATEGORY, subpkg->PF));
107 @@ -1182,7 +1168,8 @@ pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg)
108 } else if (mlen == 257+6 &&
109 magic[257] == 'u' && magic[258] == 's' &&
110 magic[259] == 't' && magic[260] == 'a' &&
111 - magic[261] == 'r' && magic[262] == '\0')
112 + magic[261] == 'r' &&
113 + (magic[262] == '\0' || magic[262] == ' '))
114 {
115 compr = "";
116 } else if (mlen >= 4 &&
117 @@ -1399,7 +1386,7 @@ pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg)
118 rmdir("../qmerge");
119
120 printf("%s>>>%s %s%s%s/%s%s%s\n",
121 - YELLOW, NORM, WHITE, atom->CATEGORY, NORM, CYAN, pkg->PF, NORM);
122 + YELLOW, NORM, WHITE, pkg->CATEGORY, NORM, CYAN, pkg->PF, NORM);
123
124 tree_close_cat(cat_ctx);
125 tree_close(vdb);
126 @@ -1622,7 +1609,7 @@ pkg_verify_checksums(
127 }
128
129 if (pkg->MD5[0]) {
130 - if (md5 != NULL && strcmp(md5, pkg->MD5) == 0) {
131 + if (strcmp(md5, pkg->MD5) == 0) {
132 if (display)
133 printf("MD5: [%sOK%s] %s %s/%s\n",
134 GREEN, NORM, md5, atom->CATEGORY, pkg->PF);
135 @@ -1634,7 +1621,7 @@ pkg_verify_checksums(
136 }
137 }
138
139 - if (sha1 != NULL && pkg->SHA1[0]) {
140 + if (pkg->SHA1[0]) {
141 if (strcmp(sha1, pkg->SHA1) == 0) {
142 if (display)
143 qprintf("SHA1: [%sOK%s] %s %s/%s\n",
144 @@ -1663,7 +1650,8 @@ pkg_fetch(int level, const depend_atom *atom, const struct pkg_t *pkg)
145
146 /* qmerge -pv patch */
147 if (pretend) {
148 - if (!install) install++;
149 + if (!install)
150 + install++;
151 /* qprint_tree_node(level, atom, pkg); */
152 pkg_merge(level, atom, pkg);
153 return;
154 @@ -1679,13 +1667,12 @@ pkg_fetch(int level, const depend_atom *atom, const struct pkg_t *pkg)
155 return;
156 }
157
158 - /* XXX: should do a size check here for partial downloads */
159 -
160 if (force_download && (access(buf, R_OK) == 0) &&
161 (pkg->SHA1[0] || pkg->MD5[0]))
162 {
163 if (pkg_verify_checksums(buf, pkg, atom, 0, 0) != 0)
164 - unlink(buf);
165 + if (getenv("QMERGE") == NULL)
166 + unlink(buf);
167 }
168 if (access(buf, R_OK) == 0) {
169 if (!pkg->SHA1[0] && !pkg->MD5[0]) {
170 @@ -1742,7 +1729,7 @@ print_Pkg(int full, const depend_atom *atom, const struct pkg_t *pkg)
171 char *p = NULL;
172 char buf[512];
173
174 - printf("%s%s/%s%s:%s%s%s%s%s\n", BOLD, atom->CATEGORY, BLUE, pkg->PF, pkg->SLOT, NORM,
175 + printf("%s%s%s%s\n", atom_format("%[CAT]%[PF]%[SLOT]", atom),
176 !quiet ? " [" : "",
177 !quiet ? make_human_readable_str(pkg->SIZE, 1, KILOBYTE) : "",
178 !quiet ? " KiB]" : "");
179 @@ -1757,7 +1744,8 @@ print_Pkg(int full, const depend_atom *atom, const struct pkg_t *pkg)
180 if (pkg->MD5[0])
181 printf(" %sMd5%s:%s %s\n", DKGREEN, YELLOW, NORM, pkg->MD5);
182 if (!pkg->MD5[0] && !pkg->SHA1[0])
183 - printf(" %sSums%s:%s %s(MISSING!)%s\n", DKGREEN, YELLOW, NORM, RED, NORM);
184 + printf(" %sSums%s:%s %s(MISSING!)%s\n",
185 + DKGREEN, YELLOW, NORM, RED, NORM);
186 if (pkg->SLOT[0])
187 printf(" %sSlot%s:%s %s\n", DKGREEN, YELLOW, NORM, pkg->SLOT);
188 if (pkg->LICENSE[0])
189 @@ -1781,7 +1769,8 @@ print_Pkg(int full, const depend_atom *atom, const struct pkg_t *pkg)
190 case OLDER: icolor = BLUE; break;
191 default: icolor = NORM; break;
192 }
193 - printf(" %sInstalled%s:%s %s%s%s\n", DKGREEN, YELLOW, NORM, icolor, p, NORM);
194 + printf(" %sInstalled%s:%s %s%s%s\n",
195 + DKGREEN, YELLOW, NORM, icolor, p, NORM);
196 }
197 }
198 }
199 @@ -1833,453 +1822,70 @@ unmerge_packages(set *todo)
200 return ret;
201 }
202
203 -static FILE *
204 -open_binpkg_index(void)
205 -{
206 - FILE *fp;
207 - char *path;
208 -
209 - xasprintf(&path, "%s/portage/%s", port_tmpdir, Packages);
210 - fp = fopen(path, "r");
211 - if (fp)
212 - goto done;
213 - free(path);
214 -
215 - xasprintf(&path, "%s/%s", pkgdir, Packages);
216 - fp = fopen(path, "r");
217 - if (fp)
218 - goto done;
219 -
220 - /* This is normal when installing from local repo only. */
221 - warnp("Unable to open package file %s in %s/portage or %s",
222 - Packages, port_tmpdir, pkgdir);
223 - warn("Attempting to manually regen via `emaint binhost`");
224 -
225 - pid_t p;
226 - int status;
227 -
228 - char argv_emaint[] = "emaint";
229 - char argv_binhost[] = "binhost";
230 - char argv_fix[] = "--fix";
231 - char *argv[] = {
232 - argv_emaint,
233 - argv_binhost,
234 - argv_fix,
235 - NULL,
236 - };
237 -
238 - p = vfork();
239 - switch (p) {
240 - case 0:
241 - _exit(execvp(argv[0], argv));
242 - case -1:
243 - errp("vfork failed");
244 - }
245 - waitpid(p, &status, 0);
246 -
247 - fp = fopen(path, "r");
248 -
249 - done:
250 - free(path);
251 - return fp;
252 -}
253 -
254 +static tree_ctx *_grab_binpkg_info_tree = NULL;
255 static struct pkg_t *
256 -grab_binpkg_info(const char *name)
257 -{
258 - FILE *fp;
259 - char buf[BUFSIZ];
260 - char *p;
261 - depend_atom *atom;
262 -
263 - struct pkg_t Pkg;
264 - struct pkg_t *pkg = xzalloc(sizeof(struct pkg_t));
265 - struct pkg_t *rpkg = xzalloc(sizeof(struct pkg_t));
266 -
267 - static char best_match[sizeof(Pkg.PF)+2+sizeof(Pkg.CATEGORY)];
268 -
269 - best_match[0] = 0;
270 - strcpy(pkg->SLOT,"0");
271 -
272 - fp = open_binpkg_index();
273 -
274 - while (fgets(buf, sizeof(buf), fp) != NULL) {
275 - if (*buf == '\n') {
276 - if (pkg->PF[0] && pkg->CATEGORY[0]) {
277 - int ret;
278 -
279 - snprintf(buf, sizeof(buf), "%s/%s", pkg->CATEGORY, pkg->PF);
280 - if (strstr(buf, name) != NULL) {
281 - if (!best_match[0])
282 - snprintf(best_match, sizeof(best_match), "%.*s",
283 - (int)sizeof(best_match) - 1, buf);
284 -
285 - atom = atom_explode(buf);
286 - if (atom->PR_int) {
287 - snprintf(buf, sizeof(buf), "%s/%s-%s-r%i",
288 - atom->CATEGORY, atom->PN,
289 - atom->PV, atom->PR_int);
290 - } else {
291 - snprintf(buf, sizeof(buf), "%s/%s-%s",
292 - atom->CATEGORY, atom->PN, atom->PV);
293 - }
294 - ret = atom_compare_str(name, buf);
295 - IF_DEBUG(fprintf(stderr,
296 - "=== atom_compare(%s, %s) = %d %s\n",
297 - name, buf, ret, booga[ret]));
298 - /* buf(%s) depend(%s)\n", ret, pkg->CATEGORY,
299 - * pkg->PF, name, pkg->RDEPEND); */
300 - switch (ret) {
301 - case EQUAL:
302 - case NEWER:
303 - snprintf(buf, sizeof(buf), "%s/%s",
304 - pkg->CATEGORY, pkg->PF);
305 - ret = atom_compare_str(buf, best_match);
306 - if (ret == NEWER || ret == EQUAL) {
307 - snprintf(best_match, sizeof(best_match), "%.*s",
308 - (int)sizeof(best_match) - 1, buf);
309 - memcpy(rpkg, pkg, sizeof(struct pkg_t));
310 - IF_DEBUG(fprintf(stderr,
311 - "--- %s/%s depend(%s)\n",
312 - rpkg->CATEGORY, rpkg->PF,
313 - rpkg->RDEPEND));
314 - }
315 - case OLDER: break;
316 - default:
317 - break;
318 - }
319 - atom_implode(atom);
320 - }
321 - memset(pkg, 0, sizeof(struct pkg_t));
322 - strcpy(pkg->SLOT,"0");
323 - }
324 - continue;
325 - }
326 -
327 - if ((p = strchr(buf, '\n')) != NULL)
328 - *p = 0;
329 - if ((p = strchr(buf, ':')) == NULL)
330 - continue;
331 - if (p[1] != ' ')
332 - continue;
333 - *p = 0;
334 - p += 2;
335 -
336 - if (*buf) {
337 - /* we dont need all the info */
338 - if (strcmp(buf, "RDEPEND") == 0)
339 - snprintf(pkg->RDEPEND, sizeof(Pkg.RDEPEND), "%.*s",
340 - (int)sizeof(Pkg.RDEPEND) - 1, p);
341 - if (strcmp(buf, "PF") == 0)
342 - snprintf(pkg->PF, sizeof(Pkg.PF), "%.*s",
343 - (int)sizeof(Pkg.PF) - 1, p);
344 - if (strcmp(buf, "CATEGORY") == 0)
345 - snprintf(pkg->CATEGORY, sizeof(Pkg.CATEGORY), "%.*s",
346 - (int)sizeof(Pkg.CATEGORY) - 1, p);
347 - if (strcmp(buf, "REPO") == 0)
348 - snprintf(pkg->REPO, sizeof(Pkg.REPO), "%.*s",
349 - (int)sizeof(Pkg.REPO) - 1, p);
350 -
351 - if (strcmp(buf, "CPV") == 0) {
352 - if ((atom = atom_explode(p)) != NULL) {
353 - if (atom->PR_int) {
354 - snprintf(buf, sizeof(buf), "%s-%s-r%i",
355 - atom->PN, atom->PV, atom->PR_int);
356 - } else {
357 - snprintf(buf, sizeof(buf), "%s-%s", atom->PN, atom->PV);
358 - }
359 - snprintf(pkg->PF, sizeof(Pkg.PF), "%.*s",
360 - (int)sizeof(Pkg.PF) - 1, buf);
361 - snprintf(pkg->CATEGORY, sizeof(Pkg.CATEGORY), "%.*s",
362 - (int)sizeof(Pkg.CATEGORY) - 1, atom->CATEGORY);
363 - atom_implode(atom);
364 - }
365 - }
366 - if (strcmp(buf, "SLOT") == 0)
367 - snprintf(pkg->SLOT, sizeof(Pkg.SLOT), "%.*s",
368 - (int)sizeof(Pkg.SLOT) - 1, p);
369 - if (strcmp(buf, "USE") == 0)
370 - snprintf(pkg->USE, sizeof(Pkg.USE), "%.*s",
371 - (int)sizeof(Pkg.USE) - 1, p);
372 - /* checksums. We must have 1 or the other unless --*/
373 - if (strcmp(buf, "MD5") == 0)
374 - snprintf(pkg->MD5, sizeof(Pkg.MD5), "%.*s",
375 - (int)sizeof(Pkg.MD5) - 1, p);
376 - if (strcmp(buf, "SHA1") == 0)
377 - snprintf(pkg->SHA1, sizeof(Pkg.SHA1), "%.*s",
378 - (int)sizeof(Pkg.SHA1) - 1, p);
379 - }
380 - }
381 - fclose(fp);
382 - free(pkg);
383 - return rpkg;
384 -}
385 -
386 -static char *
387 -find_binpkg(const char *name)
388 +grab_binpkg_info(depend_atom *atom)
389 {
390 - FILE *fp;
391 - char buf[BUFSIZ];
392 - char *p;
393 - struct pkg_t Pkg;
394 - char PF[sizeof(Pkg.PF)];
395 - char CATEGORY[sizeof(Pkg.CATEGORY)];
396 -
397 - static char best_match[sizeof(Pkg.PF)+2+sizeof(Pkg.CATEGORY)];
398 -
399 - best_match[0] = 0;
400 - if (NULL == name)
401 - return best_match;
402 -
403 - fp = open_binpkg_index();
404 - PF[0] = CATEGORY[0] = '\0';
405 -
406 - while (fgets(buf, sizeof(buf), fp) != NULL) {
407 - if (*buf == '\n') {
408 - if (PF[0] && CATEGORY[0]) {
409 - int ret;
410 - snprintf(buf, sizeof(buf), "%s/%s", CATEGORY, PF);
411 - if (strstr(buf, name) != NULL) {
412 - depend_atom *atom;
413 -
414 - if (!best_match[0])
415 - snprintf(best_match, sizeof(best_match), "%.*s",
416 - (int)sizeof(best_match) - 1, buf);
417 -
418 - atom = atom_explode(buf);
419 - snprintf(buf, sizeof(buf), "%s/%s",
420 - atom->CATEGORY, atom->PN);
421 - ret = atom_compare_str(name, buf);
422 - switch (ret) {
423 - case OLDER: break;
424 - case NEWER:
425 - case EQUAL:
426 - snprintf(buf, sizeof(buf), "%s/%s", CATEGORY, PF);
427 - ret = atom_compare_str(buf, best_match);
428 - if (ret == NEWER || ret == EQUAL)
429 - snprintf(best_match, sizeof(best_match), "%.*s",
430 - (int)sizeof(best_match) - 1, buf);
431 - /* printf("[%s == %s] = %d; %s/%s\n",
432 - * name, buf, ret, CATEGORY, PF); */
433 - default:
434 - break;
435 - }
436 - atom_implode(atom);
437 - }
438 - }
439 - continue;
440 - }
441 -
442 - if ((p = strchr(buf, '\n')) != NULL)
443 - *p = 0;
444 - if ((p = strchr(buf, ':')) == NULL)
445 - continue;
446 - if (p[1] != ' ')
447 - continue;
448 - *p = 0;
449 - p += 2;
450 -
451 - if (*buf) {
452 - if (strcmp(buf, "CPV") == 0) {
453 - depend_atom *atom;
454 - if ((atom = atom_explode(p)) != NULL) {
455 - if (atom->PR_int) {
456 - snprintf(buf, sizeof(buf), "%s-%s-r%i",
457 - atom->PN, atom->PV, atom->PR_int);
458 - } else {
459 - snprintf(buf, sizeof(buf), "%s-%s", atom->PN, atom->PV);
460 - }
461 - snprintf(PF, sizeof(PF), "%.*s", (int)sizeof(PF) - 1, buf);
462 - snprintf(CATEGORY, sizeof(CATEGORY), "%.*s",
463 - (int)sizeof(CATEGORY) - 1, atom->CATEGORY);
464 - atom_implode(atom);
465 - }
466 - }
467 - if (strcmp(buf, "PF") == 0)
468 - snprintf(PF, sizeof(PF), "%.*s", (int)sizeof(PF) - 1, p);
469 - if (strcmp(buf, "CATEGORY") == 0)
470 - snprintf(CATEGORY, sizeof(CATEGORY), "%.*s",
471 - (int)sizeof(CATEGORY) - 1, p);
472 - }
473 - }
474 - fclose(fp);
475 - return best_match;
476 -}
477 -
478 -static int
479 -parse_packages(set *todo)
480 -{
481 - FILE *fp;
482 - int linelen;
483 - size_t buflen;
484 - char *buf, *p;
485 - struct pkg_t Pkg;
486 - depend_atom *pkg_atom;
487 - char repo[sizeof(Pkg.REPO)];
488 - depend_atom **todo_atoms = NULL;
489 - size_t todo_cnt = 0;
490 - size_t i;
491 -
492 - fp = open_binpkg_index();
493 - if (fp == NULL)
494 - return EXIT_FAILURE;
495 -
496 - buf = NULL;
497 - buflen = 0; /* make getline allocate */
498 - repo[0] = '\0';
499 -
500 - /* First consume the header with the common data. */
501 - while ((linelen = getline(&buf, &buflen, fp)) >= 0) {
502 - rmspace_len(buf, (size_t)linelen);
503 - if (buf[0] == '\0')
504 - break;
505 -
506 - if ((p = strchr(buf, ':')) == NULL)
507 - continue;
508 - if (p[1] != ' ')
509 - continue;
510 - *p = 0;
511 - p += 2;
512 -
513 - switch (*buf) {
514 - case 'R':
515 - if (!strcmp(buf, "REPO"))
516 - snprintf(repo, sizeof(repo), "%.*s", (int)sizeof(repo) - 1, p);
517 - break;
518 + tree_ctx *tree = _grab_binpkg_info_tree;
519 + tree_match_ctx *tpkg;
520 + struct pkg_t *pkg = NULL;
521 + char path[BUFSIZ];
522 + FILE *d;
523 +
524 + /* reuse previously opened tree, so we really employ the cache
525 + * from libq/tree */
526 + if (tree == NULL) {
527 + snprintf(path, sizeof(path), "%s/portage/Packages", port_tmpdir);
528 + /* we don't use ROOT on package tree here, operating on ROOT
529 + * should be for package merges/unmerges, but be able to pull
530 + * binpkgs from current system */
531 + if ((d = fopen(path, "r")) != NULL) {
532 + fclose(d);
533 + snprintf(path, sizeof(path), "%s/portage", port_tmpdir);
534 + tree = tree_open_binpkg("/", path);
535 + } else {
536 + tree = tree_open_binpkg("/", pkgdir);
537 }
538 - }
539 + _grab_binpkg_info_tree = tree;
540
541 - pkg_atom = NULL;
542 - memset(&Pkg, 0, sizeof(Pkg));
543 - strcpy(Pkg.SLOT, "0");
544 -
545 - /* build list with exploded atoms for each access below */
546 - if (todo != NULL) {
547 - char **todo_strs;
548 - todo_cnt = list_set(todo, &todo_strs);
549 - todo_atoms = xmalloc(sizeof(*todo_atoms) * todo_cnt);
550 - for (i = 0; i < todo_cnt; i++)
551 - todo_atoms[i] = atom_explode(todo_strs[i]);
552 - free(todo_strs);
553 + /* if opening the tree failed somehow, we can't return anything */
554 + if (tree == NULL)
555 + return NULL;
556 }
557
558 - /* Then walk all the package entries. */
559 - while (getline(&buf, &buflen, fp) != -1) {
560 - if (*buf == '\n') {
561 - if (pkg_atom) {
562 - if (search_pkgs && !todo) {
563 - print_Pkg(verbose, pkg_atom, &Pkg);
564 - } else {
565 - for (i = 0; i < todo_cnt; i++) {
566 - pkg_atom->REPO = todo_atoms[i]->REPO ? Pkg.REPO : NULL;
567 - pkg_atom->SLOT = todo_atoms[i]->SLOT ? Pkg.SLOT : NULL;
568 - if (atom_compare(pkg_atom, todo_atoms[i]) == EQUAL) {
569 - if (search_pkgs)
570 - print_Pkg(verbose, pkg_atom, &Pkg);
571 - else
572 - pkg_fetch(0, pkg_atom, &Pkg);
573 - }
574 - }
575 - }
576
577 - atom_implode(pkg_atom);
578 - pkg_atom = NULL;
579 - }
580 - memset(&Pkg, 0, sizeof(Pkg));
581 - strcpy(Pkg.SLOT, "0");
582 - strcpy(Pkg.REPO, repo);
583 - continue;
584 - }
585 -
586 - if ((p = strchr(buf, '\n')) != NULL)
587 - *p = 0;
588 - if ((p = strchr(buf, ':')) == NULL)
589 - continue;
590 - if (p[1] != ' ')
591 - continue;
592 - *p = 0;
593 - p += 2;
594 -
595 - switch (*buf) {
596 - case 'U':
597 - if (strcmp(buf, "USE") == 0)
598 - snprintf(Pkg.USE, sizeof(Pkg.USE), "%.*s",
599 - (int)sizeof(Pkg.USE) - 1, p);
600 - break;
601 - case 'P':
602 - if (strcmp(buf, "PF") == 0)
603 - snprintf(Pkg.PF, sizeof(Pkg.PF), "%.*s",
604 - (int)sizeof(Pkg.PF) - 1, p);
605 - break;
606 - case 'S':
607 - if (strcmp(buf, "SIZE") == 0)
608 - Pkg.SIZE = atol(p);
609 - if (strcmp(buf, "SLOT") == 0)
610 - snprintf(Pkg.SLOT, sizeof(Pkg.SLOT), "%.*s",
611 - (int)sizeof(Pkg.SLOT) - 1, p);
612 - if (strcmp(buf, "SHA1") == 0)
613 - snprintf(Pkg.SHA1, sizeof(Pkg.SHA1), "%.*s",
614 - (int)sizeof(Pkg.SHA1) - 1, p);
615 - break;
616 - case 'M':
617 - if (strcmp(buf, "MD5") == 0)
618 - snprintf(Pkg.MD5, sizeof(Pkg.MD5), "%.*s",
619 - (int)sizeof(Pkg.MD5) - 1, p);
620 - break;
621 - case 'R':
622 - if (strcmp(buf, "REPO") == 0)
623 - snprintf(Pkg.REPO, sizeof(Pkg.REPO), "%.*s",
624 - (int)sizeof(Pkg.REPO) - 1, p);
625 - if (strcmp(buf, "RDEPEND") == 0)
626 - snprintf(Pkg.RDEPEND, sizeof(Pkg.RDEPEND), "%.*s",
627 - (int)sizeof(Pkg.RDEPEND) - 1, p);
628 - break;
629 - case 'L':
630 - if (strcmp(buf, "LICENSE") == 0)
631 - snprintf(Pkg.LICENSE, sizeof(Pkg.LICENSE), "%.*s",
632 - (int)sizeof(Pkg.LICENSE) - 1, p);
633 - break;
634 - case 'C':
635 - if (strcmp(buf, "CATEGORY") == 0)
636 - snprintf(Pkg.CATEGORY, sizeof(Pkg.CATEGORY), "%.*s",
637 - (int)sizeof(Pkg.CATEGORY) - 1, p);
638 - if (strcmp(buf, "CPV") == 0) {
639 - if (pkg_atom != NULL) /* hypothetical Coverity case */
640 - atom_implode(pkg_atom);
641 - if ((pkg_atom = atom_explode(p)) != NULL) {
642 - if (pkg_atom->PR_int)
643 - snprintf(Pkg.PF, sizeof(Pkg.PF), "%s-%s-r%i",
644 - pkg_atom->PN, pkg_atom->PV,
645 - pkg_atom->PR_int);
646 - else
647 - snprintf(Pkg.PF, sizeof(Pkg.PF), "%s-%s",
648 - pkg_atom->PN, pkg_atom->PV);
649 - snprintf(Pkg.CATEGORY, sizeof(Pkg.CATEGORY),
650 - "%.*s", (int)sizeof(Pkg.CATEGORY) - 1,
651 - pkg_atom->CATEGORY);
652 - }
653 - }
654 - break;
655 - case 'D':
656 - if (strcmp(buf, "DESC") == 0)
657 - snprintf(Pkg.DESC, sizeof(Pkg.DESC), "%.*s",
658 - (int)sizeof(Pkg.DESC) - 1, p);
659 - break;
660 - default:
661 - break;
662 - }
663 + tpkg = tree_match_atom(tree, atom,
664 + TREE_MATCH_FIRST | TREE_MATCH_VIRTUAL | TREE_MATCH_METADATA);
665 + if (tpkg != NULL) {
666 + depend_atom *tatom = tpkg->atom;
667 + tree_pkg_meta *meta = tpkg->meta;
668 + pkg = xzalloc(sizeof(struct pkg_t));
669 +
670 + snprintf(pkg->PF, sizeof(pkg->PF), "%s", tatom->PF);
671 + snprintf(pkg->CATEGORY, sizeof(pkg->CATEGORY), "%s", tatom->CATEGORY);
672 + if (meta->Q_DESCRIPTION != NULL)
673 + snprintf(pkg->DESC, sizeof(pkg->DESC), "%s", meta->Q_DESCRIPTION);
674 + if (meta->Q_LICENSE != NULL)
675 + snprintf(pkg->LICENSE, sizeof(pkg->LICENSE), "%s", meta->Q_LICENSE);
676 + if (meta->Q_RDEPEND != NULL)
677 + snprintf(pkg->RDEPEND, sizeof(pkg->RDEPEND), "%s", meta->Q_RDEPEND);
678 + if (meta->Q_MD5 != NULL)
679 + snprintf(pkg->MD5, sizeof(pkg->MD5), "%s", meta->Q_MD5);
680 + if (meta->Q_SHA1 != NULL)
681 + snprintf(pkg->SHA1, sizeof(pkg->SHA1), "%s", meta->Q_SHA1);
682 + if (meta->Q_USE != NULL)
683 + snprintf(pkg->USE, sizeof(pkg->USE), "%s", meta->Q_USE);
684 + if (meta->Q_repository != NULL)
685 + snprintf(pkg->REPO, sizeof(pkg->REPO), "%s", meta->Q_repository);
686 + if (meta->Q_SLOT != NULL)
687 + snprintf(pkg->REPO, sizeof(pkg->REPO), "%s", meta->Q_SLOT);
688 + if (meta->Q_SIZE != NULL)
689 + pkg->SIZE = atoi(meta->Q_SIZE);
690 +
691 + tree_match_close(tpkg);
692 }
693
694 - free(buf);
695 - fclose(fp);
696 - if (pkg_atom)
697 - atom_implode(pkg_atom);
698 -
699 - for (i = 0; i < todo_cnt; i++)
700 - atom_implode(todo_atoms[i]);
701 - free(todo_atoms);
702 -
703 - return EXIT_SUCCESS;
704 + return pkg;
705 }
706
707 static set *
708 @@ -2366,10 +1972,40 @@ qmerge_add_set(char *buf, set *q)
709 static int
710 qmerge_run(set *todo)
711 {
712 - if (uninstall)
713 + if (uninstall) {
714 return unmerge_packages(todo);
715 - else
716 - return parse_packages(todo);
717 + } else {
718 + if (todo == NULL && search_pkgs) {
719 + /* disputable, this should be qlist -kIv or something */
720 + warn("please use qlist -kI");
721 +
722 + return EXIT_SUCCESS;
723 + } else {
724 + char **todo_strs;
725 + size_t todo_cnt = list_set(todo, &todo_strs);
726 + size_t i;
727 + depend_atom *atom;
728 + struct pkg_t *pkg;
729 + int ret = EXIT_FAILURE;
730 +
731 + for (i = 0; i < todo_cnt; i++) {
732 + atom = atom_explode(todo_strs[i]);
733 + pkg = grab_binpkg_info(atom);
734 + if (pkg != NULL) {
735 + if (search_pkgs)
736 + print_Pkg(verbose, atom, pkg);
737 + else
738 + pkg_fetch(0, atom, pkg);
739 + free(pkg);
740 + ret = EXIT_SUCCESS;
741 + }
742 + atom_implode(atom);
743 + }
744 + free(todo_strs);
745 +
746 + return ret;
747 + }
748 + }
749 }
750
751 int qmerge_main(int argc, char **argv)
752 @@ -2437,10 +2073,10 @@ int qmerge_main(int argc, char **argv)
753
754 if (uninstall) {
755 if (!prompt("OK to unmerge these packages"))
756 - return 0;
757 + return EXIT_FAILURE;
758 } else {
759 if (!prompt("OK to merge these packages"))
760 - return 0;
761 + return EXIT_FAILURE;
762 }
763
764 pretend = save_pretend;