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 B518B138334 for ; Thu, 25 Apr 2019 09:22:21 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 44839E09D7; Thu, 25 Apr 2019 09:22:17 +0000 (UTC) Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) (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 17F5FE09D7 for ; Thu, 25 Apr 2019 09:22:16 +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 95ED1342653 for ; Thu, 25 Apr 2019 09:22:15 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id 7F60C5D2 for ; Thu, 25 Apr 2019 09:22:12 +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: <1556183001.33598fc089e54253261d5a0ec176bde9d300a94f.grobian@gentoo> Subject: [gentoo-commits] proj/portage-utils:master commit in: / X-VCS-Repository: proj/portage-utils X-VCS-Files: qsearch.c X-VCS-Directories: / X-VCS-Committer: grobian X-VCS-Committer-Name: Fabian Groffen X-VCS-Revision: 33598fc089e54253261d5a0ec176bde9d300a94f X-VCS-Branch: master Date: Thu, 25 Apr 2019 09:22:12 +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: 7479791c-ad9f-461e-bdc0-908b629d7883 X-Archives-Hash: a2bb1d56baf24e193d6d814f0ce4045a commit: 33598fc089e54253261d5a0ec176bde9d300a94f Author: Fabian Groffen gentoo org> AuthorDate: Thu Apr 25 09:03:21 2019 +0000 Commit: Fabian Groffen gentoo org> CommitDate: Thu Apr 25 09:03:21 2019 +0000 URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=33598fc0 qsearch: rewrite to use libq/cache Signed-off-by: Fabian Groffen gentoo.org> qsearch.c | 281 ++++++++++++++++++++++---------------------------------------- 1 file changed, 100 insertions(+), 181 deletions(-) diff --git a/qsearch.c b/qsearch.c index f543b8a..b6d7410 100644 --- a/qsearch.c +++ b/qsearch.c @@ -25,232 +25,151 @@ #include "xarray.h" #include "xregex.h" -#define QSEARCH_FLAGS "acesSNH" COMMON_FLAGS +#define QSEARCH_FLAGS "asSNHR" COMMON_FLAGS static struct option const qsearch_long_opts[] = { {"all", no_argument, NULL, 'a'}, - {"cache", no_argument, NULL, 'c'}, - {"ebuilds", no_argument, NULL, 'e'}, {"search", no_argument, NULL, 's'}, {"desc", a_argument, NULL, 'S'}, {"name-only", no_argument, NULL, 'N'}, {"homepage", no_argument, NULL, 'H'}, + {"repo", no_argument, NULL, 'R'}, COMMON_LONG_OPTS }; static const char * const qsearch_opts_help[] = { "List the descriptions of every package in the cache", - "Use the portage cache", - "Use the portage ebuild tree (default)", "Regex search package basenames", - "Regex search package descriptions", + "Regex search package descriptions (or homepage when using -H)", "Only show package name", - "Show homepage info", + "Show homepage info instead of description", + "Show repository the ebuild originates from", COMMON_OPTS_HELP }; #define qsearch_usage(ret) usage(ret, QSEARCH_FLAGS, qsearch_long_opts, qsearch_opts_help, NULL, lookup_applet_idx("qsearch")) -#define LAST_BUF_SIZE 256 +struct qsearch_state { + bool show_homepage:1; + bool show_name:1; + bool show_desc:1; + bool show_repo:1; + bool search_desc:1; + bool search_name:1; + regex_t search_expr; +}; -/* Search an ebuild's details via the metadata cache. */ -static void -qsearch_ebuild_metadata( - int overlay_fd, - const char *ebuild, - const char *search_me, - char *last, - bool search_desc, - bool search_all, - bool search_name, - bool show_name_only, - bool show_homepage) +static int +qsearch_cb(cache_pkg_ctx *pkg_ctx, void *priv) { - (void)overlay_fd; - (void)search_name; - - portage_cache *pcache = cache_read_file(portcachedir_type, ebuild); - - if (pcache == NULL) { - warnf("missing cache, please (re)generate"); - return; + static depend_atom *last_atom; + + struct qsearch_state *state = (struct qsearch_state *)priv; + depend_atom *atom; + char buf[_Q_PATH_MAX]; + cache_pkg_meta *meta; + char *desc; + char *repo; + bool match; + + snprintf(buf, sizeof(buf), "%s/%s", pkg_ctx->cat_ctx->name, pkg_ctx->name); + atom = atom_explode(buf); + if (atom == NULL) + return 0; + + /* skip duplicate packages (we never report version) */ + if (last_atom != NULL && strcmp(last_atom->PN, atom->PN) == 0) { + atom_implode(atom); + return 0; } - if (strcmp(pcache->atom->PN, last) != 0) { - strncpy(last, pcache->atom->PN, LAST_BUF_SIZE); - if (search_all || rematch(search_me, - (search_desc ? pcache->DESCRIPTION : ebuild), - REG_EXTENDED | REG_ICASE) == 0) - printf("%s%s/%s%s%s%s%s\n", BOLD, pcache->atom->CATEGORY, BLUE, - pcache->atom->PN, NORM, - (show_name_only ? "" : " "), - (show_name_only ? "" : - (show_homepage ? pcache->HOMEPAGE : pcache->DESCRIPTION))); - } - cache_free(pcache); -} - -/* Search an ebuild's details via the ebuild cache. */ -static void -qsearch_ebuild_ebuild( - int overlay_fd, - const char *ebuild, - const char *search_me, - char *last, - bool search_desc, - bool search_all, - bool search_name, - bool show_name_only, - bool show_homepage) -{ - const char * const search_vars[] = { "DESCRIPTION=", "HOMEPAGE=" }; - const char *search_var = search_vars[show_homepage ? 1 : 0]; - size_t search_len = strlen(search_var); - char *p, *q, *str; - char *buf = NULL; - int linelen; - size_t buflen; - bool show_it = false; - FILE *ebuildfp; - int fd; - - str = xstrdup(ebuild); - p = dirname(str); - - (void)search_desc; - (void)show_homepage; - - if (strcmp(p, last) == 0) - goto no_cache_ebuild_match; - - strncpy(last, p, LAST_BUF_SIZE); - if (search_name) { - if (rematch(search_me, basename(last), REG_EXTENDED | REG_ICASE) != 0) { - goto no_cache_ebuild_match; - } else { - q = NULL; - show_it = true; + match = false; + if (state->search_name && + regexec(&state->search_expr, atom->PN, 0, NULL, 0) == 0) + match = true; + + desc = NULL; + meta = NULL; + if ((match && (state->show_homepage || state->show_desc)) || + (!match && state->search_desc)) + { + meta = cache_pkg_read(pkg_ctx); + if (meta != NULL) { + if (state->show_homepage) + desc = meta->HOMEPAGE; + else if (state->show_desc) + desc = meta->DESCRIPTION; } } - fd = openat(overlay_fd, ebuild, O_RDONLY|O_CLOEXEC); - if (fd != -1) { - ebuildfp = fdopen(fd, "r"); - if (ebuildfp == NULL) { - close(fd); - goto no_cache_ebuild_match; - } - } else { - warnf("missing cache, please (re)generate"); - goto no_cache_ebuild_match; + if (!match && state->search_desc && desc != NULL && + regexec(&state->search_expr, desc, 0, NULL, 0) == 0) + match = true; + + repo = NULL; + if (match) { + if (state->show_repo) + repo = pkg_ctx->repo; + printf("%s%s/%s%s%s%s%s%s%s%s\n", BOLD, atom->CATEGORY, + BLUE, atom->PN, + GREEN, (repo ? "::" : ""), (repo ? repo : ""), NORM, + (state->show_name ? "" : " "), + (state->show_name ? "" : desc ? desc : "")); } - while ((linelen = getline(&buf, &buflen, ebuildfp)) >= 0) { - if ((size_t)linelen <= search_len) - continue; - if (strncmp(buf, search_var, search_len) != 0) - continue; - if ((q = strrchr(buf, '"')) != NULL) - *q = 0; - if (strlen(buf) <= search_len) - break; - q = buf + search_len + 1; - if (!search_all && !search_name && - rematch(search_me, q, REG_EXTENDED | REG_ICASE) != 0) - break; - show_it = true; - break; - } + if (meta != NULL) + cache_close_meta(meta); - if (show_it) { - const char *pkg = basename(p); - printf("%s%s/%s%s%s%s%s\n", - BOLD, dirname(p), BLUE, pkg, NORM, - (show_name_only ? "" : " "), - (show_name_only ? "" : q ? : "")); - } + if (last_atom != NULL) + atom_implode(last_atom); + last_atom = atom; - free(buf); - fclose(ebuildfp); - no_cache_ebuild_match: - free(str); + return EXIT_SUCCESS; } int qsearch_main(int argc, char **argv) { - char last[LAST_BUF_SIZE]; - char *search_me = NULL; - bool show_homepage = false, show_name_only = false; - bool search_desc = false, search_all = false, search_name = true; - int search_cache = CACHE_EBUILD; + int ret = EXIT_SUCCESS; + const char *search_me = NULL; int i; - void (*search_func)(int, const char *, const char *, char *last, bool, bool, bool, bool, bool); + const char *overlay; + size_t n; + struct qsearch_state state = { + .show_homepage = false, + .show_name = false, + .show_desc = false, + .show_repo = false, + .search_desc = false, + .search_name = false, + }; while ((i = GETOPT_LONG(QSEARCH, qsearch, "")) != -1) { switch (i) { COMMON_GETOPTS_CASES(qsearch) - case 'a': search_all = true; break; - case 'c': search_cache = CACHE_METADATA; break; - case 'e': search_cache = CACHE_EBUILD; break; - case 's': search_desc = false; search_name = true; break; - case 'S': search_desc = true; search_name = false; break; - case 'N': show_name_only = true; break; - case 'H': show_homepage = true; break; + case 'a': search_me = ".*"; break; + case 's': state.search_name = true; break; + case 'S': state.search_desc = true; break; + case 'N': state.show_name = true; break; + case 'H': state.show_homepage = true; break; + case 'R': state.show_repo = true; break; } } - switch (search_cache) { - case CACHE_METADATA: - search_func = qsearch_ebuild_metadata; - break; - case CACHE_EBUILD: - search_func = qsearch_ebuild_ebuild; - break; - default: - err("unknown cache %i", search_cache); - } + /* set defaults */ + if (!state.show_homepage) + state.show_desc = true; + if (!state.search_name && !state.search_desc) + state.search_name = true; - if (search_all) { - search_desc = true; - search_name = false; - } else { + /* compile expression */ + if (search_me == NULL) { if (argc == optind) qsearch_usage(EXIT_FAILURE); search_me = argv[optind]; } - last[0] = 0; + xregcomp(&state.search_expr, search_me, REG_EXTENDED | REG_ICASE); - int ret = 0; - size_t n; - const char *overlay; - array_for_each(overlays, n, overlay) { - FILE *fp = fopen(initialize_flat(overlay, search_cache, false), "r"); - if (!fp) { - warnp("opening cache for %s failed", overlay); - ret = 1; - continue; - } - - int overlay_fd = open(overlay, O_RDONLY|O_CLOEXEC|O_PATH); - if (overlay_fd < 0) { - fclose(fp); - warnp("open failed: %s", overlay); - ret = 1; - continue; - } - - int linelen; - size_t buflen; - char *buf = NULL; - while ((linelen = getline(&buf, &buflen, fp)) >= 0) { - rmspace_len(buf, (size_t)linelen); - if (!buf[0]) - continue; - - search_func(overlay_fd, buf, search_me, last, search_desc, - search_all, search_name, show_name_only, show_homepage); - } - free(buf); - close(overlay_fd); - fclose(fp); - } + /* use sorted order here so the duplicate reduction works reliably */ + array_for_each(overlays, n, overlay) + ret |= cache_foreach_pkg_sorted(portroot, overlay, qsearch_cb, + &state, NULL, NULL); return ret; }