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_version.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_version.c')
-rw-r--r-- | src/app_version.c | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/src/app_version.c b/src/app_version.c new file mode 100644 index 0000000..a29d899 --- /dev/null +++ b/src/app_version.c @@ -0,0 +1,207 @@ +/* app_version.c - Alpine Package Keeper (APK) + * + * Copyright (C) 2005-2008 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 <stdio.h> +#include "apk_defines.h" +#include "apk_applet.h" +#include "apk_database.h" +#include "apk_version.h" +#include "apk_print.h" + +struct ver_ctx { + int (*action)(struct apk_database *db, struct apk_string_array *args); + const char *limchars; + int all_tags : 1; +}; + +static int ver_indexes(struct apk_database *db, struct apk_string_array *args) +{ + struct apk_repository *repo; + int i; + + for (i = 0; i < db->num_repos; i++) { + repo = &db->repos[i]; + + if (APK_BLOB_IS_NULL(repo->description)) + continue; + + printf(BLOB_FMT " [%s]\n", + BLOB_PRINTF(repo->description), + db->repos[i].url); + } + + return 0; +} + +static int ver_test(struct apk_database *db, struct apk_string_array *args) +{ + int r; + + if (args->num != 2) + return 1; + + r = apk_version_compare(args->item[0], args->item[1]); + printf("%s\n", apk_version_op_string(r)); + return 0; +} + +static int ver_validate(struct apk_database *db, struct apk_string_array *args) +{ + char **parg; + int errors = 0; + + foreach_array_item(parg, args) { + if (!apk_version_validate(APK_BLOB_STR(*parg))) { + if (apk_verbosity > 0) + printf("%s\n", *parg); + errors++; + } + } + return errors; +} + +static int option_parse_applet(void *ctx, struct apk_db_options *dbopts, int optch, const char *optarg) +{ + struct ver_ctx *ictx = (struct ver_ctx *) ctx; + switch (optch) { + case 'I': + ictx->action = ver_indexes; + break; + case 't': + ictx->action = ver_test; + dbopts->open_flags |= APK_OPENF_NO_STATE | APK_OPENF_NO_REPOS; + break; + case 'c': + ictx->action = ver_validate; + dbopts->open_flags |= APK_OPENF_NO_STATE | APK_OPENF_NO_REPOS; + break; + case 'l': + ictx->limchars = optarg; + break; + case 'a': + ictx->all_tags = 1; + break; + default: + return -ENOTSUP; + } + return 0; +} + +static const struct apk_option options_applet[] = { + { 'I', "indexes" }, + { 't', "test" }, + { 'c', "check" }, + { 'a', "all" }, + { 'l', "limit", required_argument, "LIMCHARs" }, +}; + +static const struct apk_option_group optgroup_applet = { + .name = "Version", + .options = options_applet, + .num_options = ARRAY_SIZE(options_applet), + .parse = option_parse_applet, +}; + +static void ver_print_package_status(struct apk_database *db, const char *match, struct apk_name *name, void *pctx) +{ + struct ver_ctx *ctx = (struct ver_ctx *) pctx; + struct apk_package *pkg; + struct apk_provider *p0; + char pkgname[41]; + const char *opstr; + apk_blob_t *latest = apk_blob_atomize(APK_BLOB_STR("")); + unsigned int latest_repos = 0; + int i, r = -1; + unsigned short tag, allowed_repos; + + if (!name) return; + + pkg = apk_pkg_get_installed(name); + if (!pkg) return; + + tag = pkg->ipkg->repository_tag; + allowed_repos = db->repo_tags[tag].allowed_repos; + + foreach_array_item(p0, name->providers) { + struct apk_package *pkg0 = p0->pkg; + if (pkg0->name != name || pkg0->repos == 0) + continue; + if (!(ctx->all_tags || (pkg0->repos & allowed_repos))) + continue; + r = apk_version_compare_blob(*pkg0->version, *latest); + switch (r) { + case APK_VERSION_GREATER: + latest = pkg0->version; + latest_repos = pkg0->repos; + break; + case APK_VERSION_EQUAL: + latest_repos |= pkg0->repos; + break; + } + } + r = latest->len ? apk_version_compare_blob(*pkg->version, *latest) + : APK_VERSION_UNKNOWN; + opstr = apk_version_op_string(r); + if ((ctx->limchars != NULL) && (strchr(ctx->limchars, *opstr) == NULL)) + return; + if (apk_verbosity <= 0) { + printf("%s\n", pkg->name->name); + return; + } + + tag = APK_DEFAULT_REPOSITORY_TAG; + for (i = 1; i < db->num_repo_tags; i++) { + if (latest_repos & db->repo_tags[i].allowed_repos) { + tag = i; + break; + } + } + + snprintf(pkgname, sizeof(pkgname), PKG_VER_FMT, PKG_VER_PRINTF(pkg)); + printf("%-40s%s " BLOB_FMT " " BLOB_FMT "\n", + pkgname, opstr, + BLOB_PRINTF(*latest), + BLOB_PRINTF(db->repo_tags[tag].tag)); +} + +static int ver_main(void *pctx, struct apk_database *db, struct apk_string_array *args) +{ + struct ver_ctx *ctx = (struct ver_ctx *) pctx; + + if (ctx->limchars) { + if (strlen(ctx->limchars) == 0) + ctx->limchars = NULL; + } else if (args->num == 0 && apk_verbosity == 1) { + ctx->limchars = "<"; + } + + if (ctx->action != NULL) + return ctx->action(db, args); + + if (apk_verbosity > 0) + printf("%-42sAvailable:\n", "Installed:"); + + apk_name_foreach_matching( + db, args, APK_FOREACH_NULL_MATCHES_ALL | apk_foreach_genid(), + ver_print_package_status, ctx); + + return 0; +} + +static struct apk_applet apk_ver = { + .name = "version", + .open_flags = APK_OPENF_READ, + .context_size = sizeof(struct ver_ctx), + .optgroups = { &optgroup_global, &optgroup_applet }, + .main = ver_main, +}; + +APK_DEFINE_APPLET(apk_ver); |