apk-tools/src/app_version.c

208 lines
4.9 KiB
C
Raw Normal View History

2020-02-14 11:49:41 +00:00
/* app_version.c - Alpine Package Keeper (APK)
*
* Copyright (C) 2005-2008 Natanael Copa <n@tanael.org>
2011-09-13 08:53:01 +00:00
* 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"
2010-03-05 08:13:25 +00:00
#include "apk_print.h"
struct ver_ctx {
int (*action)(struct apk_database *db, struct apk_string_array *args);
const char *limchars;
2012-02-15 12:28:29 +00:00
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;
2012-02-15 12:28:29 +00:00
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" },
add script to autogenerate help from man pages This creates main help like: -- usage: apk [<OPTIONS>...] COMMAND [<ARGUMENTS>...] Package installation and removal: add Add packages to WORLD and commit changes del Remove packages from WORLD and commit changes System maintenance: fix Check WORLD against the system and ensure consistency update Update repository indexes upgrade Install upgrades available from repositories cache Commands related to the management of an offline package cache Querying package information: info Give detailed information about packages or repositories list List packages matching a pattern or other criteria dot Generate graphviz graphs policy Show repository policy for packages Repository maintenance: index Create repository index file from packages fetch Download packages from global repositories to a local directory manifest Show checksums of package contents verify Verify package integrity and signature Miscellaneous: audit Audit directories for changes stats Show statistics about repositories and installations version Compare package versions or perform tests on version strings This apk has coffee making abilities. -- And applet specific help like: -- usage: apk add [<OPTIONS>...] PACKAGES... Description: apk add adds the requested packages to WORLD and installs (or upgrades) them if not already present, ensuring all dependencies are met. Options: --initdb Initialize a new package database -l, --latest Disables normal heuristics for choosing which repository to install a -u, --upgrade When adding packages which are already installed, upgrade them rather -t, --virtual NAME Instead of adding the specified packages to WORLD, create a new --no-chown Do not change file owner or group --
2020-04-24 08:49:14 +00:00
{ 'l', "limit", required_argument },
};
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(""));
2012-02-15 12:28:29 +00:00
unsigned int latest_repos = 0;
int i, r = -1;
2012-02-15 12:28:29 +00:00
unsigned short tag, allowed_repos;
if (!name) return;
pkg = apk_pkg_get_installed(name);
if (!pkg) return;
tag = pkg->ipkg->repository_tag;
2012-02-15 12:28:29 +00:00
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)))
2012-02-15 12:28:29 +00:00
continue;
r = apk_version_compare_blob(*pkg0->version, *latest);
2012-02-15 12:28:29 +00:00
switch (r) {
case APK_VERSION_GREATER:
latest = pkg0->version;
latest_repos = pkg0->repos;
2012-02-15 12:28:29 +00:00
break;
case APK_VERSION_EQUAL:
latest_repos |= pkg0->repos;
2012-02-15 12:28:29 +00:00
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;
2012-02-15 12:28:29 +00:00
}
}
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);