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: tests/qmerge/, tests/qmerge/packages/sys-devel/, /, tests/qmerge/packages/
Date: Mon, 14 Jun 2021 09:34:20
Message-Id: 1623663122.f1cf942274c47dce50bbaff45d41a8a83102e3fd.grobian@gentoo
1 commit: f1cf942274c47dce50bbaff45d41a8a83102e3fd
2 Author: Fabian Groffen <grobian <AT> gentoo <DOT> org>
3 AuthorDate: Mon Jun 14 09:32:02 2021 +0000
4 Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org>
5 CommitDate: Mon Jun 14 09:32:02 2021 +0000
6 URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=f1cf9422
7
8 qmerge: once over to make better/more use of libq/tree
9
10 - unify best_version and grab_binpkg_info, into single function using
11 tree_match_atom to benefit from cache and abstract any particulars
12 - default to install action when no action given
13 - unmerge previous package on merge upgrade again
14 - possibly fix bug #792273 by exporting vars
15
16 Bug: https://bugs.gentoo.org/792273
17 Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>
18
19 qmerge.c | 782 ++++++++-------------
20 tests/qmerge/dotest | 52 +-
21 tests/qmerge/packages/Packages | 13 +
22 .../qmerge/packages/sys-devel/qmerge-test-2.0.tbz2 | Bin 0 -> 7334 bytes
23 4 files changed, 356 insertions(+), 491 deletions(-)
24
25 diff --git a/qmerge.c b/qmerge.c
26 index 8f1ca3d..f5386f2 100644
27 --- a/qmerge.c
28 +++ b/qmerge.c
29 @@ -49,8 +49,6 @@
30 /* #define BUSYBOX "/bin/busybox" */
31 #define BUSYBOX ""
32
33 -int old_repo = 0;
34 -
35 #define QMERGE_FLAGS "fFsKUpuyO" COMMON_FLAGS
36 static struct option const qmerge_long_opts[] = {
37 {"fetch", no_argument, NULL, 'f'},
38 @@ -91,25 +89,6 @@ char update_only = 0;
39 bool debug = false;
40 const char Packages[] = "Packages";
41
42 -/*
43 - "CHOST", "DEPEND", "DESCRIPTION", "EAPI",
44 - "IUSE", "KEYWORDS", "LICENSE", "PDEPEND",
45 - "PROVIDE", "RDEPEND", "SLOT", "USE"
46 -*/
47 -struct pkg_t {
48 - char PF[64];
49 - char CATEGORY[64];
50 - char DESC[126];
51 - char LICENSE[64];
52 - char RDEPEND[BUFSIZ];
53 - char MD5[34];
54 - char SHA1[42];
55 - char SLOT[64];
56 - size_t SIZE;
57 - char USE[BUFSIZ];
58 - char REPO[64];
59 -};
60 -
61 struct llist_char_t {
62 char *data;
63 struct llist_char_t *next;
64 @@ -117,17 +96,16 @@ struct llist_char_t {
65
66 typedef struct llist_char_t llist_char;
67
68 -static void pkg_fetch(int, const depend_atom *, const struct pkg_t *);
69 -static void pkg_merge(int, const depend_atom *, const struct pkg_t *);
70 +static void pkg_fetch(int, const depend_atom *, const tree_match_ctx *);
71 +static void pkg_merge(int, const depend_atom *, const tree_match_ctx *);
72 static int pkg_unmerge(tree_pkg_ctx *, set *, int, char **, int, char **);
73 -static struct pkg_t *grab_binpkg_info(depend_atom *);
74
75 static bool
76 -prompt(const char *p)
77 +qmerge_prompt(const char *p)
78 {
79 printf("%s? [Y/n] ", p);
80 fflush(stdout);
81 - switch (getc(stdin)) {
82 + switch (fgetc(stdin)) {
83 case '\n':
84 case 'y':
85 case 'Y':
86 @@ -143,8 +121,7 @@ fetch(const char *destdir, const char *src)
87 if (!binhost[0])
88 return;
89
90 - fflush(stdout);
91 - fflush(stderr);
92 + fflush(NULL);
93
94 #if 0
95 if (getenv("FETCHCOMMAND") != NULL) {
96 @@ -161,18 +138,15 @@ fetch(const char *destdir, const char *src)
97
98 xasprintf(&path, "%s/%s", binhost, src);
99
100 + /* wget -c -q -P <dir> <uri> */
101 char prog[] = "wget";
102 - char argv_c[] = "-c";
103 - char argv_P[] = "-P";
104 - char argv_q[] = "-q";
105 - char *argv_dir = xstrdup(destdir);
106 - char *argv[] = {
107 + char *const argv[] = {
108 prog,
109 - argv_c,
110 - argv_P,
111 - argv_dir,
112 + (char *)"-c",
113 + (char *)"-P",
114 + (char *)destdir,
115 path,
116 - quiet ? argv_q : NULL,
117 + quiet ? (char *)"-q" : NULL,
118 NULL,
119 };
120 if (!(force_download || install) && pretend)
121 @@ -187,7 +161,6 @@ fetch(const char *destdir, const char *src)
122 }
123
124 free(path);
125 - free(argv_dir);
126
127 waitpid(p, &status, 0);
128 #if 0
129 @@ -205,7 +178,7 @@ qmerge_initialize(void)
130 {
131 char *buf;
132
133 - if (strlen(BUSYBOX))
134 + if (strlen(BUSYBOX) > 0)
135 if (access(BUSYBOX, X_OK) != 0)
136 err(BUSYBOX " must be installed");
137
138 @@ -232,52 +205,78 @@ qmerge_initialize(void)
139 free(buf);
140 }
141
142 -static char _best_version_retbuf[4096];
143 -static int
144 -qmerge_best_version_cb(tree_pkg_ctx *pkg_ctx, void *priv)
145 +static tree_ctx *_qmerge_vdb_tree = NULL;
146 +static tree_ctx *_qmerge_binpkg_tree = NULL;
147 +#define BV_INSTALLED BV_VDB
148 +#define BV_BINARY BV_BINPKG
149 +#define BV_EBUILD (1<<0) /* not yet supported */
150 +#define BV_VDB (1<<1)
151 +#define BV_BINPKG (1<<2)
152 +static tree_match_ctx *
153 +best_version(const depend_atom *atom, int mode)
154 {
155 - depend_atom *sa = priv;
156 - depend_atom *a = tree_get_atom(pkg_ctx, true); /* need SLOT */
157 - if (atom_compare(a, sa) == EQUAL)
158 - snprintf(_best_version_retbuf, sizeof(_best_version_retbuf),
159 - "%s/%s:%s", a->CATEGORY, a->PF, a->SLOT);
160 - return 0;
161 -}
162 + tree_ctx *vdb = _qmerge_vdb_tree;
163 + tree_ctx *binpkg = _qmerge_binpkg_tree;
164 + tree_match_ctx *tmv = NULL;
165 + tree_match_ctx *tmp = NULL;
166 + tree_match_ctx *ret;
167 + int r;
168 +
169 + if (mode & BV_EBUILD) {
170 + warn("BV_EBUILD not yet supported");
171 + return NULL;
172 + }
173 + if (mode == 0) {
174 + warn("mode needs to be set");
175 + return NULL;
176 + }
177
178 -static char *
179 -best_version(const char *catname, const char *pkgname, const char *slot)
180 -{
181 - static int vdb_check = 1;
182 - tree_ctx *vdb;
183 -
184 - /* Make sure these dirs exist before we try walking them */
185 - switch (vdb_check) {
186 - case 1: {
187 - int fd = open(portroot, O_RDONLY|O_CLOEXEC|O_PATH);
188 - if (fd >= 0) {
189 - /* skip leading slash */
190 - vdb_check = faccessat(fd, portvdb + 1, X_OK, 0);
191 - close(fd);
192 - } else
193 - vdb_check = -1;
194 + if (mode & BV_VDB) {
195 + if (vdb == NULL) {
196 + vdb = tree_open_vdb(portroot, portvdb);
197 + if (vdb == NULL)
198 + return NULL;
199 + _qmerge_vdb_tree = vdb;
200 + }
201 + tmv = tree_match_atom(vdb, atom,
202 + TREE_MATCH_LATEST | TREE_MATCH_FIRST);
203 }
204 - if (vdb_check)
205 - case -1:
206 - goto done;
207 +
208 + if (mode & BV_BINPKG) {
209 + if (binpkg == NULL) {
210 + binpkg = tree_open_binpkg("/", pkgdir);
211 + if (binpkg == NULL) {
212 + if (tmv != NULL)
213 + tree_match_close(tmv);
214 + if (vdb != NULL)
215 + tree_close(vdb);
216 + return NULL;
217 + }
218 + _qmerge_binpkg_tree = binpkg;
219 + }
220 + tmp = tree_match_atom(binpkg, atom,
221 + TREE_MATCH_LATEST | TREE_MATCH_FIRST | TREE_MATCH_METADATA);
222 }
223
224 - snprintf(_best_version_retbuf, sizeof(_best_version_retbuf),
225 - "%s%s%s:%s", catname ? : "", catname ? "/" : "", pkgname, slot);
226 - vdb = tree_open_vdb(portroot, portvdb);
227 - if (vdb != NULL) {
228 - depend_atom *sa = atom_explode(_best_version_retbuf);
229 - tree_foreach_pkg_fast(vdb, qmerge_best_version_cb, sa, sa);
230 - tree_close(vdb);
231 - atom_implode(sa);
232 + if (tmv == NULL && tmp == NULL)
233 + ret = NULL;
234 + else if (tmv == NULL && tmp != NULL)
235 + ret = tmp;
236 + else if (tmv != NULL && tmp == NULL)
237 + ret = tmv;
238 + else {
239 + if ((r = atom_compare(tmv->atom, tmp->atom)) == EQUAL || r == OLDER)
240 + ret = tmp;
241 + else
242 + ret = tmv;
243 }
244
245 - done:
246 - return _best_version_retbuf;
247 + if (tmv != NULL && tmv != ret)
248 + tree_match_close(tmv);
249 + if (tmp != NULL && tmp != ret)
250 + tree_match_close(tmp);
251 +
252 + return ret;
253 }
254
255 static int
256 @@ -557,50 +556,47 @@ install_mask_pwd(int iargc, char **iargv, const struct stat * const st, int fd)
257 }
258
259 static char
260 -qprint_tree_node(int level, const depend_atom *atom, const struct pkg_t *pkg)
261 +qprint_tree_node(
262 + int level,
263 + const tree_match_ctx *mpkg,
264 + const tree_match_ctx *bpkg,
265 + int replacing)
266 {
267 - char buf[1024];
268 - char *p;
269 - int i, ret;
270 -
271 - char install_ver[126] = "";
272 - char c = 'N';
273 - const char *color;
274 + char buf[1024];
275 + int i;
276 + char install_ver[126] = "";
277 + char c = 'N';
278 + const char *color;
279
280 if (!pretend)
281 return 0;
282
283 - p = best_version(pkg->CATEGORY, atom->PN, pkg->SLOT);
284 -
285 - if (strlen(p) < 1) {
286 + if (bpkg == NULL) {
287 c = 'N';
288 snprintf(buf, sizeof(buf), "%sN%s", GREEN, NORM);
289 } else {
290 - depend_atom *subatom = atom_explode(p);
291 - if (subatom != NULL) {
292 - ret = atom_compare(subatom, atom);
293 - switch (ret) {
294 + if (bpkg != NULL) {
295 + switch (replacing) {
296 case EQUAL: c = 'R'; break;
297 case NEWER: c = 'U'; break;
298 case OLDER: c = 'D'; break;
299 - default: c = '?'; break;
300 + default: c = '?'; break;
301 }
302 snprintf(install_ver, sizeof(install_ver), "[%s%.*s%s] ",
303 DKBLUE,
304 (int)(sizeof(install_ver) - 4 -
305 sizeof(DKBLUE) - sizeof(NORM)),
306 - subatom->P, NORM);
307 - atom_implode(subatom);
308 + bpkg->atom->PVR, NORM);
309 }
310 if (update_only && c != 'U')
311 return c;
312 if ((c == 'R' || c == 'D') && update_only && level)
313 return c;
314 switch (c) {
315 - case 'R': color = YELLOW; break;
316 - case 'U': color = BLUE; break;
317 - case 'D': color = DKBLUE; break;
318 - default: color = RED; break;
319 + case 'R': color = YELLOW; break;
320 + case 'U': color = BLUE; break;
321 + case 'D': color = DKBLUE; break;
322 + default: color = RED; break;
323 }
324 snprintf(buf, sizeof(buf), "%s%c%s", color, c, NORM);
325 #if 0
326 @@ -615,14 +611,19 @@ qprint_tree_node(int level, const depend_atom *atom, const struct pkg_t *pkg)
327 }
328 #endif
329 }
330 +
331 printf("[%s] ", buf);
332 for (i = 0; i < level; ++i)
333 putchar(' ');
334 - if (verbose)
335 - printf("%s%s/%s%s %s%s%s%s%s%s\n", DKGREEN, pkg->CATEGORY, pkg->PF, NORM,
336 - install_ver, strlen(pkg->USE) > 0 ? "(" : "", RED, pkg->USE, NORM, strlen(pkg->USE) > 0 ? ")" : "");
337 - else
338 - printf("%s%s/%s%s\n", DKGREEN, pkg->CATEGORY, pkg->PF, NORM);
339 + if (verbose) {
340 + char *use = mpkg->meta->Q_USE; /* TODO: compute difference */
341 + printf("%s %s%s%s%s%s%s\n",
342 + atom_format("%[CAT]%[PF]", mpkg->atom),
343 + install_ver, use != NULL ? "(" : "",
344 + RED, use, NORM, use != NULL ? ")" : "");
345 + } else {
346 + printf("%s\n", atom_format("%[CAT]%[PF]", mpkg->atom));
347 + }
348 return c;
349 }
350
351 @@ -641,7 +642,7 @@ pkg_run_func_at(int dirfd, const char *vdb_path, const char *phases, const char
352 return;
353 }
354
355 - qprintf(">>> %s\n", func);
356 + qprintf("@@@ %s\n", func);
357
358 xasprintf(&script,
359 /* Provide funcs required by the PMS */
360 @@ -681,16 +682,16 @@ pkg_run_func_at(int dirfd, const char *vdb_path, const char *phases, const char
361 /* Load the main env */
362 ". '%1$s/environment'\n"
363 /* Reload env vars that matter to us */
364 - "FILESDIR=/.does/not/exist/anywhere\n"
365 - "MERGE_TYPE=binary\n"
366 - "ROOT='%4$s'\n"
367 - "EROOT=\"${ROOT%%/}${EPREFIX%%/}/\"\n"
368 - "D=\"%5$s\"\n"
369 - "ED=\"${D%%/}${EPREFIX%%/}/\"\n"
370 - "T=\"%6$s\"\n"
371 + "export FILESDIR=/.does/not/exist/anywhere\n"
372 + "export MERGE_TYPE=binary\n"
373 + "export ROOT='%4$s'\n"
374 + "export EROOT=\"${ROOT%%/}${EPREFIX%%/}/\"\n"
375 + "export D=\"%5$s\"\n"
376 + "export ED=\"${D%%/}${EPREFIX%%/}/\"\n"
377 + "export T=\"%6$s\"\n"
378 /* we do not support preserve-libs yet, so force
379 * preserve_old_lib instead */
380 - "FEATURES=\"${FEATURES/preserve-libs/disabled}\"\n"
381 + "export FEATURES=\"${FEATURES/preserve-libs/disabled}\"\n"
382 /* Finally run the func */
383 "%7$s%2$s\n"
384 /* Ignore func return values (not exit values) */
385 @@ -778,7 +779,7 @@ merge_tree_at(int fd_src, const char *src, int fd_dst, const char *dst,
386 if (!pretend)
387 fprintf(contents, "dir %s\n", cpath);
388 *objs = add_set(cpath, *objs);
389 - qprintf("%s>>>%s %s%s%s/\n", GREEN, NORM, DKBLUE, cpath, NORM);
390 + qprintf("%s---%s %s%s%s/\n", GREEN, NORM, DKBLUE, cpath, NORM);
391
392 /* Copy all of these contents */
393 merge_tree_at(subfd_src, name,
394 @@ -973,67 +974,78 @@ pkg_extract_xpak_cb(
395 }
396
397 /* oh shit getting into pkg mgt here. FIXME: write a real dep resolver. */
398 +static char *pm_phases;
399 +static size_t pm_phases_len;
400 static void
401 -pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg)
402 +pkg_merge(int level, const depend_atom *qatom, const tree_match_ctx *mpkg)
403 {
404 - set *objs;
405 - tree_ctx *vdb;
406 - tree_cat_ctx *cat_ctx;
407 - FILE *fp, *contents;
408 - static char *phases;
409 - static size_t phases_len;
410 - char *eprefix = NULL;
411 - size_t eprefix_len = 0;
412 - char buf[1024];
413 - char *tbz2, *p, *D, *T;
414 - int i;
415 - char **ARGV;
416 - int ARGC;
417 - struct stat st;
418 - char **iargv;
419 - char c;
420 - int iargc;
421 - const char *compr;
422 - int cp_argc;
423 - int cpm_argc;
424 - char **cp_argv;
425 - char **cpm_argv;
426 - int tbz2size;
427 -
428 - if (!install || !pkg || !atom)
429 + set *objs;
430 + tree_ctx *vdb;
431 + tree_cat_ctx *cat_ctx;
432 + tree_match_ctx *bpkg;
433 + tree_match_ctx *previnst;
434 + depend_atom *slotatom;
435 + FILE *fp;
436 + FILE *contents;
437 + char *eprefix = NULL;
438 + size_t eprefix_len = 0;
439 + char buf[1024];
440 + char *p;
441 + char *D;
442 + char *T;
443 + int i;
444 + char **ARGV;
445 + int ARGC;
446 + struct stat st;
447 + char **iargv;
448 + int iargc;
449 + const char *compr;
450 + int cp_argc;
451 + int cpm_argc;
452 + char **cp_argv;
453 + char **cpm_argv;
454 + int tbz2size;
455 + int replacing = 0;
456 +
457 + if (!install || !mpkg || !qatom)
458 return;
459
460 - if (!pkg->PF[0] || !pkg->CATEGORY[0]) {
461 - if (verbose) warn("CPF is really NULL at level %d", level);
462 - return;
463 - }
464 + /* create atom of the installed mpkg without version, with this
465 + * SLOT (without SUBSLOT) */
466 + snprintf(buf, sizeof(buf), "%s/%s:%s",
467 + mpkg->atom->CATEGORY,
468 + mpkg->atom->PN,
469 + mpkg->atom->SLOT != NULL ? "0" : mpkg->atom->SLOT);
470 + slotatom = atom_explode(buf);
471
472 - c = qprint_tree_node(level, atom, pkg);
473 + previnst = best_version(slotatom, BV_INSTALLED);
474 + if (previnst != NULL)
475 + replacing = atom_compare(mpkg->atom, slotatom);
476
477 - if (0)
478 - if (((c == 'R') || (c == 'D')) && update_only)
479 - return;
480 + (void)qprint_tree_node(level, mpkg, previnst, replacing);
481
482 - if (pkg->RDEPEND[0] != '\0' && follow_rdepends) {
483 - const char *rdepend;
484 + if (mpkg->meta->Q_RDEPEND != NULL &&
485 + mpkg->meta->Q_RDEPEND[0] != '\0' &&
486 + follow_rdepends)
487 + {
488 + const char *rdepend = mpkg->meta->Q_RDEPEND;
489
490 - IF_DEBUG(fprintf(stderr, "\n+Parent: %s/%s\n", pkg->CATEGORY, pkg->PF));
491 - IF_DEBUG(fprintf(stderr, "+Depstring: %s\n", pkg->RDEPEND));
492 + IF_DEBUG(fprintf(stderr, "\n+Parent: %s\n+Depstring: %s\n",
493 + atom_to_string(mpkg->atom), rdepend));
494
495 /* <hack> */
496 - if (strncmp(pkg->RDEPEND, "|| ", 3) == 0) {
497 + if (strncmp(rdepend, "|| ", 3) == 0) {
498 if (verbose)
499 - qfprintf(stderr, "fix this rdepend hack %s\n", pkg->RDEPEND);
500 + qfprintf(stderr, "fix this rdepend hack %s\n", rdepend);
501 rdepend = "";
502 - } else
503 - rdepend = pkg->RDEPEND;
504 + }
505 /* </hack> */
506
507 makeargv(rdepend, &ARGC, &ARGV);
508 /* Walk the rdepends here. Merging what need be. */
509 for (i = 1; i < ARGC; i++) {
510 - depend_atom *subatom, *ratom;
511 - char *name = ARGV[i];
512 + depend_atom *subatom;
513 + char *name = ARGV[i];
514 switch (*name) {
515 case '|':
516 case '!':
517 @@ -1046,41 +1058,19 @@ pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg)
518 break;
519 default:
520 if ((subatom = atom_explode(name)) != NULL) {
521 - struct pkg_t *subpkg;
522 -
523 - subpkg = grab_binpkg_info(subatom); /* free me later */
524 - if (subpkg == NULL) {
525 - warn("Cannot find a binpkg for %s from rdepend(%s)",
526 - name, pkg->RDEPEND);
527 + bpkg = best_version(subatom, BV_INSTALLED | BV_BINPKG);
528 + if (bpkg == NULL) {
529 + warn("cannot resolve %s from rdepend(%s)",
530 + name, rdepend);
531 atom_implode(subatom);
532 continue;
533 }
534
535 - assert(subpkg != NULL);
536 - IF_DEBUG(fprintf(stderr, "+Subpkg: %s/%s\n",
537 - subpkg->CATEGORY, subpkg->PF));
538 -
539 - /* look at installed versions now.
540 - * If NULL or < merge this pkg */
541 - snprintf(buf, sizeof(buf), "%s/%s",
542 - subpkg->CATEGORY, subpkg->PF);
543 -
544 - ratom = atom_explode(buf);
545 -
546 - p = best_version(subpkg->CATEGORY,
547 - subpkg->PF, subpkg->SLOT);
548 -
549 - /* we dont want to remerge equal versions here */
550 - IF_DEBUG(fprintf(stderr, "+Installed: %s\n", p));
551 - if (strlen(p) < 1)
552 - if (!((strcmp(pkg->PF, subpkg->PF) == 0) &&
553 - (strcmp(pkg->CATEGORY,
554 - subpkg->CATEGORY) == 0)))
555 - pkg_fetch(level+1, ratom, subpkg);
556 + if (bpkg->pkg->cat_ctx->ctx->cachetype != CACHE_VDB)
557 + pkg_fetch(level + 1, subatom, bpkg);
558
559 + tree_match_close(bpkg);
560 atom_implode(subatom);
561 - atom_implode(ratom);
562 - free(subpkg);
563 } else {
564 qfprintf(stderr, "Cant explode atom %s\n", name);
565 }
566 @@ -1103,22 +1093,22 @@ pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg)
567 }
568 if (vdb == NULL)
569 errf("need access to root, check permissions to access %s", portroot);
570 - cat_ctx = tree_open_cat(vdb, pkg->CATEGORY);
571 + cat_ctx = tree_open_cat(vdb, mpkg->atom->CATEGORY);
572 if (!cat_ctx) {
573 if (errno != ENOENT) {
574 tree_close(vdb);
575 return;
576 }
577 - mkdirat(vdb->tree_fd, pkg->CATEGORY, 0755);
578 - cat_ctx = tree_open_cat(vdb, pkg->CATEGORY);
579 + mkdirat(vdb->tree_fd, mpkg->atom->CATEGORY, 0755);
580 + cat_ctx = tree_open_cat(vdb, mpkg->atom->CATEGORY);
581 if (!cat_ctx) {
582 tree_close(vdb);
583 return;
584 }
585 }
586
587 - /* Set up our temp dir to unpack this stuff */
588 - xasprintf(&p, "%s/qmerge/%s/%s", port_tmpdir, pkg->CATEGORY, pkg->PF);
589 + /* Set up our temp dir to unpack this stuff FIXME p -> builddir */
590 + xasprintf(&p, "%s/qmerge/%s", port_tmpdir, atom_to_string(mpkg->atom));
591 mkdir_p(p, 0755);
592 xchdir(p);
593 xasprintf(&D, "%s/image", p);
594 @@ -1131,7 +1121,6 @@ pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg)
595 mkdir("temp", 0755);
596 mkdir_p(portroot, 0755);
597
598 - xasprintf(&tbz2, "%s/%s/%s.tbz2", pkgdir, pkg->CATEGORY, pkg->PF);
599 tbz2size = 0;
600
601 mkdir("vdb", 0755);
602 @@ -1139,10 +1128,10 @@ pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg)
603 int vdbfd = open("vdb", O_RDONLY);
604 if (vdbfd == -1)
605 err("failed to open vdb extraction directory");
606 - tbz2size = xpak_extract(tbz2, &vdbfd, pkg_extract_xpak_cb);
607 + tbz2size = xpak_extract(mpkg->path, &vdbfd, pkg_extract_xpak_cb);
608 }
609 if (tbz2size <= 0)
610 - err("%s appears not to be a valid tbz2 file", tbz2);
611 + err("%s appears not to be a valid tbz2 file", mpkg->path);
612
613 /* figure out if the data is compressed differently from what the
614 * name suggests, bug #660508, usage of BINPKG_COMPRESS,
615 @@ -1162,7 +1151,7 @@ pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg)
616 FILE *mfd;
617
618 compr = "brotli -dc"; /* default: brotli; has no magic header */
619 - mfd = fopen(tbz2, "r");
620 + mfd = fopen(mpkg->path, "r");
621 if (mfd != NULL) {
622 size_t mlen = fread(magic, 1, sizeof(magic), mfd);
623 fclose(mfd);
624 @@ -1261,18 +1250,18 @@ pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg)
625 if ((tarpipe = popen(buf, "w")) == NULL)
626 errp("failed to start %s", buf);
627
628 - if ((tbz2f = fopen(tbz2, "r")) == NULL)
629 - errp("failed to open %s for reading", tbz2);
630 + if ((tbz2f = fopen(mpkg->path, "r")) == NULL)
631 + errp("failed to open %s for reading", mpkg->path);
632
633 for (piped = wr = 0; piped < tbz2size; piped += wr) {
634 n = MIN(tbz2size - piped, (ssize_t)sizeof iobuf);
635 rd = fread(iobuf, 1, n, tbz2f);
636 if (0 == rd) {
637 if ((err = ferror(tbz2f)) != 0)
638 - err("reading %s failed: %s", tbz2, strerror(err));
639 + err("reading %s failed: %s", mpkg->path, strerror(err));
640
641 if (feof(tbz2f))
642 - err("unexpected EOF in %s: corrupted binpkg", tbz2);
643 + err("unexpected EOF in %s: corrupted binpkg", mpkg->path);
644 }
645
646 for (wr = n = 0; wr < rd; wr += n) {
647 @@ -1296,13 +1285,12 @@ pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg)
648 errp("finishing unpack binpkg unsuccessful");
649 }
650
651 - free(tbz2);
652 fflush(stdout);
653
654 - eat_file("vdb/DEFINED_PHASES", &phases, &phases_len);
655 - pkg_run_func("vdb", phases, "pkg_pretend", D, T);
656 - pkg_run_func("vdb", phases, "pkg_setup", D, T);
657 - pkg_run_func("vdb", phases, "pkg_preinst", D, T);
658 + eat_file("vdb/DEFINED_PHASES", &pm_phases, &pm_phases_len);
659 + pkg_run_func("vdb", pm_phases, "pkg_pretend", D, T);
660 + pkg_run_func("vdb", pm_phases, "pkg_setup", D, T);
661 + pkg_run_func("vdb", pm_phases, "pkg_preinst", D, T);
662
663 if (!eat_file("vdb/EPREFIX", &eprefix, &eprefix_len))
664 eprefix_len = 0;
665 @@ -1379,7 +1367,7 @@ pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg)
666
667 /* run postinst */
668 if (!pretend)
669 - pkg_run_func("vdb", phases, "pkg_postinst", D, T);
670 + pkg_run_func("vdb", pm_phases, "pkg_postinst", D, T);
671
672 /* XXX: hmm, maybe we'll want to strip more ? */
673 unlink("vdb/environment");
674 @@ -1387,43 +1375,24 @@ pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg)
675 /* Unmerge any stray pieces from the older version which we didn't
676 * replace */
677 /* TODO: Should see about merging with unmerge_packages() */
678 - while (1) {
679 - int ret;
680 - tree_pkg_ctx *pkg_ctx;
681 - depend_atom *old_atom;
682 -
683 - pkg_ctx = tree_next_pkg(cat_ctx);
684 - if (!pkg_ctx)
685 + switch (replacing) {
686 + case NEWER:
687 + case OLDER:
688 + case EQUAL:
689 + /* We need to really set this unmerge pending after we
690 + * look at contents of the new pkg */
691 + pkg_unmerge(previnst->pkg, objs,
692 + cp_argc, cp_argv, cpm_argc, cpm_argv);
693 + break;
694 + default:
695 + warn("no idea how we reached here.");
696 + case ERROR:
697 + case NOT_EQUAL:
698 break;
699 - old_atom = tree_get_atom(pkg_ctx, 1); /* retrieve SLOT */
700 - if (!old_atom)
701 - goto next_pkg;
702 - old_atom->SUBSLOT = NULL; /* just match SLOT */
703 - old_atom->REPO = NULL; /* REPO never matters, TODO atom_compare */
704 - ret = atom_compare(atom, old_atom);
705 - switch (ret) {
706 - case NEWER:
707 - case OLDER:
708 - case EQUAL:
709 - /* We need to really set this unmerge pending after we
710 - * look at contents of the new pkg */
711 - break;
712 - default:
713 - warn("no idea how we reached here.");
714 - case ERROR:
715 - case NOT_EQUAL:
716 - goto next_pkg;
717 - }
718 -
719 - printf("%s+++%s %s/%s %s %s/%s\n",
720 - GREEN, NORM, atom->CATEGORY, pkg->PF,
721 - booga[ret], cat_ctx->name, pkg_ctx->name);
722 -
723 - pkg_unmerge(pkg_ctx, objs, cp_argc, cp_argv, cpm_argc, cpm_argv);
724 - next_pkg:
725 - tree_close_pkg(pkg_ctx);
726 }
727
728 + tree_match_close(previnst);
729 +
730 freeargv(cp_argc, cp_argv);
731 freeargv(cpm_argc, cpm_argv);
732
733 @@ -1442,9 +1411,9 @@ pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg)
734 if (!pretend) {
735 /* move the local vdb copy to the final place */
736 snprintf(buf, sizeof(buf), "%s%s/%s/",
737 - portroot, portvdb, pkg->CATEGORY);
738 + portroot, portvdb, mpkg->atom->CATEGORY);
739 mkdir_p(buf, 0755);
740 - strcat(buf, pkg->PF);
741 + strcat(buf, mpkg->atom->PF);
742 rm_rf(buf); /* get rid of existing dir, empty dir is fine */
743 if (rename("vdb", buf) != 0)
744 warn("failed to move 'vdb' to '%s': %s", buf, strerror(errno));
745 @@ -1452,12 +1421,12 @@ pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg)
746
747 /* clean up our local temp dir */
748 xchdir("..");
749 - rm_rf(pkg->PF);
750 + rm_rf(mpkg->atom->PF);
751 /* don't care about return */
752 rmdir("../qmerge");
753
754 - printf("%s>>>%s %s%s%s/%s%s%s\n",
755 - YELLOW, NORM, WHITE, pkg->CATEGORY, NORM, CYAN, pkg->PF, NORM);
756 + printf("%s>>>%s %s\n",
757 + YELLOW, NORM, atom_format("%[CAT]%[PF]", mpkg->atom));
758
759 tree_close_cat(cat_ctx);
760 tree_close(vdb);
761 @@ -1481,7 +1450,7 @@ pkg_unmerge(tree_pkg_ctx *pkg_ctx, set *keep,
762 buf = phases = NULL;
763 T = "${PWD}/temp";
764
765 - printf("%s<<<%s %s\n", YELLOW, NORM,
766 + printf("%s***%s unmerging %s\n", YELLOW, NORM,
767 atom_format("%[CATEGORY]%[PF]", tree_get_atom(pkg_ctx, false)));
768
769 if (pretend == 100)
770 @@ -1513,11 +1482,11 @@ pkg_unmerge(tree_pkg_ctx *pkg_ctx, set *keep,
771 strstr(features, "config-protect-if-modified") != NULL;
772
773 for (; (buf = strtok_r(buf, "\n", &savep)) != NULL; buf = NULL) {
774 - bool del;
775 + bool del;
776 contents_entry *e;
777 - char zing[20];
778 - int protected = 0;
779 - struct stat st;
780 + char zing[20];
781 + int protected = 0;
782 + struct stat st;
783
784 e = contents_parse_line(buf);
785 if (!e)
786 @@ -1657,55 +1626,58 @@ unlink_empty(const char *buf)
787
788 static int
789 pkg_verify_checksums(
790 - char *fname,
791 - const struct pkg_t *pkg,
792 - int strict,
793 - int display)
794 + const tree_match_ctx *pkg,
795 + int strict,
796 + int display)
797 {
798 - int ret = 0;
799 - char md5[32+1];
800 - char sha1[40+1];
801 + int ret = 0;
802 + char md5[32+1];
803 + char sha1[40+1];
804 size_t flen;
805 + int mlen;
806
807 - if (hash_multiple_file(fname, md5, sha1, NULL, NULL, NULL, NULL,
808 + if (hash_multiple_file(pkg->path, md5, sha1, NULL, NULL, NULL, NULL,
809 &flen, HASH_MD5 | HASH_SHA1) == -1)
810 - errf("failed to compute hashes for %s/%s: %s\n",
811 - pkg->CATEGORY, pkg->PF, strerror(errno));
812 + errf("failed to compute hashes for %s: %s\n",
813 + atom_to_string(pkg->atom), strerror(errno));
814
815 - if (flen != pkg->SIZE) {
816 - warn("filesize %zu doesn't match requested size %zu for %s/%s\n",
817 - flen, pkg->SIZE, pkg->CATEGORY, pkg->PF);
818 + mlen = atoi(pkg->meta->Q_SIZE);
819 + if (flen != (size_t)mlen) {
820 + warn("filesize %zu doesn't match requested size %d for %s\n",
821 + flen, mlen, atom_to_string(pkg->atom));
822 ret++;
823 }
824
825 - if (pkg->MD5[0]) {
826 - if (strcmp(md5, pkg->MD5) == 0) {
827 + if (pkg->meta->Q_MD5 != NULL) {
828 + if (strcmp(md5, pkg->meta->Q_MD5) == 0) {
829 if (display)
830 - printf("MD5: [%sOK%s] %s %s/%s\n",
831 - GREEN, NORM, md5, pkg->CATEGORY, pkg->PF);
832 + printf("MD5: [%sOK%s] %s %s\n",
833 + GREEN, NORM, md5, atom_to_string(pkg->atom));
834 } else {
835 if (display)
836 - warn("MD5: [%sER%s] (%s) != (%s) %s/%s",
837 - RED, NORM, md5, pkg->MD5, pkg->CATEGORY, pkg->PF);
838 + warn("MD5: [%sER%s] (%s) != (%s) %s",
839 + RED, NORM, md5, pkg->meta->Q_MD5,
840 + atom_to_string(pkg->atom));
841 ret++;
842 }
843 }
844
845 - if (pkg->SHA1[0]) {
846 - if (strcmp(sha1, pkg->SHA1) == 0) {
847 + if (pkg->meta->Q_SHA1 != NULL) {
848 + if (strcmp(sha1, pkg->meta->Q_SHA1) == 0) {
849 if (display)
850 - qprintf("SHA1: [%sOK%s] %s %s/%s\n",
851 - GREEN, NORM, sha1, pkg->CATEGORY, pkg->PF);
852 + qprintf("SHA1: [%sOK%s] %s %s\n",
853 + GREEN, NORM, sha1, atom_to_string(pkg->atom));
854 } else {
855 if (display)
856 - warn("SHA1: [%sER%s] (%s) != (%s) %s/%s",
857 - RED, NORM, sha1, pkg->SHA1, pkg->CATEGORY, pkg->PF);
858 + warn("SHA1: [%sER%s] (%s) != (%s) %s",
859 + RED, NORM, sha1, pkg->meta->Q_SHA1,
860 + atom_to_string(pkg->atom));
861 ret++;
862 }
863 }
864
865 - if (!pkg->SHA1[0] && !pkg->MD5[0])
866 - return 1;
867 + if (pkg->meta->Q_MD5 == NULL && pkg->meta->Q_SHA1 == NULL)
868 + return -1;
869
870 if (strict && ret)
871 errf("strict is set in features");
872 @@ -1714,140 +1686,69 @@ pkg_verify_checksums(
873 }
874
875 static void
876 -pkg_fetch(int level, const depend_atom *atom, const struct pkg_t *pkg)
877 +pkg_fetch(int level, const depend_atom *qatom, const tree_match_ctx *mpkg)
878 {
879 - char buf[_Q_PATH_MAX], str[_Q_PATH_MAX];
880 + int verifyret;
881 + char buf[_Q_PATH_MAX];
882
883 /* qmerge -pv patch */
884 if (pretend) {
885 if (!install)
886 install++;
887 - /* qprint_tree_node(level, atom, pkg); */
888 - pkg_merge(level, atom, pkg);
889 + /* qprint_tree_node(level, qatom, mpkg); */
890 + pkg_merge(level, qatom, mpkg);
891 return;
892 }
893
894 - /* check to see if file exists and it's checksum matches */
895 - snprintf(buf, sizeof(buf), "%s/%s/%s.tbz2", pkgdir, pkg->CATEGORY, pkg->PF);
896 - unlink_empty(buf);
897 + unlink_empty(mpkg->path);
898
899 - snprintf(str, sizeof(str), "%s/%s", pkgdir, pkg->CATEGORY);
900 - if (mkdir(str, 0755) == -1 && errno != EEXIST) {
901 - warn("Failed to create %s", str);
902 + if (mkdir(mpkg->pkg->cat_ctx->ctx->path, 0755) == -1 && errno != EEXIST) {
903 + warn("Failed to create %s", mpkg->pkg->cat_ctx->ctx->path);
904 return;
905 }
906
907 - if (force_download && (access(buf, R_OK) == 0) &&
908 - (pkg->SHA1[0] || pkg->MD5[0]))
909 + if (force_download && (access(mpkg->path, R_OK) == 0) &&
910 + (mpkg->meta->Q_SHA1 != NULL || mpkg->meta->Q_MD5 != NULL))
911 {
912 - if (pkg_verify_checksums(buf, pkg, 0, 0) != 0)
913 + if (pkg_verify_checksums(mpkg, 0, 0) != 0)
914 if (getenv("QMERGE") == NULL)
915 - unlink(buf);
916 - }
917 - if (access(buf, R_OK) == 0) {
918 - if (!pkg->SHA1[0] && !pkg->MD5[0]) {
919 - warn("No checksum data for %s (try `emaint binhost --fix`)", buf);
920 - return;
921 - } else {
922 - if (pkg_verify_checksums(buf, pkg, qmerge_strict, !quiet)
923 - == 0)
924 - {
925 - pkg_merge(0, atom, pkg);
926 - return;
927 - }
928 - }
929 - }
930 - if (verbose)
931 - printf("Fetching %s/%s.tbz2\n", atom->CATEGORY, pkg->PF);
932 -
933 - /* fetch the package */
934 - /* Check CATEGORY first */
935 - if (!old_repo) {
936 - snprintf(buf, sizeof(buf), "%s/%s.tbz2", atom->CATEGORY, pkg->PF);
937 - fetch(str, buf);
938 - }
939 - snprintf(buf, sizeof(buf), "%s/%s/%s.tbz2",
940 - pkgdir, atom->CATEGORY, pkg->PF);
941 - if (access(buf, R_OK) != 0) {
942 - snprintf(buf, sizeof(buf), "%s.tbz2", pkg->PF);
943 - fetch(str, buf);
944 - old_repo = 1;
945 + unlink(mpkg->path);
946 }
947
948 - /* verify the pkg exists now. unlink if zero bytes */
949 - snprintf(buf, sizeof(buf), "%s/%s/%s.tbz2",
950 - pkgdir, atom->CATEGORY, pkg->PF);
951 - unlink_empty(buf);
952 + if (access(mpkg->path, R_OK) != 0) {
953 + if (verbose)
954 + printf("Fetching %s\n", atom_to_string(mpkg->atom));
955
956 - if (access(buf, R_OK) != 0) {
957 - warn("Failed to fetch %s.tbz2 from %s", pkg->PF, binhost);
958 - fflush(stderr);
959 - return;
960 + /* fetch the package */
961 + snprintf(buf, sizeof(buf), "%s/%s.tbz2",
962 + mpkg->atom->CATEGORY, mpkg->atom->PF);
963 + fetch(mpkg->pkg->cat_ctx->ctx->path, buf);
964 +
965 + /* verify the pkg exists now. unlink if zero bytes */
966 + unlink_empty(mpkg->path);
967 }
968
969 - snprintf(buf, sizeof(buf), "%s/%s/%s.tbz2",
970 - pkgdir, atom->CATEGORY, pkg->PF);
971 - if (pkg_verify_checksums(buf, pkg, qmerge_strict, !quiet) == 0) {
972 - pkg_merge(0, atom, pkg);
973 + if (access(mpkg->path, R_OK) != 0) {
974 + warn("Failed to fetch %s.tbz2 from %s", mpkg->atom->PF, binhost);
975 + fflush(stderr);
976 return;
977 }
978 -}
979 -
980 -static void
981 -print_Pkg(int full, const depend_atom *atom, const struct pkg_t *pkg)
982 -{
983 - char *p = NULL;
984 - char buf[512];
985 -
986 - printf("%s%s%s%s\n", atom_format("%[CAT]%[PF]%[SLOT]", atom),
987 - !quiet ? " [" : "",
988 - !quiet ? make_human_readable_str(pkg->SIZE, 1, KILOBYTE) : "",
989 - !quiet ? " KiB]" : "");
990
991 - if (full == 0)
992 + /* check to see if checksum matches */
993 + verifyret = pkg_verify_checksums(mpkg, qmerge_strict, !quiet);
994 + if (verifyret == -1) {
995 + warn("No checksum data for %s (try `emaint binhost --fix`)",
996 + mpkg->path);
997 + return;
998 + } else if (verifyret == 0) {
999 + pkg_merge(0, qatom, mpkg);
1000 return;
1001 -
1002 - if (pkg->DESC[0])
1003 - printf(" %sDesc%s:%s %s\n", DKGREEN, YELLOW, NORM, pkg->DESC);
1004 - if (pkg->SHA1[0])
1005 - printf(" %sSha1%s:%s %s\n", DKGREEN, YELLOW, NORM, pkg->SHA1);
1006 - if (pkg->MD5[0])
1007 - printf(" %sMd5%s:%s %s\n", DKGREEN, YELLOW, NORM, pkg->MD5);
1008 - if (!pkg->MD5[0] && !pkg->SHA1[0])
1009 - printf(" %sSums%s:%s %s(MISSING!)%s\n",
1010 - DKGREEN, YELLOW, NORM, RED, NORM);
1011 - if (pkg->SLOT[0])
1012 - printf(" %sSlot%s:%s %s\n", DKGREEN, YELLOW, NORM, pkg->SLOT);
1013 - if (pkg->LICENSE[0])
1014 - printf(" %sLicense%s:%s %s\n", DKGREEN, YELLOW, NORM, pkg->LICENSE);
1015 - if (pkg->RDEPEND[0])
1016 - printf(" %sRdepend%s:%s %s\n", DKGREEN, YELLOW, NORM, pkg->RDEPEND);
1017 - if (pkg->USE[0])
1018 - printf(" %sUse%s:%s %s\n", DKGREEN, YELLOW, NORM, pkg->USE);
1019 - if (pkg->REPO[0])
1020 - if (strcmp(pkg->REPO, "gentoo") != 0)
1021 - printf(" %sRepo%s:%s %s\n", DKGREEN, YELLOW, NORM, pkg->REPO);
1022 -
1023 - if ((p = best_version(pkg->CATEGORY, atom->PN, pkg->SLOT)) != NULL) {
1024 - if (*p) {
1025 - int ret;
1026 - const char *icolor = RED;
1027 - ret = atom_compare_str(buf, p);
1028 - switch (ret) {
1029 - case EQUAL: icolor = RED; break;
1030 - case NEWER: icolor = YELLOW; break;
1031 - case OLDER: icolor = BLUE; break;
1032 - default: icolor = NORM; break;
1033 - }
1034 - printf(" %sInstalled%s:%s %s%s%s\n",
1035 - DKGREEN, YELLOW, NORM, icolor, p, NORM);
1036 - }
1037 }
1038 }
1039
1040 /* HACK: pull this in, knowing that qlist will be in the final link, we
1041 * should however figure out how to do what match does here from e.g.
1042 - * atom */
1043 + * atom FIXME use tree_match_atom instead */
1044 extern bool qlist_match(
1045 tree_pkg_ctx *pkg_ctx,
1046 const char *name,
1047 @@ -1893,71 +1794,6 @@ unmerge_packages(set *todo)
1048 return ret;
1049 }
1050
1051 -static tree_ctx *_grab_binpkg_info_tree = NULL;
1052 -static struct pkg_t *
1053 -grab_binpkg_info(depend_atom *atom)
1054 -{
1055 - tree_ctx *tree = _grab_binpkg_info_tree;
1056 - tree_match_ctx *tpkg;
1057 - struct pkg_t *pkg = NULL;
1058 - char path[BUFSIZ];
1059 - FILE *d;
1060 -
1061 - /* reuse previously opened tree, so we really employ the cache
1062 - * from libq/tree */
1063 - if (tree == NULL) {
1064 - snprintf(path, sizeof(path), "%s/portage/%s", port_tmpdir, Packages);
1065 - /* we don't use ROOT on package tree here, operating on ROOT
1066 - * should be for package merges/unmerges, but be able to pull
1067 - * binpkgs from current system */
1068 - if ((d = fopen(path, "r")) != NULL) {
1069 - fclose(d);
1070 - snprintf(path, sizeof(path), "%s/portage", port_tmpdir);
1071 - tree = tree_open_binpkg("/", path);
1072 - } else {
1073 - tree = tree_open_binpkg("/", pkgdir);
1074 - }
1075 - _grab_binpkg_info_tree = tree;
1076 -
1077 - /* if opening the tree failed somehow, we can't return anything */
1078 - if (tree == NULL)
1079 - return NULL;
1080 - }
1081 -
1082 - tpkg = tree_match_atom(tree, atom,
1083 - TREE_MATCH_FIRST | TREE_MATCH_VIRTUAL | TREE_MATCH_METADATA);
1084 - if (tpkg != NULL) {
1085 - depend_atom *tatom = tpkg->atom;
1086 - tree_pkg_meta *meta = tpkg->meta;
1087 - pkg = xzalloc(sizeof(struct pkg_t));
1088 -
1089 - snprintf(pkg->PF, sizeof(pkg->PF), "%s", tatom->PF);
1090 - snprintf(pkg->CATEGORY, sizeof(pkg->CATEGORY), "%s", tatom->CATEGORY);
1091 - if (meta->Q_DESCRIPTION != NULL)
1092 - snprintf(pkg->DESC, sizeof(pkg->DESC), "%s", meta->Q_DESCRIPTION);
1093 - if (meta->Q_LICENSE != NULL)
1094 - snprintf(pkg->LICENSE, sizeof(pkg->LICENSE), "%s", meta->Q_LICENSE);
1095 - if (meta->Q_RDEPEND != NULL)
1096 - snprintf(pkg->RDEPEND, sizeof(pkg->RDEPEND), "%s", meta->Q_RDEPEND);
1097 - if (meta->Q_MD5 != NULL)
1098 - snprintf(pkg->MD5, sizeof(pkg->MD5), "%s", meta->Q_MD5);
1099 - if (meta->Q_SHA1 != NULL)
1100 - snprintf(pkg->SHA1, sizeof(pkg->SHA1), "%s", meta->Q_SHA1);
1101 - if (meta->Q_USE != NULL)
1102 - snprintf(pkg->USE, sizeof(pkg->USE), "%s", meta->Q_USE);
1103 - if (meta->Q_repository != NULL)
1104 - snprintf(pkg->REPO, sizeof(pkg->REPO), "%s", meta->Q_repository);
1105 - if (meta->Q_SLOT != NULL)
1106 - snprintf(pkg->REPO, sizeof(pkg->REPO), "%s", meta->Q_SLOT);
1107 - if (meta->Q_SIZE != NULL)
1108 - pkg->SIZE = atoi(meta->Q_SIZE);
1109 -
1110 - tree_match_close(tpkg);
1111 - }
1112 -
1113 - return pkg;
1114 -}
1115 -
1116 static set *
1117 qmerge_add_set_file(const char *pfx, const char *dir, const char *file, set *q)
1118 {
1119 @@ -2046,8 +1882,7 @@ qmerge_run(set *todo)
1120 return unmerge_packages(todo);
1121 } else {
1122 if (todo == NULL || search_pkgs) {
1123 - /* disputable, this should be qlist -kIv or something */
1124 - warn("please use qlist -kI");
1125 + warn("please use qlist -kIv");
1126
1127 return EXIT_SUCCESS;
1128 } else {
1129 @@ -2055,19 +1890,18 @@ qmerge_run(set *todo)
1130 size_t todo_cnt = list_set(todo, &todo_strs);
1131 size_t i;
1132 depend_atom *atom;
1133 - struct pkg_t *pkg;
1134 + tree_match_ctx *bpkg;
1135 int ret = EXIT_FAILURE;
1136
1137 for (i = 0; i < todo_cnt; i++) {
1138 atom = atom_explode(todo_strs[i]);
1139 - pkg = grab_binpkg_info(atom);
1140 - if (pkg != NULL) {
1141 - if (search_pkgs)
1142 - print_Pkg(verbose, atom, pkg);
1143 - else
1144 - pkg_fetch(0, atom, pkg);
1145 - free(pkg);
1146 + bpkg = best_version(atom, BV_BINPKG);
1147 + if (bpkg != NULL) {
1148 + pkg_fetch(0, atom, bpkg);
1149 + tree_match_close(bpkg);
1150 ret = EXIT_SUCCESS;
1151 + } else {
1152 + warn("nothing found for %s", atom_to_string(atom));
1153 }
1154 atom_implode(atom);
1155 }
1156 @@ -2088,23 +1922,27 @@ int qmerge_main(int argc, char **argv)
1157
1158 while ((i = GETOPT_LONG(QMERGE, qmerge, "")) != -1) {
1159 switch (i) {
1160 - case 'f': force_download = 1; break;
1161 - case 'F': force_download = 2; break;
1162 - case 's': search_pkgs = 1; interactive = 0; break;
1163 + case 'f': force_download = 1; break;
1164 + case 'F': force_download = 2; break;
1165 + case 's': search_pkgs = 1;
1166 + interactive = 0; break;
1167 /* case 'i': case 'g': */
1168 - case 'K': install = 1; break;
1169 - case 'U': uninstall = 1; break;
1170 - case 'p': pretend = 1; break;
1171 - case 'u':
1172 - update_only = 1;
1173 - /* fall through */
1174 - case 'y': interactive = 0; break;
1175 + case 'K': install = 1; break;
1176 + case 'U': uninstall = 1; break;
1177 + case 'p': pretend = 1; break;
1178 + case 'u': update_only = 1;
1179 + install = 1; break;
1180 + case 'y': interactive = 0; break;
1181 case 'O': follow_rdepends = 0; break;
1182 - case 128: debug = true; break;
1183 + case 128: debug = true; break;
1184 COMMON_GETOPTS_CASES(qmerge)
1185 }
1186 }
1187
1188 + /* default to install if no action given */
1189 + if (!install && !uninstall)
1190 + install = 1;
1191 +
1192 qmerge_strict = (strstr("strict", features) == 0) ? 1 : 0;
1193
1194 /* Short circut this. */
1195 @@ -2140,14 +1978,14 @@ int qmerge_main(int argc, char **argv)
1196 verbose = 0;
1197 quiet = 1;
1198 ret = qmerge_run(todo);
1199 - if (ret || save_pretend)
1200 + if (ret != EXIT_SUCCESS || save_pretend)
1201 return ret;
1202
1203 if (uninstall) {
1204 - if (!prompt("OK to unmerge these packages"))
1205 + if (!qmerge_prompt("OK to unmerge these packages"))
1206 return EXIT_FAILURE;
1207 } else {
1208 - if (!prompt("OK to merge these packages"))
1209 + if (!qmerge_prompt("OK to merge these packages"))
1210 return EXIT_FAILURE;
1211 }
1212
1213
1214 diff --git a/tests/qmerge/dotest b/tests/qmerge/dotest
1215 index 59f249d..0f870ef 100755
1216 --- a/tests/qmerge/dotest
1217 +++ b/tests/qmerge/dotest
1218 @@ -22,16 +22,17 @@ set +e
1219
1220 # sanity check on environment
1221 q -Cev
1222 +qlist -kIv
1223
1224 # Do a merge into an empty tree.
1225
1226 -out=$(yes | qmerge -F qmerge-test)
1227 +out=$(yes | qmerge -F qmerge-test-1.3)
1228 tend $? "qmerge-test: [N] basic merge" || die "${out}"
1229
1230 [[ ${out} != *"FAIL"* ]]
1231 tend $? "qmerge-test: [N] no FAIL messages" || die "${out}"
1232
1233 -order=$(echo "${out}" | awk '$1 == ">>>" && $2 ~ /^pkg_/ { printf "%s ", $NF }')
1234 +order=$(echo "${out}" | awk '$1 == "@@@" && $2 ~ /^pkg_/ { printf "%s ", $NF }')
1235 [[ ${order} == "pkg_pretend pkg_setup pkg_preinst pkg_postinst " ]]
1236 tend $? "qmerge-test: [N] pkg_* order of execution" || die "$(printf '%s\n' "${order}" "${out}")"
1237
1238 @@ -45,14 +46,14 @@ tend $? "qmerge-test: [N] installed expected files" || die "$(treedir "${ROOT}")
1239
1240 # Now do a re-emerge.
1241
1242 -out=$(yes | qmerge -F qmerge-test)
1243 +out=$(yes | qmerge -F "<qmerge-test-2")
1244 tend $? "qmerge-test: [R] re-emerge" || die "${out}"
1245
1246 [[ -x ${ROOT}/usr/bin/qmerge-test ]]
1247 tend $? "qmerge-test: [R] installed expected files" || die "$(treedir "${ROOT}")"
1248
1249 -order=$(echo "${out}" | awk '$1 == ">>>" && $2 ~ /^pkg_/ { printf "%s ", $NF }')
1250 -[[ ${order} == "pkg_pretend pkg_setup pkg_preinst pkg_postinst " ]]
1251 +order=$(echo "${out}" | awk '$1 == "@@@" && $2 ~ /^pkg_/ { printf "%s ", $NF }')
1252 +[[ ${order} == "pkg_pretend pkg_setup pkg_preinst pkg_postinst pkg_prerm pkg_postrm " ]]
1253 tend $? "qmerge-test: [R] pkg_* order of execution" || die "$(printf '%s\n' "${order}" "${out}")"
1254
1255 [[ -x ${ROOT}/usr/bin/qmerge-test && \
1256 @@ -61,6 +62,19 @@ tend $? "qmerge-test: [R] pkg_* order of execution" || die "$(printf '%s\n' "${o
1257 -f ${ROOT}/etc/._cfg0000_some.conf ]]
1258 tend $? "qmerge-test: [R] re-installed expected files" || die "$(treedir "${ROOT}")"
1259
1260 +# upgrade to latest version
1261 +
1262 +out=$(yes | qmerge -F qmerge-test)
1263 +tend $? "qmerge-test: [U] update" || die "${out}"
1264 +
1265 +[[ $(qlist -Iv qmerge-test) == "sys-devel/qmerge-test-2.0" ]]
1266 +tend $? "qmerge-test: qlist does not report version 2.0 installed" || die "$(qlist -Iv qmerge-test;qlist -kIv) ${out}"
1267 +
1268 +[[ ! -x ${ROOT}/usr/bin/qmerge-test ]]
1269 +tend $? "qmerge-test: binary from version 1 does not exist" || die "$(treedir "${ROOT}")"
1270 +[[ -x ${ROOT}/usr/bin/qmerge-test2 ]]
1271 +tend $? "qmerge-test: binary from version 2 exists" || die "$(treedir "${ROOT}")"
1272 +
1273 # Finally do an unmerge.
1274
1275 echo alkdsjfalksdf > "${ROOT}/etc/some.conf"
1276 @@ -69,7 +83,7 @@ rm -f "${ROOT}/etc/._cfg0000_some.conf"
1277 out=$(yes | qmerge -FU qmerge-test)
1278 tend $? "qmerge-test: [C] uninstall" || die "${out}"
1279
1280 -order=$(echo "${out}" | awk '$1 == ">>>" { printf "%s ", $NF }')
1281 +order=$(echo "${out}" | awk '$1 == "@@@" { printf "%s ", $NF }')
1282 [[ ${order} == "pkg_prerm pkg_postrm " ]]
1283 tend $? "qmerge-test: [C] pkg_* order of execution" || die "$(printf '%s\n' "${order}" "${out}")"
1284
1285 @@ -90,9 +104,9 @@ tend $? "qmerge-test: [M] install no /etc" || die "${out}"
1286 tend $? "qmerge-test: [M] found no /etc" || die "$(treedir "${ROOT}")"
1287
1288 out=$(yes | qmerge -FU qmerge-test)
1289 -tend $? "qmerge-test: [M] uninstall" || die "${out}"
1290 +tend $? "qmerge-test: [U] uninstall" || die "${out}"
1291 [[ ! -e ${ROOT}/etc ]]
1292 -tend $? "qmerge-test: [M] /etc removed" || die "$(treedir "${ROOT}")"
1293 +tend $? "qmerge-test: [U] /etc removed" || die "$(treedir "${ROOT}")"
1294
1295 export INSTALL_MASK="/etc -/etc/some.conf"
1296 out=$(yes | qmerge -F qmerge-test)
1297 @@ -101,9 +115,9 @@ tend $? "qmerge-test: [M] install only /etc/some.conf" || die "${out}"
1298 tend $? "qmerge-test: [M] found /etc/another.conf" || die "$(treedir "${ROOT}")"
1299
1300 out=$(yes | qmerge -FU qmerge-test)
1301 -tend $? "qmerge-test: [M] uninstall" || die "${out}"
1302 +tend $? "qmerge-test: [U] uninstall" || die "${out}"
1303 [[ ! -e ${ROOT}/etc ]]
1304 -tend $? "qmerge-test: [M] /etc removed" || die "$(treedir "${ROOT}")"
1305 +tend $? "qmerge-test: [U] /etc removed" || die "$(treedir "${ROOT}")"
1306
1307 export INSTALL_MASK="/usr -/usr/bin/dummy"
1308 out=$(yes | qmerge -F qmerge-test)
1309 @@ -114,22 +128,22 @@ tend $? "qmerge-test: [M] found /usr/bin/dummy" || die "$(treedir "${ROOT}")"
1310 tend $? "qmerge-test: [M] /usr/bin/qmerge-test absent" || die "$(treedir "${ROOT}")"
1311
1312 out=$(yes | qmerge -FU qmerge-test)
1313 -tend $? "qmerge-test: [M] uninstall" || die "${out}"
1314 +tend $? "qmerge-test: [U] uninstall" || die "${out}"
1315 [[ ! -e ${ROOT}/usr/bin/dummy ]]
1316 -tend $? "qmerge-test: [M] /usr/bin/dummy removed" || die "$(treedir "${ROOT}")"
1317 +tend $? "qmerge-test: [U] /usr/bin/dummy removed" || die "$(treedir "${ROOT}")"
1318
1319 export INSTALL_MASK="/usr -/usr/bin /usr/bin/dummy"
1320 out=$(yes | qmerge -F qmerge-test)
1321 tend $? "qmerge-test: [M] install except /usr/bin/dummy" || die "${out}"
1322 [[ ! -e ${ROOT}/usr/bin/dummy ]]
1323 tend $? "qmerge-test: [M] found no /usr/bin/dummy" || die "$(treedir "${ROOT}")"
1324 -[[ -e ${ROOT}/usr/bin/qmerge-test ]]
1325 -tend $? "qmerge-test: [M] found /usr/bin/qmerge-test" || die "$(treedir "${ROOT}")"
1326 +[[ -e ${ROOT}/usr/bin/qmerge-test2 ]]
1327 +tend $? "qmerge-test: [M] found /usr/bin/qmerge-test2" || die "$(treedir "${ROOT}")"
1328
1329 out=$(yes | qmerge -FU qmerge-test)
1330 -tend $? "qmerge-test: [M] uninstall" || die "${out}"
1331 -[[ ! -e ${ROOT}/usr/bin/qmerge-test ]]
1332 -tend $? "qmerge-test: [M] /usr/bin/qmerge-test removed" || die "$(treedir "${ROOT}")"
1333 +tend $? "qmerge-test: [U] uninstall" || die "${out}"
1334 +[[ ! -e ${ROOT}/usr/bin/qmerge-test2 ]]
1335 +tend $? "qmerge-test: [U] /usr/bin/qmerge-test2 removed" || die "$(treedir "${ROOT}")"
1336
1337 # try all compressions we know to see if we handle them properly
1338 pkgver=qmerge-test-1.3
1339 @@ -152,10 +166,10 @@ for compr in "" brotli gzip bzip2 xz lz4 zstd lzip lzop ; do
1340 : $((rev++))
1341 qtbz2 -j ${f} ${pkgver}.xpak pkgs/sys-devel/${pkgver}-r${rev}.tbz2
1342 ls -l pkgs/sys-devel/${pkgver}-r${rev}.tbz2
1343 - ROOT=/ qlist -kIv | tee /dev/stderr | wc -l
1344 + qlist -kIv | tee /dev/stderr | wc -l
1345
1346 # see if we can install this package
1347 - out=$(yes | qmerge -Fv qmerge-test)
1348 + out=$(yes | qmerge -Fv =${pkgver}-r${rev})
1349 tend $? "qmerge-test: [X] install ${pkgver}-r${rev}" || die "${out}"
1350 qlist -Iv
1351 out=$(yes | qmerge -FU qmerge-test)
1352
1353 diff --git a/tests/qmerge/packages/Packages b/tests/qmerge/packages/Packages
1354 index e6fa3a2..cd34d8d 100644
1355 --- a/tests/qmerge/packages/Packages
1356 +++ b/tests/qmerge/packages/Packages
1357 @@ -28,3 +28,16 @@ SHA1: 47f731ce30149f5ab15f0c47dc19b46e4b189d60
1358 SIZE: 7289
1359 REPO: local
1360
1361 +BUILD_TIME: 1367285976
1362 +CPV: sys-devel/qmerge-test-2.0
1363 +DEFINED_PHASES: install postinst postrm preinst prerm pretend setup
1364 +DESC: my desc
1365 +EAPI: 6
1366 +KEYWORDS: ~amd64 ~x86
1367 +LICENSE: GPL-2
1368 +MD5: 100f6c414b1dc980fc73cf70178c2190
1369 +MTIME: 1367290147
1370 +SHA1: 5ba9c5db40a1b9be5e0e98b19b2cff5d2c197808
1371 +SIZE: 7334
1372 +REPO: local
1373 +
1374
1375 diff --git a/tests/qmerge/packages/sys-devel/qmerge-test-2.0.tbz2 b/tests/qmerge/packages/sys-devel/qmerge-test-2.0.tbz2
1376 new file mode 100644
1377 index 0000000..1fac801
1378 Binary files /dev/null and b/tests/qmerge/packages/sys-devel/qmerge-test-2.0.tbz2 differ