diff options
author | Timo Teräs <timo.teras@iki.fi> | 2020-02-14 13:49:41 +0200 |
---|---|---|
committer | Timo Teräs <timo.teras@iki.fi> | 2020-02-14 16:49:55 +0200 |
commit | 60b87557e57ca4e23126bf8c25b1cb978e380dfd (patch) | |
tree | ca2469a61c3badb5f4054f387b7059c2bb6c5db7 /src/app_search.c | |
parent | 72be8139303d55463e470ee608a27eb4af950aff (diff) | |
download | apk-tools-60b87557e57ca4e23126bf8c25b1cb978e380dfd.tar.gz apk-tools-60b87557e57ca4e23126bf8c25b1cb978e380dfd.tar.bz2 apk-tools-60b87557e57ca4e23126bf8c25b1cb978e380dfd.tar.xz apk-tools-60b87557e57ca4e23126bf8c25b1cb978e380dfd.zip |
rename all applets sources to app_*.c
Diffstat (limited to 'src/app_search.c')
-rw-r--r-- | src/app_search.c | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/src/app_search.c b/src/app_search.c new file mode 100644 index 0000000..9bf64b2 --- /dev/null +++ b/src/app_search.c @@ -0,0 +1,217 @@ +/* app_search.c - Alpine Package Keeper (APK) + * + * Copyright (C) 2005-2009 Natanael Copa <n@tanael.org> + * Copyright (C) 2008-2011 Timo Teräs <timo.teras@iki.fi> + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. See http://www.gnu.org/ for details. + */ + +#include <fnmatch.h> +#include <stdio.h> +#include "apk_defines.h" +#include "apk_applet.h" +#include "apk_package.h" +#include "apk_database.h" + +struct search_ctx { + void (*print_result)(struct search_ctx *ctx, struct apk_package *pkg); + void (*print_package)(struct search_ctx *ctx, struct apk_package *pkg); + + int show_all : 1; + int search_exact : 1; + int search_description : 1; + int search_origin : 1; + + unsigned int matches; + struct apk_string_array *filter; +}; + +static int unique_match(struct apk_package *pkg) +{ + if (pkg->state_int) return 0; + pkg->state_int = 1; + return 1; +} + +static void print_package_name(struct search_ctx *ctx, struct apk_package *pkg) +{ + if (!unique_match(pkg)) return; + printf("%s", pkg->name->name); + if (apk_verbosity > 0) + printf("-" BLOB_FMT, BLOB_PRINTF(*pkg->version)); + if (apk_verbosity > 1) + printf(" - %s", pkg->description); + printf("\n"); +} + +static void print_origin_name(struct search_ctx *ctx, struct apk_package *pkg) +{ + if (!unique_match(pkg)) return; + if (pkg->origin != NULL) + printf(BLOB_FMT, BLOB_PRINTF(*pkg->origin)); + else + printf("%s", pkg->name->name); + if (apk_verbosity > 0) + printf("-" BLOB_FMT, BLOB_PRINTF(*pkg->version)); + printf("\n"); +} + +static void print_rdep_pkg(struct apk_package *pkg0, struct apk_dependency *dep0, struct apk_package *pkg, void *pctx) +{ + struct search_ctx *ctx = (struct search_ctx *) pctx; + ctx->print_package(ctx, pkg0); +} + +static void print_rdepends(struct search_ctx *ctx, struct apk_package *pkg) +{ + if (apk_verbosity > 0) { + ctx->matches = apk_foreach_genid() | APK_DEP_SATISFIES; + printf(PKG_VER_FMT " is required by:\n", PKG_VER_PRINTF(pkg)); + } + apk_pkg_foreach_reverse_dependency(pkg, ctx->matches, print_rdep_pkg, ctx); +} + +static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int optch, const char *optarg) +{ + struct search_ctx *ictx = (struct search_ctx *) ctx; + + switch (optch) { + case 'a': + ictx->show_all = 1; + break; + case 'd': + ictx->search_description = 1; + ictx->search_exact = 1; + ictx->show_all = 1; + break; + case 'e': + case 'x': + ictx->search_exact = 1; + break; + case 'o': + ictx->print_package = print_origin_name; + break; + case 'r': + ictx->print_result = print_rdepends; + break; + case 0x10000: + ictx->search_origin = 1; + ictx->search_exact = 1; + ictx->show_all = 1; + break; + default: + return -ENOTSUP; + } + return 0; +} + +static const struct apk_option options_applet[] = { + { 'a', "all" }, + { 'd', "description" }, + { 'x', "exact" }, + { 'e', NULL }, + { 'o', "origin" }, + { 'r', "rdepends" }, + { 0x10000, "has-origin" }, +}; + +static const struct apk_option_group optgroup_applet = { + .name = "Search", + .options = options_applet, + .num_options = ARRAY_SIZE(options_applet), + .parse = option_parse_applet, +}; + +static void print_result_pkg(struct search_ctx *ctx, struct apk_package *pkg) +{ + char **pmatch; + + if (ctx->search_description) { + foreach_array_item(pmatch, ctx->filter) { + if (strstr(pkg->description, *pmatch) != NULL || + strstr(pkg->name->name, *pmatch) != NULL) + goto match; + } + return; + } + if (ctx->search_origin) { + foreach_array_item(pmatch, ctx->filter) { + if (pkg->origin && apk_blob_compare(APK_BLOB_STR(*pmatch), *pkg->origin) == 0) + goto match; + } + return; + } +match: + ctx->print_result(ctx, pkg); +} + +static void print_result(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) +{ + struct search_ctx *ctx = pctx; + struct apk_provider *p; + struct apk_package *pkg = NULL; + + if (!name) return; + + if (ctx->show_all) { + foreach_array_item(p, name->providers) + print_result_pkg(ctx, p->pkg); + } else { + foreach_array_item(p, name->providers) { + if (pkg == NULL || + apk_version_compare_blob(*p->version, *pkg->version) == APK_VERSION_GREATER) + pkg = p->pkg; + } + if (pkg) + print_result_pkg(ctx, pkg); + } +} + +static int print_pkg(apk_hash_item item, void *pctx) +{ + print_result_pkg((struct search_ctx *) pctx, (struct apk_package *) item); + return 0; +} + +static int search_main(void *pctx, struct apk_database *db, struct apk_string_array *args) +{ + struct search_ctx *ctx = (struct search_ctx *) pctx; + char *tmp, **pmatch; + + ctx->filter = args; + ctx->matches = apk_foreach_genid() | APK_DEP_SATISFIES; + if (ctx->print_package == NULL) + ctx->print_package = print_package_name; + if (ctx->print_result == NULL) + ctx->print_result = ctx->print_package; + + if (ctx->search_description || ctx->search_origin) + return apk_hash_foreach(&db->available.packages, print_pkg, ctx); + + if (!ctx->search_exact) { + foreach_array_item(pmatch, ctx->filter) { + tmp = alloca(strlen(*pmatch) + 3); + sprintf(tmp, "*%s*", *pmatch); + *pmatch = tmp; + } + } + apk_name_foreach_matching( + db, args, APK_FOREACH_NULL_MATCHES_ALL | apk_foreach_genid(), + print_result, ctx); + return 0; +} + +static struct apk_applet apk_search = { + .name = "search", + .arguments = "PATTERN", + .open_flags = APK_OPENF_READ | APK_OPENF_NO_STATE, + .command_groups = APK_COMMAND_GROUP_QUERY, + .context_size = sizeof(struct search_ctx), + .optgroups = { &optgroup_global, &optgroup_applet }, + .main = search_main, +}; + +APK_DEFINE_APPLET(apk_search); |