ver.c 4.21 KB
Newer Older
1 2 3 4 5 6
/* ver.c - Alpine Package Keeper (APK)
 *
 * Copyright (C) 2005-2008 Natanael Copa <n@tanael.org>
 * Copyright (C) 2008 Timo Teräs <timo.teras@iki.fi>
 * All rights reserved.
 *
Timo Teräs's avatar
Timo Teräs committed
7
 * This program is free software; you can redistribute it and/or modify it
8 9 10 11 12 13 14 15 16
 * 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"
Natanael Copa's avatar
Natanael Copa committed
17
#include "apk_print.h"
18

19
struct ver_ctx {
20
	int (*action)(struct apk_database *db, int argc, char **argv);
Natanael Copa's avatar
Natanael Copa committed
21
	const char *limchars;
22 23
};

24 25 26 27 28 29 30 31 32 33 34
static int ver_indexes(struct apk_database *db, int argc, char **argv)
{
	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;

35 36 37 38
		printf("%.*s [%s]\n",
                       repo->description.len,
		       repo->description.ptr,
		       db->repos[i].url);
39 40 41 42 43 44
	}

	return 0;
}

static int ver_test(struct apk_database *db, int argc, char **argv)
45 46 47 48 49 50
{
	int r;

	if (argc != 2)
		return 1;

51
	r = apk_version_compare(argv[0], argv[1]);
Natanael Copa's avatar
Natanael Copa committed
52
	printf("%s\n", apk_version_op_string(r));
53 54 55
	return 0;
}

56
static int ver_validate(struct apk_database *db, int argc, char **argv)
57 58 59 60 61 62 63 64 65 66 67
{
	int i, r = 0;
	for (i = 0; i < argc; i++) {
		if (!apk_version_validate(APK_BLOB_STR(argv[i]))) {
			if (apk_verbosity > 0)
				printf("%s\n", argv[i]);
			r++;
		}
	}
	return r;
}
Timo Teräs's avatar
Timo Teräs committed
68

69 70
static int ver_parse(void *ctx, struct apk_db_options *dbopts,
		     int opt, int optindex, const char *optarg)
71 72 73
{
	struct ver_ctx *ictx = (struct ver_ctx *) ctx;
	switch (opt) {
74 75 76
	case 'I':
		ictx->action = ver_indexes;
		break;
77 78 79
	case 't':
		ictx->action = ver_test;
		break;
80 81 82
	case 'c':
		ictx->action = ver_validate;
		break;
Natanael Copa's avatar
Natanael Copa committed
83 84 85
	case 'l':
		ictx->limchars = optarg;
		break;
86 87 88 89 90 91
	default:
		return -1;
	}
	return 0;
}

Natanael Copa's avatar
Natanael Copa committed
92
static void ver_print_package_status(struct apk_package *pkg, const char *limit)
93 94
{
	struct apk_name *name;
Natanael Copa's avatar
Natanael Copa committed
95
	struct apk_package *tmp;
Timo Teräs's avatar
Timo Teräs committed
96
	char pkgname[256];
Natanael Copa's avatar
Natanael Copa committed
97 98
	const char *opstr, *latest = "";
	int i, r = -1;
99 100 101 102

	name = pkg->name;
	for (i = 0; i < name->pkgs->num; i++) {
		tmp = name->pkgs->item[i];
Natanael Copa's avatar
Natanael Copa committed
103
		if (tmp->name != name || tmp->repos == 0)
104
			continue;
Natanael Copa's avatar
Natanael Copa committed
105
		r = apk_version_compare(tmp->version, latest);
106
		if (r == APK_VERSION_GREATER)
Natanael Copa's avatar
Natanael Copa committed
107
			latest = tmp->version;
108
	}
Natanael Copa's avatar
Natanael Copa committed
109 110 111 112
	r = apk_version_compare(pkg->version, latest);
	opstr = apk_version_op_string(r);
	if ((limit != NULL) && (strchr(limit, *opstr) == NULL))
		return;
Timo Teräs's avatar
Timo Teräs committed
113
	snprintf(pkgname, sizeof(pkgname), "%s-%s", name->name, pkg->version);
Natanael Copa's avatar
Natanael Copa committed
114
	printf("%-40s%s %s\n", pkgname, opstr, latest);
115 116
}

117
static int ver_main(void *ctx, struct apk_database *db, int argc, char **argv)
118
{
119
	struct ver_ctx *ictx = (struct ver_ctx *) ctx;
120
	struct apk_installed_package *ipkg;
121
	struct apk_name *name;
122 123
	int i, j, ret = 0;

124

125
	if (ictx->action != NULL)
126
		return ictx->action(db, argc, argv);
127

Natanael Copa's avatar
Natanael Copa committed
128 129 130
	if (apk_verbosity > 0)
		printf("%-42sAvailable:\n", "Installed:");

131
	if (argc == 0) {
132
		list_for_each_entry(ipkg, &db->installed.packages,
133
				    installed_pkgs_list) {
134
			ver_print_package_status(ipkg->pkg, ictx->limchars);
135
		}
136
		goto ver_exit;
137 138
	}

139
	for (i = 0; i < argc; i++) {
140
		name = apk_db_query_name(db, APK_BLOB_STR(argv[i]));
141 142 143 144 145 146 147
		if (name == NULL) {
			apk_error("Not found: %s", name);
			ret = 1;
			goto ver_exit;
		}
		for (j = 0; j < name->pkgs->num; j++) {
			struct apk_package *pkg = name->pkgs->item[j];
148
			if (pkg->ipkg != NULL)
Natanael Copa's avatar
Natanael Copa committed
149
				ver_print_package_status(pkg, ictx->limchars);
150 151 152 153 154
		}
	}

ver_exit:
	return ret;
155 156
}

Timo Teräs's avatar
Timo Teräs committed
157
static struct apk_option ver_options[] = {
158
	{ 'I', "indexes",	"Print description and versions of indexes" },
Timo Teräs's avatar
Timo Teräs committed
159 160
	{ 't', "test",		"Compare two given versions" },
	{ 'c', "check", 	"Check if the given version string is valid" },
Natanael Copa's avatar
Natanael Copa committed
161 162
	{ 'l', "limit",		"Limit output to packages whos status matches LIMCHAR",
	  required_argument, "LIMCHAR" },
163 164
};

165 166
static struct apk_applet apk_ver = {
	.name = "version",
Timo Teräs's avatar
Timo Teräs committed
167 168
	.help = "Compare package versions (in installed database vs. available)"
		" or do tests on version strings given on command line.",
169
	.open_flags = APK_OPENF_READ,
170 171 172 173
	.context_size = sizeof(struct ver_ctx),
	.num_options = ARRAY_SIZE(ver_options),
	.options = ver_options,
	.parse = ver_parse,
174 175 176 177 178
	.main = ver_main,
};

APK_DEFINE_APPLET(apk_ver);