From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 477B71382C5 for ; Mon, 25 May 2020 10:44:04 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id EDAA6E0863; Mon, 25 May 2020 10:44:01 +0000 (UTC) Received: from smtp.gentoo.org (dev.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id CAD4DE0863 for ; Mon, 25 May 2020 10:44:01 +0000 (UTC) Received: from oystercatcher.gentoo.org (unknown [IPv6:2a01:4f8:202:4333:225:90ff:fed9:fc84]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id C8DE034F01B for ; Mon, 25 May 2020 10:44:00 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id D0B0426E for ; Mon, 25 May 2020 10:43:56 +0000 (UTC) From: "Fabian Groffen" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Fabian Groffen" Message-ID: <1590403145.f2e63b4a1280d0a2c18cb1a66ceffd9699d1b9ac.grobian@gentoo> Subject: [gentoo-commits] proj/portage-utils:master commit in: / X-VCS-Repository: proj/portage-utils X-VCS-Files: qmerge.c X-VCS-Directories: / X-VCS-Committer: grobian X-VCS-Committer-Name: Fabian Groffen X-VCS-Revision: f2e63b4a1280d0a2c18cb1a66ceffd9699d1b9ac X-VCS-Branch: master Date: Mon, 25 May 2020 10:43:56 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Archives-Salt: c07e9d29-508a-4959-80b3-f49d3159c254 X-Archives-Hash: 8be0e5cbde1b172ff9243dc7637cfa07 commit: f2e63b4a1280d0a2c18cb1a66ceffd9699d1b9ac Author: Fabian Groffen gentoo org> AuthorDate: Mon May 25 10:39:05 2020 +0000 Commit: Fabian Groffen gentoo org> CommitDate: Mon May 25 10:39:05 2020 +0000 URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=f2e63b4a qmerge: use libq/tree for binpkg/Packages needs Instead of manual parsing of Packages file and traversing binpkgs, use the functionality provided by libq/tree, most notably tree_match_atom(). This is just phase one, where we replace the custom code with libq/tree code and then fill in the Pkg structure. In a next phase we should skip this and directly use tree_match_ctx, with atom and meta in there. Signed-off-by: Fabian Groffen gentoo.org> qmerge.c | 596 +++++++++++++-------------------------------------------------- 1 file changed, 116 insertions(+), 480 deletions(-) diff --git a/qmerge.c b/qmerge.c index 087c5f2..554e3dc 100644 --- a/qmerge.c +++ b/qmerge.c @@ -120,8 +120,7 @@ typedef struct llist_char_t llist_char; static void pkg_fetch(int, const depend_atom *, const struct pkg_t *); static void pkg_merge(int, const depend_atom *, const struct pkg_t *); static int pkg_unmerge(tree_pkg_ctx *, set *, int, char **, int, char **); -static struct pkg_t *grab_binpkg_info(const char *); -static char *find_binpkg(const char *); +static struct pkg_t *grab_binpkg_info(depend_atom *); static bool prompt(const char *p) @@ -129,12 +128,12 @@ prompt(const char *p) printf("%s? [Y/n] ", p); fflush(stdout); switch (getc(stdin)) { - case '\n': - case 'y': - case 'Y': - return true; - default: - return false; + case '\n': + case 'y': + case 'Y': + return true; + default: + return false; } } @@ -579,7 +578,7 @@ qprint_tree_node(int level, const depend_atom *atom, const struct pkg_t *pkg) } else { depend_atom *subatom = atom_explode(p); if (subatom != NULL) { - ret = atom_compare(atom, subatom); + ret = atom_compare(subatom, atom); switch (ret) { case EQUAL: c = 'R'; break; case NEWER: c = 'U'; break; @@ -1009,7 +1008,7 @@ pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg) if (((c == 'R') || (c == 'D')) && update_only) return; - if (pkg->RDEPEND[0] && follow_rdepends) { + if (pkg->RDEPEND[0] != '\0' && follow_rdepends) { const char *rdepend; IF_DEBUG(fprintf(stderr, "\n+Parent: %s/%s\n", pkg->CATEGORY, pkg->PF)); @@ -1040,30 +1039,17 @@ pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg) case '\0': break; default: - if (*name == '~') { - name = ARGV[i] + 1; - /* warn("newname = %s", name); */ - } if ((subatom = atom_explode(name)) != NULL) { struct pkg_t *subpkg; - char *resolved = NULL; - - resolved = find_binpkg(name); - IF_DEBUG(fprintf(stderr, - "+Atom: argv0(%s) resolved(%s)\n", - name, resolved)); - - if (strlen(resolved) < 1) { - warn("Cant find a binpkg for %s from rdepend(%s)", + subpkg = grab_binpkg_info(subatom); /* free me later */ + if (subpkg == NULL) { + warn("Cannot find a binpkg for %s from rdepend(%s)", name, pkg->RDEPEND); atom_implode(subatom); continue; } - /* ratom = atom_explode(resolved); */ - subpkg = grab_binpkg_info(resolved); /* free me later */ - assert(subpkg != NULL); IF_DEBUG(fprintf(stderr, "+Subpkg: %s/%s\n", subpkg->CATEGORY, subpkg->PF)); @@ -1182,7 +1168,8 @@ pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg) } else if (mlen == 257+6 && magic[257] == 'u' && magic[258] == 's' && magic[259] == 't' && magic[260] == 'a' && - magic[261] == 'r' && magic[262] == '\0') + magic[261] == 'r' && + (magic[262] == '\0' || magic[262] == ' ')) { compr = ""; } else if (mlen >= 4 && @@ -1399,7 +1386,7 @@ pkg_merge(int level, const depend_atom *atom, const struct pkg_t *pkg) rmdir("../qmerge"); printf("%s>>>%s %s%s%s/%s%s%s\n", - YELLOW, NORM, WHITE, atom->CATEGORY, NORM, CYAN, pkg->PF, NORM); + YELLOW, NORM, WHITE, pkg->CATEGORY, NORM, CYAN, pkg->PF, NORM); tree_close_cat(cat_ctx); tree_close(vdb); @@ -1622,7 +1609,7 @@ pkg_verify_checksums( } if (pkg->MD5[0]) { - if (md5 != NULL && strcmp(md5, pkg->MD5) == 0) { + if (strcmp(md5, pkg->MD5) == 0) { if (display) printf("MD5: [%sOK%s] %s %s/%s\n", GREEN, NORM, md5, atom->CATEGORY, pkg->PF); @@ -1634,7 +1621,7 @@ pkg_verify_checksums( } } - if (sha1 != NULL && pkg->SHA1[0]) { + if (pkg->SHA1[0]) { if (strcmp(sha1, pkg->SHA1) == 0) { if (display) qprintf("SHA1: [%sOK%s] %s %s/%s\n", @@ -1663,7 +1650,8 @@ pkg_fetch(int level, const depend_atom *atom, const struct pkg_t *pkg) /* qmerge -pv patch */ if (pretend) { - if (!install) install++; + if (!install) + install++; /* qprint_tree_node(level, atom, pkg); */ pkg_merge(level, atom, pkg); return; @@ -1679,13 +1667,12 @@ pkg_fetch(int level, const depend_atom *atom, const struct pkg_t *pkg) return; } - /* XXX: should do a size check here for partial downloads */ - if (force_download && (access(buf, R_OK) == 0) && (pkg->SHA1[0] || pkg->MD5[0])) { if (pkg_verify_checksums(buf, pkg, atom, 0, 0) != 0) - unlink(buf); + if (getenv("QMERGE") == NULL) + unlink(buf); } if (access(buf, R_OK) == 0) { if (!pkg->SHA1[0] && !pkg->MD5[0]) { @@ -1742,7 +1729,7 @@ print_Pkg(int full, const depend_atom *atom, const struct pkg_t *pkg) char *p = NULL; char buf[512]; - printf("%s%s/%s%s:%s%s%s%s%s\n", BOLD, atom->CATEGORY, BLUE, pkg->PF, pkg->SLOT, NORM, + printf("%s%s%s%s\n", atom_format("%[CAT]%[PF]%[SLOT]", atom), !quiet ? " [" : "", !quiet ? make_human_readable_str(pkg->SIZE, 1, KILOBYTE) : "", !quiet ? " KiB]" : ""); @@ -1757,7 +1744,8 @@ print_Pkg(int full, const depend_atom *atom, const struct pkg_t *pkg) if (pkg->MD5[0]) printf(" %sMd5%s:%s %s\n", DKGREEN, YELLOW, NORM, pkg->MD5); if (!pkg->MD5[0] && !pkg->SHA1[0]) - printf(" %sSums%s:%s %s(MISSING!)%s\n", DKGREEN, YELLOW, NORM, RED, NORM); + printf(" %sSums%s:%s %s(MISSING!)%s\n", + DKGREEN, YELLOW, NORM, RED, NORM); if (pkg->SLOT[0]) printf(" %sSlot%s:%s %s\n", DKGREEN, YELLOW, NORM, pkg->SLOT); if (pkg->LICENSE[0]) @@ -1781,7 +1769,8 @@ print_Pkg(int full, const depend_atom *atom, const struct pkg_t *pkg) case OLDER: icolor = BLUE; break; default: icolor = NORM; break; } - printf(" %sInstalled%s:%s %s%s%s\n", DKGREEN, YELLOW, NORM, icolor, p, NORM); + printf(" %sInstalled%s:%s %s%s%s\n", + DKGREEN, YELLOW, NORM, icolor, p, NORM); } } } @@ -1833,453 +1822,70 @@ unmerge_packages(set *todo) return ret; } -static FILE * -open_binpkg_index(void) -{ - FILE *fp; - char *path; - - xasprintf(&path, "%s/portage/%s", port_tmpdir, Packages); - fp = fopen(path, "r"); - if (fp) - goto done; - free(path); - - xasprintf(&path, "%s/%s", pkgdir, Packages); - fp = fopen(path, "r"); - if (fp) - goto done; - - /* This is normal when installing from local repo only. */ - warnp("Unable to open package file %s in %s/portage or %s", - Packages, port_tmpdir, pkgdir); - warn("Attempting to manually regen via `emaint binhost`"); - - pid_t p; - int status; - - char argv_emaint[] = "emaint"; - char argv_binhost[] = "binhost"; - char argv_fix[] = "--fix"; - char *argv[] = { - argv_emaint, - argv_binhost, - argv_fix, - NULL, - }; - - p = vfork(); - switch (p) { - case 0: - _exit(execvp(argv[0], argv)); - case -1: - errp("vfork failed"); - } - waitpid(p, &status, 0); - - fp = fopen(path, "r"); - - done: - free(path); - return fp; -} - +static tree_ctx *_grab_binpkg_info_tree = NULL; static struct pkg_t * -grab_binpkg_info(const char *name) -{ - FILE *fp; - char buf[BUFSIZ]; - char *p; - depend_atom *atom; - - struct pkg_t Pkg; - struct pkg_t *pkg = xzalloc(sizeof(struct pkg_t)); - struct pkg_t *rpkg = xzalloc(sizeof(struct pkg_t)); - - static char best_match[sizeof(Pkg.PF)+2+sizeof(Pkg.CATEGORY)]; - - best_match[0] = 0; - strcpy(pkg->SLOT,"0"); - - fp = open_binpkg_index(); - - while (fgets(buf, sizeof(buf), fp) != NULL) { - if (*buf == '\n') { - if (pkg->PF[0] && pkg->CATEGORY[0]) { - int ret; - - snprintf(buf, sizeof(buf), "%s/%s", pkg->CATEGORY, pkg->PF); - if (strstr(buf, name) != NULL) { - if (!best_match[0]) - snprintf(best_match, sizeof(best_match), "%.*s", - (int)sizeof(best_match) - 1, buf); - - atom = atom_explode(buf); - if (atom->PR_int) { - snprintf(buf, sizeof(buf), "%s/%s-%s-r%i", - atom->CATEGORY, atom->PN, - atom->PV, atom->PR_int); - } else { - snprintf(buf, sizeof(buf), "%s/%s-%s", - atom->CATEGORY, atom->PN, atom->PV); - } - ret = atom_compare_str(name, buf); - IF_DEBUG(fprintf(stderr, - "=== atom_compare(%s, %s) = %d %s\n", - name, buf, ret, booga[ret])); - /* buf(%s) depend(%s)\n", ret, pkg->CATEGORY, - * pkg->PF, name, pkg->RDEPEND); */ - switch (ret) { - case EQUAL: - case NEWER: - snprintf(buf, sizeof(buf), "%s/%s", - pkg->CATEGORY, pkg->PF); - ret = atom_compare_str(buf, best_match); - if (ret == NEWER || ret == EQUAL) { - snprintf(best_match, sizeof(best_match), "%.*s", - (int)sizeof(best_match) - 1, buf); - memcpy(rpkg, pkg, sizeof(struct pkg_t)); - IF_DEBUG(fprintf(stderr, - "--- %s/%s depend(%s)\n", - rpkg->CATEGORY, rpkg->PF, - rpkg->RDEPEND)); - } - case OLDER: break; - default: - break; - } - atom_implode(atom); - } - memset(pkg, 0, sizeof(struct pkg_t)); - strcpy(pkg->SLOT,"0"); - } - continue; - } - - if ((p = strchr(buf, '\n')) != NULL) - *p = 0; - if ((p = strchr(buf, ':')) == NULL) - continue; - if (p[1] != ' ') - continue; - *p = 0; - p += 2; - - if (*buf) { - /* we dont need all the info */ - if (strcmp(buf, "RDEPEND") == 0) - snprintf(pkg->RDEPEND, sizeof(Pkg.RDEPEND), "%.*s", - (int)sizeof(Pkg.RDEPEND) - 1, p); - if (strcmp(buf, "PF") == 0) - snprintf(pkg->PF, sizeof(Pkg.PF), "%.*s", - (int)sizeof(Pkg.PF) - 1, p); - if (strcmp(buf, "CATEGORY") == 0) - snprintf(pkg->CATEGORY, sizeof(Pkg.CATEGORY), "%.*s", - (int)sizeof(Pkg.CATEGORY) - 1, p); - if (strcmp(buf, "REPO") == 0) - snprintf(pkg->REPO, sizeof(Pkg.REPO), "%.*s", - (int)sizeof(Pkg.REPO) - 1, p); - - if (strcmp(buf, "CPV") == 0) { - if ((atom = atom_explode(p)) != NULL) { - if (atom->PR_int) { - snprintf(buf, sizeof(buf), "%s-%s-r%i", - atom->PN, atom->PV, atom->PR_int); - } else { - snprintf(buf, sizeof(buf), "%s-%s", atom->PN, atom->PV); - } - snprintf(pkg->PF, sizeof(Pkg.PF), "%.*s", - (int)sizeof(Pkg.PF) - 1, buf); - snprintf(pkg->CATEGORY, sizeof(Pkg.CATEGORY), "%.*s", - (int)sizeof(Pkg.CATEGORY) - 1, atom->CATEGORY); - atom_implode(atom); - } - } - if (strcmp(buf, "SLOT") == 0) - snprintf(pkg->SLOT, sizeof(Pkg.SLOT), "%.*s", - (int)sizeof(Pkg.SLOT) - 1, p); - if (strcmp(buf, "USE") == 0) - snprintf(pkg->USE, sizeof(Pkg.USE), "%.*s", - (int)sizeof(Pkg.USE) - 1, p); - /* checksums. We must have 1 or the other unless --*/ - if (strcmp(buf, "MD5") == 0) - snprintf(pkg->MD5, sizeof(Pkg.MD5), "%.*s", - (int)sizeof(Pkg.MD5) - 1, p); - if (strcmp(buf, "SHA1") == 0) - snprintf(pkg->SHA1, sizeof(Pkg.SHA1), "%.*s", - (int)sizeof(Pkg.SHA1) - 1, p); - } - } - fclose(fp); - free(pkg); - return rpkg; -} - -static char * -find_binpkg(const char *name) +grab_binpkg_info(depend_atom *atom) { - FILE *fp; - char buf[BUFSIZ]; - char *p; - struct pkg_t Pkg; - char PF[sizeof(Pkg.PF)]; - char CATEGORY[sizeof(Pkg.CATEGORY)]; - - static char best_match[sizeof(Pkg.PF)+2+sizeof(Pkg.CATEGORY)]; - - best_match[0] = 0; - if (NULL == name) - return best_match; - - fp = open_binpkg_index(); - PF[0] = CATEGORY[0] = '\0'; - - while (fgets(buf, sizeof(buf), fp) != NULL) { - if (*buf == '\n') { - if (PF[0] && CATEGORY[0]) { - int ret; - snprintf(buf, sizeof(buf), "%s/%s", CATEGORY, PF); - if (strstr(buf, name) != NULL) { - depend_atom *atom; - - if (!best_match[0]) - snprintf(best_match, sizeof(best_match), "%.*s", - (int)sizeof(best_match) - 1, buf); - - atom = atom_explode(buf); - snprintf(buf, sizeof(buf), "%s/%s", - atom->CATEGORY, atom->PN); - ret = atom_compare_str(name, buf); - switch (ret) { - case OLDER: break; - case NEWER: - case EQUAL: - snprintf(buf, sizeof(buf), "%s/%s", CATEGORY, PF); - ret = atom_compare_str(buf, best_match); - if (ret == NEWER || ret == EQUAL) - snprintf(best_match, sizeof(best_match), "%.*s", - (int)sizeof(best_match) - 1, buf); - /* printf("[%s == %s] = %d; %s/%s\n", - * name, buf, ret, CATEGORY, PF); */ - default: - break; - } - atom_implode(atom); - } - } - continue; - } - - if ((p = strchr(buf, '\n')) != NULL) - *p = 0; - if ((p = strchr(buf, ':')) == NULL) - continue; - if (p[1] != ' ') - continue; - *p = 0; - p += 2; - - if (*buf) { - if (strcmp(buf, "CPV") == 0) { - depend_atom *atom; - if ((atom = atom_explode(p)) != NULL) { - if (atom->PR_int) { - snprintf(buf, sizeof(buf), "%s-%s-r%i", - atom->PN, atom->PV, atom->PR_int); - } else { - snprintf(buf, sizeof(buf), "%s-%s", atom->PN, atom->PV); - } - snprintf(PF, sizeof(PF), "%.*s", (int)sizeof(PF) - 1, buf); - snprintf(CATEGORY, sizeof(CATEGORY), "%.*s", - (int)sizeof(CATEGORY) - 1, atom->CATEGORY); - atom_implode(atom); - } - } - if (strcmp(buf, "PF") == 0) - snprintf(PF, sizeof(PF), "%.*s", (int)sizeof(PF) - 1, p); - if (strcmp(buf, "CATEGORY") == 0) - snprintf(CATEGORY, sizeof(CATEGORY), "%.*s", - (int)sizeof(CATEGORY) - 1, p); - } - } - fclose(fp); - return best_match; -} - -static int -parse_packages(set *todo) -{ - FILE *fp; - int linelen; - size_t buflen; - char *buf, *p; - struct pkg_t Pkg; - depend_atom *pkg_atom; - char repo[sizeof(Pkg.REPO)]; - depend_atom **todo_atoms = NULL; - size_t todo_cnt = 0; - size_t i; - - fp = open_binpkg_index(); - if (fp == NULL) - return EXIT_FAILURE; - - buf = NULL; - buflen = 0; /* make getline allocate */ - repo[0] = '\0'; - - /* First consume the header with the common data. */ - while ((linelen = getline(&buf, &buflen, fp)) >= 0) { - rmspace_len(buf, (size_t)linelen); - if (buf[0] == '\0') - break; - - if ((p = strchr(buf, ':')) == NULL) - continue; - if (p[1] != ' ') - continue; - *p = 0; - p += 2; - - switch (*buf) { - case 'R': - if (!strcmp(buf, "REPO")) - snprintf(repo, sizeof(repo), "%.*s", (int)sizeof(repo) - 1, p); - break; + tree_ctx *tree = _grab_binpkg_info_tree; + tree_match_ctx *tpkg; + struct pkg_t *pkg = NULL; + char path[BUFSIZ]; + FILE *d; + + /* reuse previously opened tree, so we really employ the cache + * from libq/tree */ + if (tree == NULL) { + snprintf(path, sizeof(path), "%s/portage/Packages", port_tmpdir); + /* we don't use ROOT on package tree here, operating on ROOT + * should be for package merges/unmerges, but be able to pull + * binpkgs from current system */ + if ((d = fopen(path, "r")) != NULL) { + fclose(d); + snprintf(path, sizeof(path), "%s/portage", port_tmpdir); + tree = tree_open_binpkg("/", path); + } else { + tree = tree_open_binpkg("/", pkgdir); } - } + _grab_binpkg_info_tree = tree; - pkg_atom = NULL; - memset(&Pkg, 0, sizeof(Pkg)); - strcpy(Pkg.SLOT, "0"); - - /* build list with exploded atoms for each access below */ - if (todo != NULL) { - char **todo_strs; - todo_cnt = list_set(todo, &todo_strs); - todo_atoms = xmalloc(sizeof(*todo_atoms) * todo_cnt); - for (i = 0; i < todo_cnt; i++) - todo_atoms[i] = atom_explode(todo_strs[i]); - free(todo_strs); + /* if opening the tree failed somehow, we can't return anything */ + if (tree == NULL) + return NULL; } - /* Then walk all the package entries. */ - while (getline(&buf, &buflen, fp) != -1) { - if (*buf == '\n') { - if (pkg_atom) { - if (search_pkgs && !todo) { - print_Pkg(verbose, pkg_atom, &Pkg); - } else { - for (i = 0; i < todo_cnt; i++) { - pkg_atom->REPO = todo_atoms[i]->REPO ? Pkg.REPO : NULL; - pkg_atom->SLOT = todo_atoms[i]->SLOT ? Pkg.SLOT : NULL; - if (atom_compare(pkg_atom, todo_atoms[i]) == EQUAL) { - if (search_pkgs) - print_Pkg(verbose, pkg_atom, &Pkg); - else - pkg_fetch(0, pkg_atom, &Pkg); - } - } - } - atom_implode(pkg_atom); - pkg_atom = NULL; - } - memset(&Pkg, 0, sizeof(Pkg)); - strcpy(Pkg.SLOT, "0"); - strcpy(Pkg.REPO, repo); - continue; - } - - if ((p = strchr(buf, '\n')) != NULL) - *p = 0; - if ((p = strchr(buf, ':')) == NULL) - continue; - if (p[1] != ' ') - continue; - *p = 0; - p += 2; - - switch (*buf) { - case 'U': - if (strcmp(buf, "USE") == 0) - snprintf(Pkg.USE, sizeof(Pkg.USE), "%.*s", - (int)sizeof(Pkg.USE) - 1, p); - break; - case 'P': - if (strcmp(buf, "PF") == 0) - snprintf(Pkg.PF, sizeof(Pkg.PF), "%.*s", - (int)sizeof(Pkg.PF) - 1, p); - break; - case 'S': - if (strcmp(buf, "SIZE") == 0) - Pkg.SIZE = atol(p); - if (strcmp(buf, "SLOT") == 0) - snprintf(Pkg.SLOT, sizeof(Pkg.SLOT), "%.*s", - (int)sizeof(Pkg.SLOT) - 1, p); - if (strcmp(buf, "SHA1") == 0) - snprintf(Pkg.SHA1, sizeof(Pkg.SHA1), "%.*s", - (int)sizeof(Pkg.SHA1) - 1, p); - break; - case 'M': - if (strcmp(buf, "MD5") == 0) - snprintf(Pkg.MD5, sizeof(Pkg.MD5), "%.*s", - (int)sizeof(Pkg.MD5) - 1, p); - break; - case 'R': - if (strcmp(buf, "REPO") == 0) - snprintf(Pkg.REPO, sizeof(Pkg.REPO), "%.*s", - (int)sizeof(Pkg.REPO) - 1, p); - if (strcmp(buf, "RDEPEND") == 0) - snprintf(Pkg.RDEPEND, sizeof(Pkg.RDEPEND), "%.*s", - (int)sizeof(Pkg.RDEPEND) - 1, p); - break; - case 'L': - if (strcmp(buf, "LICENSE") == 0) - snprintf(Pkg.LICENSE, sizeof(Pkg.LICENSE), "%.*s", - (int)sizeof(Pkg.LICENSE) - 1, p); - break; - case 'C': - if (strcmp(buf, "CATEGORY") == 0) - snprintf(Pkg.CATEGORY, sizeof(Pkg.CATEGORY), "%.*s", - (int)sizeof(Pkg.CATEGORY) - 1, p); - if (strcmp(buf, "CPV") == 0) { - if (pkg_atom != NULL) /* hypothetical Coverity case */ - atom_implode(pkg_atom); - if ((pkg_atom = atom_explode(p)) != NULL) { - if (pkg_atom->PR_int) - snprintf(Pkg.PF, sizeof(Pkg.PF), "%s-%s-r%i", - pkg_atom->PN, pkg_atom->PV, - pkg_atom->PR_int); - else - snprintf(Pkg.PF, sizeof(Pkg.PF), "%s-%s", - pkg_atom->PN, pkg_atom->PV); - snprintf(Pkg.CATEGORY, sizeof(Pkg.CATEGORY), - "%.*s", (int)sizeof(Pkg.CATEGORY) - 1, - pkg_atom->CATEGORY); - } - } - break; - case 'D': - if (strcmp(buf, "DESC") == 0) - snprintf(Pkg.DESC, sizeof(Pkg.DESC), "%.*s", - (int)sizeof(Pkg.DESC) - 1, p); - break; - default: - break; - } + tpkg = tree_match_atom(tree, atom, + TREE_MATCH_FIRST | TREE_MATCH_VIRTUAL | TREE_MATCH_METADATA); + if (tpkg != NULL) { + depend_atom *tatom = tpkg->atom; + tree_pkg_meta *meta = tpkg->meta; + pkg = xzalloc(sizeof(struct pkg_t)); + + snprintf(pkg->PF, sizeof(pkg->PF), "%s", tatom->PF); + snprintf(pkg->CATEGORY, sizeof(pkg->CATEGORY), "%s", tatom->CATEGORY); + if (meta->Q_DESCRIPTION != NULL) + snprintf(pkg->DESC, sizeof(pkg->DESC), "%s", meta->Q_DESCRIPTION); + if (meta->Q_LICENSE != NULL) + snprintf(pkg->LICENSE, sizeof(pkg->LICENSE), "%s", meta->Q_LICENSE); + if (meta->Q_RDEPEND != NULL) + snprintf(pkg->RDEPEND, sizeof(pkg->RDEPEND), "%s", meta->Q_RDEPEND); + if (meta->Q_MD5 != NULL) + snprintf(pkg->MD5, sizeof(pkg->MD5), "%s", meta->Q_MD5); + if (meta->Q_SHA1 != NULL) + snprintf(pkg->SHA1, sizeof(pkg->SHA1), "%s", meta->Q_SHA1); + if (meta->Q_USE != NULL) + snprintf(pkg->USE, sizeof(pkg->USE), "%s", meta->Q_USE); + if (meta->Q_repository != NULL) + snprintf(pkg->REPO, sizeof(pkg->REPO), "%s", meta->Q_repository); + if (meta->Q_SLOT != NULL) + snprintf(pkg->REPO, sizeof(pkg->REPO), "%s", meta->Q_SLOT); + if (meta->Q_SIZE != NULL) + pkg->SIZE = atoi(meta->Q_SIZE); + + tree_match_close(tpkg); } - free(buf); - fclose(fp); - if (pkg_atom) - atom_implode(pkg_atom); - - for (i = 0; i < todo_cnt; i++) - atom_implode(todo_atoms[i]); - free(todo_atoms); - - return EXIT_SUCCESS; + return pkg; } static set * @@ -2366,10 +1972,40 @@ qmerge_add_set(char *buf, set *q) static int qmerge_run(set *todo) { - if (uninstall) + if (uninstall) { return unmerge_packages(todo); - else - return parse_packages(todo); + } else { + if (todo == NULL && search_pkgs) { + /* disputable, this should be qlist -kIv or something */ + warn("please use qlist -kI"); + + return EXIT_SUCCESS; + } else { + char **todo_strs; + size_t todo_cnt = list_set(todo, &todo_strs); + size_t i; + depend_atom *atom; + struct pkg_t *pkg; + int ret = EXIT_FAILURE; + + for (i = 0; i < todo_cnt; i++) { + atom = atom_explode(todo_strs[i]); + pkg = grab_binpkg_info(atom); + if (pkg != NULL) { + if (search_pkgs) + print_Pkg(verbose, atom, pkg); + else + pkg_fetch(0, atom, pkg); + free(pkg); + ret = EXIT_SUCCESS; + } + atom_implode(atom); + } + free(todo_strs); + + return ret; + } + } } int qmerge_main(int argc, char **argv) @@ -2437,10 +2073,10 @@ int qmerge_main(int argc, char **argv) if (uninstall) { if (!prompt("OK to unmerge these packages")) - return 0; + return EXIT_FAILURE; } else { if (!prompt("OK to merge these packages")) - return 0; + return EXIT_FAILURE; } pretend = save_pretend;