Gentoo Archives: gentoo-commits

From: "Mike Frysinger (vapier)" <vapier@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] gentoo-projects commit in portage-utils: .depend qmerge.c
Date: Wed, 02 Mar 2011 09:16:37
Message-Id: 20110302091622.D4F5120054@flycatcher.gentoo.org
1 vapier 11/03/02 09:16:22
2
3 Modified: .depend qmerge.c
4 Log:
5 rewrite merging logic so that we can upgrade in place without doing a full unmerge followed by a full merge
6
7 Revision Changes Path
8 1.42 portage-utils/.depend
9
10 file : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/.depend?rev=1.42&view=markup
11 plain: http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/.depend?rev=1.42&content-type=text/plain
12 diff : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/.depend?r1=1.41&r2=1.42
13
14 Index: .depend
15 ===================================================================
16 RCS file: /var/cvsroot/gentoo-projects/portage-utils/.depend,v
17 retrieving revision 1.41
18 retrieving revision 1.42
19 diff -u -r1.41 -r1.42
20 --- .depend 23 Feb 2011 22:58:51 -0000 1.41
21 +++ .depend 2 Mar 2011 09:16:22 -0000 1.42
22 @@ -3,7 +3,7 @@
23 libq/hash_fd.c libq/md5_sha1_sum.c libq/human_readable.c libq/rmspace.c \
24 libq/which.c libq/compat.c libq/copy_file.c libq/safe_io.c libq/xchdir.c \
25 libq/xgetcwd.c libq/xmkdir.c libq/xreadlink.c libq/xsystem.c \
26 - libq/atom_explode.c libq/atom_compare.c libq/basename.c \
27 + libq/atom_explode.c libq/atom_compare.c libq/basename.c libq/profile.c \
28 libq/vdb_get_next_dir.c libq/virtuals.c applets.h include_applets.h q.c \
29 qcheck.c qdepends.c qfile.c qlist.c qlop.c qsearch.c qsize.c qtbz2.c \
30 quse.c qxpak.c qpkg.c qgrep.c qatom.c qmerge.c qcache.c qglsa.c
31
32
33
34 1.106 portage-utils/qmerge.c
35
36 file : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qmerge.c?rev=1.106&view=markup
37 plain: http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qmerge.c?rev=1.106&content-type=text/plain
38 diff : http://sources.gentoo.org/viewvc.cgi/gentoo-projects/portage-utils/qmerge.c?r1=1.105&r2=1.106
39
40 Index: qmerge.c
41 ===================================================================
42 RCS file: /var/cvsroot/gentoo-projects/portage-utils/qmerge.c,v
43 retrieving revision 1.105
44 retrieving revision 1.106
45 diff -u -r1.105 -r1.106
46 --- qmerge.c 2 Mar 2011 03:51:01 -0000 1.105
47 +++ qmerge.c 2 Mar 2011 09:16:22 -0000 1.106
48 @@ -1,7 +1,7 @@
49 /*
50 * Copyright 2005-2010 Gentoo Foundation
51 * Distributed under the terms of the GNU General Public License v2
52 - * $Header: /var/cvsroot/gentoo-projects/portage-utils/qmerge.c,v 1.105 2011/03/02 03:51:01 solar Exp $
53 + * $Header: /var/cvsroot/gentoo-projects/portage-utils/qmerge.c,v 1.106 2011/03/02 09:16:22 vapier Exp $
54 *
55 * Copyright 2005-2010 Ned Ludd - <solar@g.o>
56 * Copyright 2005-2010 Mike Frysinger - <vapier@g.o>
57 @@ -55,7 +55,7 @@
58 COMMON_OPTS_HELP
59 };
60
61 -static const char qmerge_rcsid[] = "$Id: qmerge.c,v 1.105 2011/03/02 03:51:01 solar Exp $";
62 +static const char qmerge_rcsid[] = "$Id: qmerge.c,v 1.106 2011/03/02 09:16:22 vapier Exp $";
63 #define qmerge_usage(ret) usage(ret, QMERGE_FLAGS, qmerge_long_opts, qmerge_opts_help, lookup_applet_idx("qmerge"))
64
65 char search_pkgs = 0;
66 @@ -95,70 +95,36 @@
67
68 typedef struct llist_char_t llist_char;
69
70 -int interactive_rename(const char *, const char *, struct pkg_t *);
71 -void fetch(const char *, const char *);
72 -char *best_version(const char *, const char *);
73 -void pkg_fetch(int, depend_atom *, struct pkg_t *);
74 -void pkg_merge(int, depend_atom *, struct pkg_t *);
75 -int pkg_unmerge(const char *, const char *);
76 -int unlink_empty(char *);
77 -void print_Pkg(int, struct pkg_t *);
78 -int pkg_verify_checksums(char *, struct pkg_t *, depend_atom *, int strict, int display);
79 -char *find_binpkg(const char *);
80 +_q_static void pkg_fetch(int, const depend_atom *, const struct pkg_t *);
81 +_q_static void pkg_merge(int, const depend_atom *, const struct pkg_t *);
82 +_q_static int pkg_unmerge(const char *, const char *, queue *);
83 +_q_static struct pkg_t *grab_binpkg_info(const char *);
84 +_q_static char *find_binpkg(const char *);
85
86 -struct pkg_t *grab_binpkg_info(const char *);
87 -
88 -static int q_unlink_q(char *path, const char *func, int line)
89 +_q_static int q_unlink_q(const char *path, const char *func, int line)
90 {
91 - if ((strcmp(path, "/bin/sh") == 0) || (strcmp(path, BUSYBOX) == 0)) {
92 - warn("Oh hell no: unlink(%s) from %s line %d", path, func, line);
93 - return 1;
94 - }
95 + int ret;
96 + char *d;
97 +
98 if (pretend)
99 return 0;
100 - return unlink(path);
101 -}
102
103 -#define unlink_q(path) q_unlink_q(path, __FUNCTION__, __LINE__)
104 -
105 -/* rewrite using copyfile() utime() stat(), lstat(), read() and perms. */
106 -int interactive_rename(const char *src, const char *dst, struct pkg_t *pkg)
107 -{
108 - FILE *fp;
109 - char *p;
110 - int ret;
111 - char buf[1024];
112 - struct stat st;
113 - char check_interactive = interactive;
114 + ret = unlink(path);
115 + if (ret)
116 + return ret;
117
118 - if (check_interactive && (stat(dst, &st) != -1)) {
119 - snprintf(buf, sizeof(buf), "qfile -Cqev %s 2>/dev/null", dst);
120 - if ((fp = popen(buf, "r")) != NULL) {
121 - buf[0] = '\0';
122 - if (fgets(buf, sizeof(buf), fp) != NULL)
123 - if ((p = strchr(buf, '\n')) != NULL) {
124 - *p = 0;
125 - p = xstrdup(buf);
126 - snprintf(buf, sizeof(buf), "%s/%s", pkg->CATEGORY, pkg->PF);
127 - if (strcmp(buf, p) == 0)
128 - check_interactive = 0;
129 - else
130 - warn("%s owns %s", p, dst);
131 - free(p);
132 - }
133 - pclose(fp);
134 - }
135 + d = strrchr(path, '/');
136 + if (d) {
137 + *d = '\0';
138 + rmdir_r(path);
139 }
140 - snprintf(buf, sizeof(buf), BUSYBOX " mv %s %s %s", check_interactive ? "-i" : "", src, dst);
141 - ret = (system(buf) << 8);
142 - if (ret == 0) {
143 - qprintf("%s>>>%s %s\n", GREEN, NORM, dst);
144 - } else
145 - warn("%s!!!%s %s ret=%d", RED, NORM, dst, ret);
146 +
147 return ret;
148 }
149
150 -void fetch(const char *destdir, const char *src)
151 +#define unlink_q(path) q_unlink_q(path, __FUNCTION__, __LINE__)
152 +
153 +_q_static void fetch(const char *destdir, const char *src)
154 {
155 char buf[BUFSIZ];
156
157 @@ -169,18 +135,47 @@
158 if (getenv("FETCHCOMMAND") != NULL) {
159 snprintf(buf, sizeof(buf), "(export DISTDIR='%s' URI='%s/%s'; %s)",
160 destdir, binhost, src, getenv("FETCHCOMMAND"));
161 + xsystem(buf);
162 } else
163 #endif
164 {
165 - snprintf(buf, sizeof(buf), "%s " BUSYBOX " wget %s -P %s %s/%s", (force_download || install) ? "" : pretend ? "echo " : "",
166 - (quiet ? "-q" : ""), destdir, binhost, src);
167 + pid_t p;
168 + int status;
169 +
170 + const char *prog = (force_download || install) ? "wget" : pretend ? "echo" : "wget";
171 + char *argv[] = {
172 + xstrdup(prog),
173 + xstrdup("-c"),
174 + xstrdup("-P"),
175 + xstrdup(destdir),
176 + buf,
177 + quiet ? xstrdup("-q") : NULL,
178 + NULL,
179 + };
180 + snprintf(buf, sizeof(buf), "%s/%s", binhost, src);
181 +
182 + p = vfork();
183 + if (p == 0)
184 + _exit(execvp(prog, argv));
185 +
186 + free(argv[0]);
187 + free(argv[1]);
188 + free(argv[2]);
189 + free(argv[3]);
190 + free(argv[5]);
191 +
192 + waitpid(p, &status, 0);
193 +#if 0
194 + if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
195 + return;
196 +#endif
197 }
198 - xsystem(buf);
199 +
200 fflush(stdout);
201 fflush(stderr);
202 }
203
204 -static void qmerge_initialize(void)
205 +_q_static void qmerge_initialize(void)
206 {
207 if (strlen(BUSYBOX))
208 if (access(BUSYBOX, X_OK) != 0)
209 @@ -196,9 +191,9 @@
210 errf("PORTAGE_BINHOST= does not appear to be valid");
211
212 if (!search_pkgs && !pretend) {
213 - if (access(pkgdir, R_OK|W_OK|X_OK) != 0)
214 - errf("Wrong perms on PKGDIR='%s'", pkgdir);
215 - mkdir(port_tmpdir, 0755);
216 + if (mkdir_p(pkgdir, 0755))
217 + errp("could not setup PKGDIR: %s", pkgdir);
218 + mkdir_p(port_tmpdir, 0755);
219 }
220
221 xchdir(port_tmpdir);
222 @@ -216,29 +211,67 @@
223 }
224 }
225
226 -char *best_version(const char *CATEGORY, const char *PN)
227 +_q_static char *best_version(const char *CATEGORY, const char *PN)
228 {
229 - static char buf[1024];
230 + /* XXX: The qlist code should be refactored to avoid this fork and I/O */
231 + static char buf[4096];
232 + ssize_t rret;
233 + int status, pipefd[2];
234 + pid_t p;
235 FILE *fp;
236 - char *p;
237
238 - /* if defined(EBUG) this spits out incorrect versions. */
239 - snprintf(buf, sizeof(buf), "qlist -CIev '%s%s%s' 2>/dev/null | tr '\n' ' '",
240 - (CATEGORY != NULL ? CATEGORY : ""), (CATEGORY != NULL ? "/" : ""), PN);
241 + buf[0] = '\0';
242 + if (pipe(pipefd))
243 + return buf;
244
245 - if ((fp = popen(buf, "r")) == NULL)
246 - return NULL;
247 + snprintf(buf, sizeof(buf), "%s%s%s", (CATEGORY != NULL ? CATEGORY : ""),
248 + (CATEGORY != NULL ? "/" : ""), PN);
249
250 - buf[0] = '\0';
251 - if (fgets(buf, sizeof(buf), fp) != NULL)
252 - if ((p = strchr(buf, '\n')) != NULL)
253 - *p = 0;
254 - pclose(fp);
255 - rmspace(buf);
256 - return (char *) buf;
257 + fflush(stdout);
258 +
259 + switch ((p = fork())) {
260 + /* Stupid -Cv screws up global state */
261 + case 0: {
262 + fclose(stdout);
263 + close(pipefd[0]);
264 + if (dup2(pipefd[1], STDOUT_FILENO) != STDOUT_FILENO)
265 + exit(1);
266 + stdout = fdopen(pipefd[1], "w");
267 + if (!stdout)
268 + exit(1);
269 + run_applet_l("qlist", "-CIev", buf, NULL);
270 + exit(0);
271 + }
272 + default:
273 + close(pipefd[1]);
274 + waitpid(p, &status, 0);
275 + }
276 +
277 + fp = fdopen(pipefd[0], "r");
278 + if (!fp) {
279 + close(pipefd[0]);
280 + return buf;
281 + }
282 +
283 + rret = fread(buf, 1, sizeof(buf), fp);
284 + if (rret > 0) {
285 + char *s;
286 +
287 + buf[rret] = '\0';
288 +
289 + s = buf;
290 + while ((s = strchr(s, '\n')) != NULL)
291 + *s = ' ';
292 + rmspace(buf);
293 + }
294 +
295 + /* takes care of close(pipefd[0]) */
296 + fclose(fp);
297 +
298 + return buf;
299 }
300
301 -static int
302 +_q_static int
303 config_protected(const char *buf, int cp_argc, char **cp_argv,
304 int cpm_argc, char **cpm_argv)
305 {
306 @@ -264,7 +297,7 @@
307 return 0;
308 }
309
310 -static void crossmount_rm(const char *fname, const struct stat st)
311 +_q_static void crossmount_rm(const char *fname, const struct stat st)
312 {
313 struct stat lst;
314
315 @@ -312,8 +345,8 @@
316 }
317 }
318
319 -char *atom2str(depend_atom *atom, char *buf, size_t size);
320 -char *atom2str(depend_atom *atom, char *buf, size_t size)
321 +_q_static char *
322 +atom2str(const depend_atom *atom, char *buf, size_t size)
323 {
324 if (atom->PR_int)
325 snprintf(buf, size, "%s-%s-r%i", atom->PN, atom->PV, atom->PR_int);
326 @@ -322,8 +355,8 @@
327 return buf;
328 }
329
330 -char qprint_tree_node(int level, depend_atom *atom, struct pkg_t *pkg);
331 -char qprint_tree_node(int level, depend_atom *atom, struct pkg_t *pkg)
332 +_q_static char
333 +qprint_tree_node(int level, const depend_atom *atom, const struct pkg_t *pkg)
334 {
335 char buf[1024];
336 char *p;
337 @@ -386,40 +419,57 @@
338 return c;
339 }
340
341 -static void pkg_run_func(const char *vdb_path, const char *phases, const char *func)
342 +_q_static void pkg_run_func(const char *vdb_path, const char *phases, const char *func)
343 {
344 + const char *phase;
345 char *script;
346
347 /* This assumes no func is a substring of another func.
348 * Today, that assumption is valid for all funcs ...
349 * The phases are the func with the "pkg_" chopped off. */
350 - if (strstr(phases, func + 4) == NULL)
351 + phase = func + 4;
352 + if (strstr(phases, phase) == NULL) {
353 + qprintf("--- %s\n", func);
354 return;
355 + }
356
357 qprintf(">>> %s\n", func);
358
359 xasprintf(&script,
360 /* Provide funcs required by the PMS */
361 + "EBUILD_PHASE=%3$s\n"
362 "debug-print() { :; }\n"
363 "debug-print-function() { :; }\n"
364 "debug-print-section() { :; }\n"
365 + /* Not quite right */
366 + "has_version() { qlist -ICq -e '$1' >/dev/null; }\n"
367 "use() { useq \"$@\"; }\n"
368 "useq() { hasq $1 $USE; }\n"
369 "has() { hasq \"$@\"; }\n"
370 "hasq() { local h=$1; shift; case \" $* \" in *\" $h \"*) return 0;; *) return 1;; esac; }\n"
371 + "elog() { printf ' * %%b\\n' \"$*\"; }\n"
372 + "einfo() { elog \"$@\"; }\n"
373 + "ewarn() { elog \"$@\"; }\n"
374 + "eerror() { elog \"$@\"; }\n"
375 + "die() { eerror \"$@\"; exit 1; }\n"
376 + "ebegin() { printf ' * %%b ...' \"$*\"; }\n"
377 + "eend() { local r=${1:-$?}; [ $r -eq 0 ] && echo '[ ok ]' || echo '[ !! ]'; return $r; }\n"
378 /* Unpack the env if need be */
379 "[ -e '%1$s/environment' ] || { bzip2 -dc '%1$s/environment.bz2' > '%1$s/environment' || exit 1; }\n"
380 /* Load the env and run the func */
381 - ". %1$s/environment && %2$s",
382 - vdb_path, func);
383 + ". '%1$s/environment' && %2$s\n"
384 + /* Ignore func return values (not exit values) */
385 + ":",
386 + vdb_path, func, phase);
387 xsystembash(script);
388 free(script);
389 }
390
391 /* Copy one tree (the single package) to another tree (ROOT) */
392 -static int merge_tree_at(int fd_src, const char *src, int fd_dst, const char *dst,
393 - FILE *contents, char **cpathp, int iargc, char **iargv,
394 - int cp_argc, char **cp_argv, int cpm_argc, char **cpm_argv)
395 +_q_static int
396 +merge_tree_at(int fd_src, const char *src, int fd_dst, const char *dst,
397 + FILE *contents, queue **objs, char **cpathp, int iargc, char **iargv,
398 + int cp_argc, char **cp_argv, int cpm_argc, char **cpm_argv)
399 {
400 int i, ret, subfd_src, subfd_dst;
401 DIR *dir;
402 @@ -458,7 +508,7 @@
403 /* Build up the full path for this entry */
404 nlen = strlen(name);
405 if (mnlen < nlen) {
406 - cpath = *cpathp = realloc(*cpathp, nlen + clen + 2);
407 + cpath = *cpathp = xrealloc(*cpathp, clen + 1 + nlen + 1);
408 mnlen = nlen;
409 }
410 strcpy(cpath + clen + 1, name);
411 @@ -489,13 +539,21 @@
412 /* XXX: update times of dir ? */
413 }
414
415 +#if 0 /* We filter out "dir" as it's generally unnecessary cruft */
416 /* syntax: dir dirname */
417 fprintf(contents, "dir %s\n", cpath);
418 + *objs = add_set(cpath, "", *objs);
419 qprintf("%s>>>%s %s%s%s/\n", GREEN, NORM, DKBLUE, cpath, NORM);
420 +#endif
421
422 /* Copy all of these contents */
423 - merge_tree_at(subfd_src, name, subfd_dst, name, contents, cpathp,
424 + merge_tree_at(subfd_src, name, subfd_dst, name, contents, objs, cpathp,
425 iargc, iargv, cp_argc, cp_argv, cpm_argc, cpm_argv);
426 + cpath = *cpathp;
427 + mnlen = 0;
428 +
429 + /* In case we didn't install anything, prune the empty dir */
430 + unlinkat(subfd_dst, name, AT_REMOVEDIR);
431 }
432
433 /* Migrate a file */
434 @@ -531,10 +589,11 @@
435 dname = name;
436 qprintf("%s>>>%s %s\n", GREEN, NORM, cpath);
437 }
438 + *objs = add_set(cpath, "", *objs);
439
440 /* First try fast path -- src/dst are same device */
441 - if (renameat(subfd_src, dname, subfd_dst, name))
442 - ;
443 + if (renameat(subfd_src, dname, subfd_dst, name) == 0)
444 + continue;
445
446 /* Fall back to slow path -- manual read/write */
447 fd_srcf = openat(subfd_src, name, O_RDONLY|O_CLOEXEC);
448 @@ -605,6 +664,7 @@
449 /* syntax: sym src -> dst mtime */
450 fprintf(contents, "sym %s -> %s %lu\n", cpath, sym, (unsigned long)st.st_mtime);
451 qprintf("%s>>>%s %s%s -> %s%s\n", GREEN, NORM, CYAN, cpath, sym, NORM);
452 + *objs = add_set(cpath, "", *objs);
453
454 /* Make it in the dest tree */
455 if (symlinkat(sym, subfd_dst, name)) {
456 @@ -630,6 +690,8 @@
457 }
458 }
459
460 + ret = 0;
461 +
462 done:
463 close(subfd_src);
464 close(subfd_dst);
465 @@ -638,8 +700,9 @@
466 }
467
468 /* Copy one tree (the single package) to another tree (ROOT) */
469 -static int merge_tree(const char *src, const char *dst, FILE *contents,
470 - int iargc, char **iargv)
471 +_q_static int
472 +merge_tree(const char *src, const char *dst, FILE *contents,
473 + queue **objs, int iargc, char **iargv)
474 {
475 int ret;
476 int cp_argc, cpm_argc;
477 @@ -654,7 +717,7 @@
478 makeargv(config_protect_mask, &cpm_argc, &cpm_argv);
479
480 cpath = xstrdup("");
481 - ret = merge_tree_at(AT_FDCWD, src, AT_FDCWD, dst, contents, &cpath,
482 + ret = merge_tree_at(AT_FDCWD, src, AT_FDCWD, dst, contents, objs, &cpath,
483 iargc, iargv, cp_argc, cp_argv, cpm_argc, cpm_argv);
484 free(cpath);
485
486 @@ -665,17 +728,16 @@
487 }
488
489 /* oh shit getting into pkg mgt here. FIXME: write a real dep resolver. */
490 -void pkg_merge(int level, depend_atom *atom, struct pkg_t *pkg)
491 +_q_static void
492 +pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg)
493 {
494 + queue *objs;
495 FILE *fp, *contents;
496 char buf[1024], phases[128];
497 - char tarball[255];
498 - char *p;
499 + char *tbz2, *p;
500 int i;
501 char **ARGV;
502 int ARGC;
503 - const char *saved_argv0 = argv0;
504 - int ret, saved_optind = optind;
505 struct stat st;
506 char c;
507 char **iargv;
508 @@ -696,6 +758,8 @@
509 */
510
511 if (pkg->RDEPEND[0] && follow_rdepends) {
512 + const char *rdepend;
513 +
514 IF_DEBUG(fprintf(stderr, "\n+Parent: %s/%s\n", pkg->CATEGORY, pkg->PF));
515 IF_DEBUG(fprintf(stderr, "+Depstring: %s\n", pkg->RDEPEND));
516
517 @@ -703,11 +767,12 @@
518 if (strncmp(pkg->RDEPEND, "|| ", 3) == 0) {
519 if (verbose)
520 qfprintf(stderr, "fix this rdepend hack %s\n", pkg->RDEPEND);
521 - strcpy(pkg->RDEPEND, "");
522 - }
523 + rdepend = "";
524 + } else
525 + rdepend = pkg->RDEPEND;
526 /* </hack> */
527
528 - makeargv(pkg->RDEPEND, &ARGC, &ARGV);
529 + makeargv(rdepend, &ARGC, &ARGV);
530 /* Walk the rdepends here. Merging what need be. */
531 for (i = 1; i < ARGC; i++) {
532 depend_atom *subatom, *ratom;
533 @@ -720,6 +785,7 @@
534 case '=':
535 if (verbose)
536 qfprintf(stderr, "Unhandled depstring %s\n", name);
537 + case '\0':
538 break;
539 default:
540 if (*name == '~') {
541 @@ -731,7 +797,6 @@
542 struct pkg_t *subpkg;
543 char *resolved = NULL;
544
545 - dep = NULL;
546 dep = find_binpkg(name);
547
548 if (strncmp(name, "virtual/", 8) == 0) {
549 @@ -785,11 +850,11 @@
550 if (pretend)
551 return;
552
553 - xchdir(port_tmpdir);
554 -
555 - mkdir(pkg->PF, 0755);
556 - /* mkdir(pkg->PF, 0710); */
557 - xchdir(pkg->PF);
558 + /* Set up our temp dir to unpack this stuff */
559 + xasprintf(&p, "%s/qmerge/%s", port_tmpdir, pkg->PF);
560 + mkdir_p(p, 0755);
561 + xchdir(p);
562 + free(p);
563
564 /* Doesn't actually remove $PWD, just everything under it */
565 rm_rf(".");
566 @@ -798,144 +863,147 @@
567 * tarball directly rather than unpacking it first. */
568
569 /* split the tbz and xpak data */
570 - snprintf(tarball, sizeof(tarball), "%s.tbz2", pkg->PF);
571 - snprintf(buf, sizeof(buf), "%s/%s/%s", pkgdir, pkg->CATEGORY, tarball);
572 - unlink(tarball);
573 - if (symlink(buf, tarball))
574 - errp("symlink(%s, %s) failed", buf, tarball);
575 + xasprintf(&tbz2, "%s/%s/%s.tbz2", pkgdir, pkg->CATEGORY, pkg->PF);
576 + assert(run_applet_l("qtbz2", "-s", tbz2, NULL) == 0);
577 +
578 mkdir("vdb", 0755);
579 - mkdir("image", 0755);
580 + sprintf(tbz2, "%s.xpak", pkg->PF);
581 + assert(run_applet_l("qxpak", "-d", "vdb", "-x", tbz2, NULL) == 0);
582
583 - /* unpack the tarball using our internal qxpak */
584 - ARGC = 3;
585 - ARGV = xmalloc(sizeof(*ARGV) * ARGC);
586 - ARGV[0] = (char *)"qtbz2";
587 - ARGV[1] = (char *)"-s";
588 - ARGV[2] = tarball;
589 - argv0 = ARGV[0];
590 - optind = 0;
591 - assert(qtbz2_main(ARGC, ARGV) == 0);
592 - argv0 = saved_argv0;
593 - optind = saved_optind;
594 - free(ARGV);
595 -
596 - /* list and extract vdb files from the xpak */
597 - snprintf(buf, sizeof(buf), "qxpak -d %s/%s/vdb -x %s.xpak `qxpak -l %s.xpak`",
598 - port_tmpdir, pkg->PF, pkg->PF, pkg->PF);
599 - xsystem(buf);
600 + free(tbz2);
601
602 /* extrct the binary package data */
603 + mkdir("image", 0755);
604 snprintf(buf, sizeof(buf), BUSYBOX " tar -jx%sf %s.tar.bz2 -C image/", ((verbose > 1) ? "v" : ""), pkg->PF);
605 xsystem(buf);
606 fflush(stdout);
607
608 + eat_file("vdb/DEFINED_PHASES", phases, sizeof(phases));
609 + pkg_run_func("vdb", phases, "pkg_preinst");
610 +
611 + /* XXX: kill this off */
612 + xchdir("image");
613 +
614 + if (stat(".", &st) == -1)
615 + err("Cant stat pwd");
616 +
617 + /* Initialize INSTALL_MASK and common stuff */
618 + makeargv(install_mask, &iargc, &iargv);
619 + /* XXX: Would be better if INSTALL_MASK deleted from image/
620 + * so we didn't have to parse it while doing merge_tree() */
621 + install_mask_pwd(iargc, iargv, st);
622 +
623 + if (strstr(features, "noinfo")) rm_rf("./usr/share/info");
624 + if (strstr(features, "noman" )) rm_rf("./usr/share/man");
625 + if (strstr(features, "nodoc" )) rm_rf("./usr/share/doc");
626 +
627 + /* we dont care about the return code */
628 + rmdir("./usr/share");
629 +
630 + /* XXX: Once we kill xchdir(image), this can die too */
631 + xchdir("..");
632 +
633 + if ((contents = fopen("vdb/CONTENTS", "w")) == NULL)
634 + errf("come on wtf?");
635 + objs = NULL;
636 + merge_tree("image", portroot, contents, &objs, iargc, iargv);
637 + fclose(contents);
638 +
639 + freeargv(iargc, iargv);
640 +
641 + /* run postinst */
642 + pkg_run_func("vdb", phases, "pkg_postinst");
643 +
644 + /* XXX: hmm, maybe we'll want to strip more ? */
645 + unlink("vdb/environment");
646 +
647 + /* FIXME */ /* move unmerging to around here ? */
648 /* check for an already installed pkg */
649 snprintf(buf, sizeof(buf), "%s/%s", atom->CATEGORY, pkg->PF);
650
651 - /* Unmerge the other versions */
652 + /* Unmerge any stray pieces from the older version which we didn't replace */
653 p = best_version(atom->CATEGORY, atom->PN);
654 if (*p) {
655 + /* XXX: Should see about merging with unmerge_packages() */
656 makeargv(p, &ARGC, &ARGV);
657 for (i = 1; i < ARGC; i++) {
658 - char pf[126];
659 + int ret, u;
660 + const char *pn;
661 + char *pf;
662 char *slot = NULL;
663 - char u;
664
665 - strncpy(pf, ARGV[i], sizeof(pf));
666 + pf = ARGV[i];
667 switch ((ret = atom_compare_str(buf, pf))) {
668 - case ERROR: break;
669 - case NOT_EQUAL: break;
670 + case ERROR:
671 + case NOT_EQUAL:
672 + continue;
673 case NEWER:
674 case OLDER:
675 case EQUAL:
676 u = 1;
677 - slot = grab_vdb_item("SLOT", atom->CATEGORY, basename(pf));
678 + pn = basename(pf);
679 + slot = grab_vdb_item("SLOT", atom->CATEGORY, pn);
680 if (pkg->SLOT[0] && slot) {
681 if (strcmp(pkg->SLOT, slot) != 0)
682 u = 0;
683 }
684 /* We need to really set this unmerge pending after we look at contents of the new pkg */
685 if (u)
686 - pkg_unmerge(atom->CATEGORY, basename(pf));
687 - break;
688 + break;
689 + continue;
690 default:
691 warn("no idea how we reached here.");
692 - break;
693 + continue;
694 }
695 - qprintf("%s+++%s %s %s %s\n", GREEN, NORM, buf, booga[ret], ARGV[i]);
696 +
697 + qprintf("%s+++%s %s %s %s\n", GREEN, NORM, buf, booga[ret], pf);
698 +
699 + pkg_unmerge(atom->CATEGORY, pn, objs);
700 }
701 freeargv(ARGC, ARGV);
702 }
703
704 - xchdir("image");
705 -
706 - eat_file("../vdb/DEFINED_PHASES", phases, sizeof(phases));
707 - pkg_run_func("../vdb", phases, "pkg_preinst");
708 -
709 - if (stat(".", &st) == -1)
710 - err("Cant stat pwd");
711 -
712 - /* Initialize INSTALL_MASK and common stuff */
713 - makeargv(install_mask, &iargc, &iargv);
714 - install_mask_pwd(iargc, iargv, st);
715 -
716 - if (strstr(features, "noinfo")) rm_rf("./usr/share/info");
717 - if (strstr(features, "noman" )) rm_rf("./usr/share/man");
718 - if (strstr(features, "nodoc" )) rm_rf("./usr/share/doc");
719 -
720 - /* we dont care about the return code */
721 - rmdir("./usr/share");
722 -
723 - if ((contents = fopen("../vdb/CONTENTS", "w")) == NULL)
724 - errf("come on wtf?");
725 -
726 - merge_tree(".", portroot, contents, iargc, iargv);
727 -
728 - fclose(contents);
729 -
730 - freeargv(iargc, iargv);
731 -
732 - xchdir(port_tmpdir);
733 - xchdir(pkg->PF);
734 -
735 - /* run postinst */
736 - pkg_run_func("./vdb", phases, "pkg_postinst");
737 -
738 - /* FIXME */ /* move unmerging to around here ? */
739 - /* not perfect when a version is already installed */
740 - snprintf(buf, sizeof(buf), "%s/var/db/pkg/%s/", portroot, pkg->CATEGORY);
741 - if (access(buf, R_OK|W_OK|X_OK) != 0)
742 - mkdir_p(buf, 0755);
743 - strncat(buf, pkg->PF, sizeof(buf)-strlen(buf)-1);
744 - if (access(buf, X_OK) == 0) {
745 - /* we need to compare CONTENTS in it and remove any file not provided by our CONTENTS */
746 - rm_rf(buf);
747 + /* Clean up the package state */
748 + while (objs) {
749 + queue *q = objs;
750 + objs = q->next;
751 + free(q->name);
752 + free(q->item);
753 + free(q);
754 }
755
756 + /* Update the magic counter */
757 if ((fp = fopen("vdb/COUNTER", "w")) != NULL) {
758 fputs("0", fp);
759 fclose(fp);
760 }
761 +
762 /* move the local vdb copy to the final place */
763 - interactive_rename("vdb", buf, pkg);
764 + snprintf(buf, sizeof(buf), "%s%s/%s/", portroot, portvdb, pkg->CATEGORY);
765 + mkdir_p(buf, 0755);
766 + strcat(buf, pkg->PF);
767 + if (rename("vdb", buf)) {
768 + xasprintf(&p, "mv vdb '%s'", buf);
769 + xsystem(p);
770 + free(p);
771 + }
772
773 - snprintf(buf, sizeof(buf), "%s.tar.bz2", pkg->PF);
774 - unlink_q(buf);
775 - xchdir(port_tmpdir);
776 + /* clean up our local temp dir */
777 + xchdir("..");
778 rm_rf(pkg->PF);
779 -
780 - snprintf(buf, sizeof(buf), "%s/%s.tbz2", pkgdir, pkg->PF);
781 - unlink(buf);
782 + /* don't care about return */
783 + rmdir("../qmerge");
784
785 printf("%s>>>%s %s%s%s/%s%s%s\n", YELLOW, NORM, WHITE, atom->CATEGORY, NORM, CYAN, atom->PN, NORM);
786 }
787
788 -int pkg_unmerge(const char *cat, const char *pkgname)
789 +_q_static int
790 +pkg_unmerge(const char *cat, const char *pkgname, queue *keep)
791 {
792 size_t buflen;
793 char *buf, *vdb_path, phases[128];
794 FILE *fp;
795 - int ret, fd, vdb_fd;
796 + int ret, fd, vdb_fd, portroot_fd;
797 int cp_argc, cpm_argc;
798 char **cp_argv, **cpm_argv;
799 llist_char *dirs = NULL;
800 @@ -943,7 +1011,7 @@
801 ret = 1;
802 buf = NULL;
803 vdb_path = NULL;
804 - vdb_fd = fd = -1;
805 + vdb_fd = portroot_fd = fd = -1;
806
807 if ((strchr(pkgname, ' ') != NULL) || (strchr(cat, ' ') != NULL)) {
808 qfprintf(stderr, "%s!!!%s '%s' '%s' (ambiguous name) specify fully-qualified pkgs\n", RED, NORM, cat, pkgname);
809 @@ -956,9 +1024,17 @@
810 if (pretend == 100)
811 return 0;
812
813 + /* Get a handle to the root to play with */
814 + portroot_fd = open(portroot, O_RDONLY | O_CLOEXEC);
815 + if (portroot_fd == -1) {
816 + warnp("unable to read %s", portroot);
817 + goto done;
818 + }
819 +
820 /* Get a handle on the vdb path which we'll use everywhere else */
821 - xasprintf(&vdb_path, "%s/%s/%s/%s/", portroot, portvdb, cat, pkgname);
822 - vdb_fd = open(vdb_path, O_RDONLY | O_CLOEXEC);
823 + /* Note: This vdb_path must be absolute since we use it in pkg_run_func() */
824 + xasprintf(&vdb_path, "%s%s/%s/%s/", portroot, portvdb, cat, pkgname);
825 + vdb_fd = openat(portroot_fd, vdb_path, O_RDONLY | O_CLOEXEC);
826 if (vdb_fd == -1) {
827 warnp("unable to read %s", vdb_path);
828 goto done;
829 @@ -988,66 +1064,84 @@
830 makeargv(config_protect_mask, &cpm_argc, &cpm_argv);
831
832 while (getline(&buf, &buflen, fp) != -1) {
833 + queue *q;
834 contents_entry *e;
835 char zing[20];
836 int protected = 0;
837 - struct stat lst;
838 - char dst[_Q_PATH_MAX];
839 + struct stat st;
840
841 e = contents_parse_line(buf);
842 - if (!e) continue;
843 - snprintf(dst, sizeof(dst), "%s%s", portroot, e->name);
844 + if (!e)
845 + continue;
846 +
847 protected = config_protected(e->name, cp_argc, cp_argv, cpm_argc, cpm_argv);
848 snprintf(zing, sizeof(zing), "%s%s%s", protected ? YELLOW : GREEN, protected ? "***" : "<<<" , NORM);
849
850 + /* This should never happen ... */
851 + assert(e->name[0] == '/' && e->name[1] != '/');
852 +
853 /* Should we remove in order symlinks,objects,dirs ? */
854 switch (e->type) {
855 case CONTENTS_DIR:
856 if (!protected) {
857 /* since the dir contains files, we remove it later */
858 llist_char *list = xmalloc(sizeof(llist_char));
859 - list->data = xstrdup(dst);
860 + list->data = xstrdup(e->name);
861 list->next = dirs;
862 dirs = list;
863 }
864 - break;
865 + continue;
866 +
867 case CONTENTS_OBJ:
868 - if (!protected)
869 - unlink_q(dst);
870 - qprintf("%s %s\n", zing, dst);
871 break;
872 +
873 case CONTENTS_SYM:
874 - if (protected)
875 - break;
876 - if (e->name[0] != '/')
877 - break;
878 - if (e->sym_target[0] != '/') {
879 - if (lstat(dst, &lst) != -1) {
880 - if (S_ISLNK(lst.st_mode)) {
881 - qprintf("%s %s%s -> %s%s\n", zing, CYAN, dst, e->sym_target, NORM);
882 - unlink_q(dst);
883 - break;
884 - }
885 - } else {
886 - warnp("lstat failed for %s -> '%s'", dst, e->sym_target);
887 - }
888 - warn("!!! %s -> %s", e->name, e->sym_target);
889 - break;
890 - }
891 - if (lstat(dst, &lst) != -1) {
892 - if (S_ISLNK(lst.st_mode)) {
893 - qprintf("%s %s%s -> %s%s\n", zing, CYAN, dst, e->sym_target, NORM);
894 - unlink_q(dst);
895 - } else {
896 - warn("%s is not a symlink", dst);
897 - }
898 - } else {
899 - warnp("lstat failed for '%s' -> %s", dst, e->sym_target);
900 + if (fstatat(portroot_fd, e->name + 1, &st, AT_SYMLINK_NOFOLLOW)) {
901 + warnp("stat failed for %s -> '%s'", e->name, e->sym_target);
902 + continue;
903 }
904 +
905 + /* Hrm, if it isn't a symlink anymore, then leave it be */
906 + if (!S_ISLNK(st.st_mode))
907 + continue;
908 +
909 break;
910 +
911 default:
912 - warn("%s???%s %s%s%s (%d)", RED, NORM, WHITE, dst, NORM, e->type);
913 + warn("%s???%s %s%s%s (%d)", RED, NORM, WHITE, e->name, NORM, e->type);
914 + continue;
915 + }
916 +
917 + if (protected) {
918 + qprintf("%s %s\n", zing, e->name);
919 + continue;
920 + }
921 +
922 + /* See if this was updated */
923 + q = keep;
924 + while (q) {
925 + if (!strcmp(q->name, e->name)) {
926 + /* XXX: could remove this from the queue */
927 + strcpy(zing, "---");
928 + q = NULL;
929 break;
930 + }
931 + q = q->next;
932 + }
933 +
934 + /* No match, so unmerge it */
935 + if (!quiet)
936 + printf("%s %s\n", zing, e->name);
937 + if (!keep || q) {
938 + char *p;
939 +
940 + unlinkat(portroot_fd, e->name + 1, 0);
941 +
942 + p = strrchr(e->name, '/');
943 + if (p) {
944 + *p = '\0';
945 + rmdir_r_at(portroot_fd, e->name + 1);
946 + }
947 }
948 }
949
950 @@ -1060,7 +1154,7 @@
951 char *dir = list->data;
952 int rm;
953
954 - rm = pretend ? -1 : rmdir(dir);
955 + rm = pretend ? -1 : rmdir_r_at(portroot_fd, dir + 1);
956 qprintf("%s%s%s %s%s%s/\n", rm ? YELLOW : GREEN, rm ? "---" : "<<<",
957 NORM, DKBLUE, dir, NORM);
958
959 @@ -1079,15 +1173,10 @@
960 pkg_run_func(vdb_path, phases, "pkg_postrm");
961
962 /* Finally delete the vdb entry */
963 - rm_rf(vdb_path);
964 + rm_rf_at(portroot_fd, vdb_path);
965
966 /* And prune any empty vdb dirs */
967 - dir = strrchr(vdb_path, '/');
968 - *dir = '\0';
969 - rmdir(vdb_path);
970 - dir = strrchr(vdb_path, '/');
971 - *dir = '\0';
972 - rmdir(vdb_path);
973 + rmdir_r_at(portroot_fd, vdb_path);
974 }
975
976 ret = 0;
977 @@ -1096,13 +1185,15 @@
978 close(fd);
979 if (vdb_fd != -1)
980 close(vdb_fd);
981 + if (portroot_fd != -1)
982 + close(portroot_fd);
983 free(buf);
984 free(vdb_path);
985
986 return ret;
987 }
988
989 -int unlink_empty(char *buf)
990 +_q_static int unlink_empty(const char *buf)
991 {
992 struct stat st;
993 if (stat(buf, &st) != -1)
994 @@ -1111,7 +1202,7 @@
995 return -1;
996 }
997
998 -static int match_pkg(queue *ll, struct pkg_t *pkg)
999 +_q_static int match_pkg(queue *ll, const struct pkg_t *pkg)
1000 {
1001 depend_atom *atom;
1002 char buf[255], buf2[255];
1003 @@ -1154,7 +1245,9 @@
1004 return match;
1005 }
1006
1007 -int pkg_verify_checksums(char *fname, struct pkg_t *pkg, depend_atom *atom, int strict, int display)
1008 +_q_static int
1009 +pkg_verify_checksums(char *fname, const struct pkg_t *pkg, const depend_atom *atom,
1010 + int strict, int display)
1011 {
1012 char *hash = NULL;
1013 int ret = 0;
1014 @@ -1197,7 +1290,8 @@
1015 return ret;
1016 }
1017
1018 -static void pkg_process(queue *todo, struct pkg_t *pkg)
1019 +_q_static
1020 +void pkg_process(queue *todo, const struct pkg_t *pkg)
1021 {
1022 queue *ll;
1023 depend_atom *atom;
1024 @@ -1221,11 +1315,10 @@
1025 atom_implode(atom);
1026 }
1027
1028 -void pkg_fetch(int level, depend_atom *atom, struct pkg_t *pkg)
1029 +_q_static void
1030 +pkg_fetch(int level, const depend_atom *atom, const struct pkg_t *pkg)
1031 {
1032 - char savecwd[_POSIX_PATH_MAX];
1033 - char buf[255], str[255];
1034 - memset(str, 0, sizeof(str));
1035 + char buf[_Q_PATH_MAX], str[_Q_PATH_MAX];
1036
1037 /* qmerge -pv patch */
1038 if (pretend) {
1039 @@ -1242,6 +1335,8 @@
1040 snprintf(str, sizeof(str), "%s/%s", pkgdir, pkg->CATEGORY);
1041 mkdir(str, 0755);
1042
1043 + /* XXX: should do a size check here for partial downloads */
1044 +
1045 if (force_download && (access(buf, R_OK) == 0) && (pkg->SHA1[0] || pkg->MD5[0])) {
1046 if (pkg_verify_checksums(buf, pkg, atom, 0, 0) != 0)
1047 unlink(buf);
1048 @@ -1251,7 +1346,7 @@
1049 warn("No checksum data for %s", buf);
1050 return;
1051 } else {
1052 - if (pkg_verify_checksums(buf, pkg, atom, qmerge_strict, 1) == 0) {
1053 + if (pkg_verify_checksums(buf, pkg, atom, qmerge_strict, !quiet) == 0) {
1054 pkg_merge(0, atom, pkg);
1055 return;
1056 }
1057 @@ -1282,25 +1377,16 @@
1058 fflush(stderr);
1059 return;
1060 }
1061 - xgetcwd(savecwd, sizeof(savecwd));
1062 - xchdir(pkgdir);
1063 - if (chdir("All/") == 0) {
1064 - snprintf(buf, sizeof(buf), "%s.tbz2", pkg->PF);
1065 - snprintf(str, sizeof(str), "../%s/%s.tbz2", atom->CATEGORY, pkg->PF);
1066 - unlink(buf);
1067 - if (symlink(str, buf))
1068 - errp("symlink(%s, %s) failed", str, buf);
1069 - }
1070 - xchdir(savecwd);
1071
1072 snprintf(buf, sizeof(buf), "%s/%s/%s.tbz2", pkgdir, atom->CATEGORY, pkg->PF);
1073 - if (pkg_verify_checksums(buf, pkg, atom, qmerge_strict, 1) == 0) {
1074 + if (pkg_verify_checksums(buf, pkg, atom, qmerge_strict, !quiet) == 0) {
1075 pkg_merge(0, atom, pkg);
1076 return;
1077 }
1078 }
1079
1080 -void print_Pkg(int full, struct pkg_t *pkg)
1081 +_q_static void
1082 +print_Pkg(int full, struct pkg_t *pkg)
1083 {
1084 char *p = NULL;
1085 char buf[512];
1086 @@ -1358,10 +1444,13 @@
1087 atom_implode(atom);
1088 }
1089
1090 -static int unmerge_packages(queue *todo)
1091 +_q_static int
1092 +unmerge_packages(queue *todo)
1093 {
1094 depend_atom *atom;
1095 char *p;
1096 + int i, argc;
1097 + char **argv;
1098
1099 while (todo) {
1100 char buf[512];
1101 @@ -1372,11 +1461,18 @@
1102 p = best_version(NULL, todo->name);
1103 if (!*p)
1104 goto next;
1105 - if ((atom = atom_explode(p)) == NULL)
1106 - goto next;
1107 - atom2str(atom, buf, sizeof(buf));
1108 - pkg_unmerge(atom->CATEGORY, buf);
1109 - atom_implode(atom);
1110 +
1111 + makeargv(p, &argc, &argv);
1112 + for (i = 1; i < argc; ++i) {
1113 + if ((atom = atom_explode(argv[i])) == NULL)
1114 + continue;
1115 + if (atom->CATEGORY) {
1116 + atom2str(atom, buf, sizeof(buf));
1117 + pkg_unmerge(atom->CATEGORY, buf, NULL);
1118 + }
1119 + atom_implode(atom);
1120 + }
1121 + freeargv(argc, argv);
1122
1123 next:
1124 todo = todo->next;
1125 @@ -1385,7 +1481,8 @@
1126 return 0;
1127 }
1128
1129 -struct pkg_t *grab_binpkg_info(const char *name)
1130 +_q_static struct pkg_t *
1131 +grab_binpkg_info(const char *name)
1132 {
1133 FILE *fp;
1134 char buf[BUFSIZ];
1135 @@ -1490,7 +1587,8 @@
1136 return rpkg;
1137 }
1138
1139 -char *find_binpkg(const char *name)
1140 +_q_static char *
1141 +find_binpkg(const char *name)
1142 {
1143 FILE *fp;
1144 char buf[BUFSIZ];
1145 @@ -1572,7 +1670,8 @@
1146 return best_match;
1147 }
1148
1149 -static int parse_packages(queue *todo)
1150 +_q_static int
1151 +parse_packages(queue *todo)
1152 {
1153 FILE *fp;
1154 size_t buflen;
1155 @@ -1670,7 +1769,8 @@
1156 return 0;
1157 }
1158
1159 -static queue *qmerge_add_set_atom(char *satom, queue *set)
1160 +_q_static queue *
1161 +qmerge_add_set_atom(char *satom, queue *set)
1162 {
1163 char *p;
1164 const char *slot;
1165 @@ -1684,30 +1784,22 @@
1166 return add_set(satom, slot, set);
1167 }
1168
1169 -static queue *qmerge_add_set_file(const char *file, queue *set)
1170 +_q_static queue *
1171 +qmerge_add_set_file(const char *dir, const char *file, queue *set)
1172 {
1173 FILE *fp;
1174 size_t buflen;
1175 - char *buf;
1176 - const char *fname;
1177 + char *buf, *fname;
1178
1179 /* Find the file to read */
1180 - if (*portroot && strcmp(portroot, "/") != 0) {
1181 - size_t len, flen;
1182 - char *f;
1183 -
1184 - len = strlen(portroot);
1185 - flen = strlen(file) + 1;
1186 - fname = f = alloca(len + flen);
1187 - memcpy(f, portroot, len);
1188 - memcpy(f + len, file, flen);
1189 - } else
1190 - fname = file;
1191 + xasprintf(&fname, "%s%s/%s", portroot, dir, file);
1192
1193 if ((fp = fopen(fname, "r")) == NULL) {
1194 warnp("unable to read set file %s", fname);
1195 + free(fname);
1196 return NULL;
1197 }
1198 + free(fname);
1199
1200 /* Load each entry */
1201 buf = NULL;
1202 @@ -1722,17 +1814,48 @@
1203 return set;
1204 }
1205
1206 -static queue *qmerge_add_set(char *buf, queue *set)
1207 +_q_static void *
1208 +qmerge_add_set_system(void *data, char *buf, FILE *fp)
1209 +{
1210 + queue *set = data;
1211 + char *s;
1212 +
1213 + s = strchr(buf, '#');
1214 + if (s)
1215 + *s = '\0';
1216 + rmspace(buf);
1217 +
1218 + s = buf;
1219 + if (*s == '*')
1220 + set = add_set(s + 1, "", set);
1221 + else if (s[0] == '-' && s[1] == '*') {
1222 + int ok;
1223 + set = del_set(s + 2, set, &ok);
1224 + }
1225 +
1226 + return set;
1227 +}
1228 +
1229 +/* XXX: note, this doesn't handle more complicated set files like
1230 + * the portage .ini files in /usr/share/portage/sets/ */
1231 +/* XXX: this code does not combine duplicate dependencies */
1232 +_q_static queue *
1233 +qmerge_add_set(char *buf, queue *set)
1234 {
1235 if (strcmp(buf, "world") == 0)
1236 - return qmerge_add_set_file("/var/lib/portage/world", set);
1237 - if (strcmp(buf, "all") == 0)
1238 + return qmerge_add_set_file("/var/lib/portage", "world", set);
1239 + else if (strcmp(buf, "all") == 0)
1240 return get_vdb_atoms(0);
1241 - /* XXX: Should load custom sets here */
1242 - return qmerge_add_set_atom(buf, set);
1243 + else if (strcmp(buf, "system") == 0)
1244 + return q_profile_walk("packages", qmerge_add_set_system, set);
1245 + else if (buf[0] == '@')
1246 + return qmerge_add_set_file("/etc/portage", buf+1, set);
1247 + else
1248 + return qmerge_add_set_atom(buf, set);
1249 }
1250
1251 -static int qmerge_run(queue *todo)
1252 +_q_static int
1253 +qmerge_run(queue *todo)
1254 {
1255 if (uninstall)
1256 return unmerge_packages(todo);