diff options
Diffstat (limited to 'src/util')
| -rw-r--r-- | src/util/.gitignore | 15 | ||||
| -rw-r--r-- | src/util/Makefile.am | 5 | ||||
| -rw-r--r-- | src/util/cleanupdelta.c | 8 | ||||
| -rw-r--r-- | src/util/pactree.c | 372 | ||||
| -rw-r--r-- | src/util/testdb.c | 19 | ||||
| -rw-r--r-- | src/util/testpkg.c | 6 | ||||
| -rw-r--r-- | src/util/vercmp.c | 23 | 
7 files changed, 404 insertions, 44 deletions
| diff --git a/src/util/.gitignore b/src/util/.gitignore index 9c855dff..2880ce2a 100644 --- a/src/util/.gitignore +++ b/src/util/.gitignore @@ -1,11 +1,12 @@  .deps  .libs -vercmp -vercmp.exe -testpkg -testpkg.exe -testdb -testdb.exe  cleanupdelta  cleanupdelta.exe - +pactree +pactree.exe +testdb +testdb.exe +testpkg +testpkg.exe +vercmp +vercmp.exe diff --git a/src/util/Makefile.am b/src/util/Makefile.am index 7dce9dcc..30a2ee35 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -3,7 +3,7 @@ conffile  = ${sysconfdir}/pacman.conf  dbpath    = ${localstatedir}/lib/pacman/  cachedir  = ${localstatedir}/cache/pacman/pkg/ -bin_PROGRAMS = vercmp testpkg testdb cleanupdelta +bin_PROGRAMS = vercmp testpkg testdb cleanupdelta pactree  DEFS = -DLOCALEDIR=\"@localedir@\" \         -DCONFFILE=\"$(conffile)\" \ @@ -27,5 +27,8 @@ testdb_LDADD = $(top_builddir)/lib/libalpm/.libs/libalpm.la  cleanupdelta_SOURCES = cleanupdelta.c  cleanupdelta_LDADD = $(top_builddir)/lib/libalpm/.libs/libalpm.la +pactree_SOURCES = pactree.c +pactree_LDADD = $(top_builddir)/lib/libalpm/.libs/libalpm.la +  # vim:set ts=2 sw=2 noet: diff --git a/src/util/cleanupdelta.c b/src/util/cleanupdelta.c index ffcfaba5..c1ef18c4 100644 --- a/src/util/cleanupdelta.c +++ b/src/util/cleanupdelta.c @@ -49,7 +49,7 @@ void output_cb(pmloglevel_t level, char *fmt, va_list args)  } -void checkpkgs(alpm_list_t *pkglist) +static void checkpkgs(alpm_list_t *pkglist)  {  	alpm_list_t *i, *j;  	for(i = pkglist; i; i = alpm_list_next(i)) { @@ -63,7 +63,7 @@ void checkpkgs(alpm_list_t *pkglist)  	}  } -void checkdbs(char *dbpath, alpm_list_t *dbnames) { +static void checkdbs(char *dbpath, alpm_list_t *dbnames) {  	char syncdbpath[PATH_MAX];  	pmdb_t *db = NULL;  	alpm_list_t *i; @@ -82,14 +82,14 @@ void checkdbs(char *dbpath, alpm_list_t *dbnames) {  } -void usage() { +static void usage(void) {  	fprintf(stderr, "usage:\n");  	fprintf(stderr,  			"\t%s [-b <pacman db>] core extra ... : check the listed sync databases\n", BASENAME);  	exit(1);  } -int main(int argc, char **argv) +int main(int argc, char *argv[])  {  	char *dbpath = DBPATH;  	int a = 1; diff --git a/src/util/pactree.c b/src/util/pactree.c new file mode 100644 index 00000000..5e869672 --- /dev/null +++ b/src/util/pactree.c @@ -0,0 +1,372 @@ +/* + *  pactree.c - a simple dependency tree viewer + * + *  Copyright (c) 2010 Pacman Development Team <pacman-dev@archlinux.org> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program.  If not, see <http://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <getopt.h> +#include <stdio.h> +#include <string.h> + +#include <alpm.h> +#include <alpm_list.h> + +/* output */ +char *provides     = " provides"; +char *unresolvable = " [unresolvable]"; +char *branch_tip1  = "|--"; +char *branch_tip2  = "+--"; +int   indent_size  = 3; + +/* color */ +char *branch1_color = "\033[0;33m"; /* yellow */ +char *branch2_color = "\033[0;37m"; /* white */ +char *leaf1_color   = "\033[1;32m"; /* bold green */ +char *leaf2_color   = "\033[0;32m"; /* green */ +char *color_off     = "\033[0m"; + +/* globals */ +pmdb_t *db_local; +alpm_list_t *walked = NULL; +alpm_list_t *provisions = NULL; + +/* options */ +int color = 0; +int graphviz = 0; +int linear = 0; +int max_depth = -1; +int reverse = 0; +int unique = 0; +char *dbpath = NULL; + +static int alpm_local_init() +{ +	int ret; + +	ret = alpm_initialize(); +	if(ret != 0) { +		return(ret); +	} + +	ret = alpm_option_set_root(ROOTDIR); +	if(ret != 0) { +		return(ret); +	} + +	if(dbpath) { +		ret = alpm_option_set_dbpath(dbpath); +	} else { +		ret = alpm_option_set_dbpath(DBPATH); +	} +	if(ret != 0) { +		return(ret); +	} + +	db_local = alpm_db_register_local(); +	if(!db_local) { +		return(1); +	} + +	return(0); +} + +static int parse_options(int argc, char *argv[]) +{ +	int opt, option_index = 0; +	char *endptr = NULL; + +	static struct option opts[] = { +		{"dbpath",  required_argument,    0, 'b'}, +		{"color",   no_argument,          0, 'c'}, +		{"depth",   required_argument,    0, 'd'}, +		{"graph",   no_argument,          0, 'g'}, +		{"help",    no_argument,          0, 'h'}, +		{"linear",  no_argument,          0, 'l'}, +		{"reverse", no_argument,          0, 'r'}, +		{"unique",  no_argument,          0, 'u'}, +		{0, 0, 0, 0} +	}; + +	while((opt = getopt_long(argc, argv, "b:cd:ghlru", opts, &option_index))) { +		if(opt < 0) { +			break; +		} + +		switch(opt) { +			case 'b': +				dbpath = strdup(optarg); +				break; +			case 'c': +				color = 1; +				break; +			case 'd': +				/* validate depth */ +				max_depth = strtol(optarg, &endptr, 10); +				if(*endptr != '\0') { +					fprintf(stderr, "error: invalid depth -- %s\n", optarg); +					return 1; +				} +				break; +			case 'g': +				graphviz = 1; +				break; +			case 'l': +				linear = 1; +				break; +			case 'r': +				reverse = 1; +				break; +			case 'u': +				unique = linear = 1; +				break; +			case 'h': +			case '?': +			default: +				return(1); +		} +	} + +	if(!argv[optind]) { +		return(1); +	} + +	if(!color) { +		branch1_color = ""; +		branch2_color = ""; +		leaf1_color   = ""; +		leaf2_color   = ""; +		color_off     = ""; +	} +	if(linear) { +		provides     = ""; +		branch_tip1  = ""; +		branch_tip2  = ""; +		indent_size  = 0; +	} + +	return(0); +} + +static void usage(void) +{ +	fprintf(stderr, "pactree v" PACKAGE_VERSION "\n" +			"Usage: pactree [options] PACKAGE\n\n" +			"  -b, --dbpath <path>  set an alternate database location\n" +			"  -c, --color          colorize output\n" +			"  -d, --depth <#>      limit the depth of recursion\n" +			"  -g, --graph          generate output for graphviz's dot\n" +			"  -l, --linear         enable linear output\n" +			"  -r, --reverse        show reverse dependencies\n" +			"  -u, --unique         show dependencies with no duplicates (implies -l)\n\n" +			"  -h, --help           display this help message\n"); +} + +static void cleanup(void) +{ +	if(dbpath) { +		free(dbpath); +	} + +	alpm_list_free(walked); +	alpm_list_free(provisions); +	alpm_release(); +} + +/* pkg provides provision */ +static void print_text(const char *pkg, const char *provision, int depth) +{ +	int indent_sz = (depth + 1) * indent_size; + +	if(!pkg && !provision) { +		/* not much we can do */ +		return; +	} + +	if(!pkg && provision) { +		/* we failed to resolve provision */ +		printf("%s%*s%s%s%s%s%s\n", branch1_color, indent_sz, branch_tip1, +				leaf1_color, provision, branch1_color, unresolvable, color_off); +	} else if(provision && strcmp(pkg, provision) != 0) { +		/* pkg provides provision */ +		printf("%s%*s%s%s%s%s %s%s%s\n", branch2_color, indent_sz, branch_tip2, +				leaf1_color, pkg, leaf2_color, provides, leaf1_color, provision, +				color_off); +	} else { +		/* pkg is a normal package */ +		printf("%s%*s%s%s%s\n", branch1_color, indent_sz, branch_tip1, leaf1_color, +				pkg, color_off); +	} +} + +static void print_graph(const char *parentname, const char *pkgname, const char *depname) +{ +	if(depname) { +		printf("\"%s\" -> \"%s\" [color=chocolate4];\n", parentname, depname); +		if(pkgname && strcmp(depname, pkgname) != 0 && !alpm_list_find_str(provisions, depname)) { +			printf("\"%s\" -> \"%s\" [arrowhead=none, color=grey];\n", depname, pkgname); +			provisions = alpm_list_add(provisions, (char *)depname); +		} +	} else if(pkgname) { +		printf("\"%s\" -> \"%s\" [color=chocolate4];\n", parentname, pkgname); +	} +} + +/* parent depends on dep which is satisfied by pkg */ +static void print(const char *parentname, const char *pkgname, const char *depname, int depth) +{ +	if(graphviz) { +		print_graph(parentname, pkgname, depname); +	} else { +		print_text(pkgname, depname, depth); +	} +} + +static void print_start(const char *pkgname, const char *provname) +{ +	if(graphviz) { +		printf("digraph G { START [color=red, style=filled];\n" +				"node [style=filled, color=green];\n" +				" \"START\" -> \"%s\";\n", pkgname); +	} else { +		print_text(pkgname, provname, 0); +	} +} + +static void print_end(void) +{ +	if(graphviz) { +		/* close graph output */ +		printf("}\n"); +	} +} + + +/** + * walk dependencies in reverse, showing packages which require the target + */ +static void walk_reverse_deps(pmpkg_t *pkg, int depth) +{ +	alpm_list_t *required_by, *i; + +	if((max_depth >= 0) && (depth == max_depth + 1)) { +		return; +	} + +	walked = alpm_list_add(walked, (void*)alpm_pkg_get_name(pkg)); +	required_by = alpm_pkg_compute_requiredby(pkg); + +	for(i = required_by; i; i = alpm_list_next(i)) { +		const char *pkgname = alpm_list_getdata(i); + +		if(alpm_list_find_str(walked, pkgname)) { +			/* if we've already seen this package, don't print in "unique" output +			 * and don't recurse */ +			if(!unique) { +				print(alpm_pkg_get_name(pkg), pkgname, NULL, depth); +			} +		} else { +			print(alpm_pkg_get_name(pkg), pkgname, NULL, depth); +			walk_reverse_deps(alpm_db_get_pkg(db_local, pkgname), depth + 1); +		} +	} + +	FREELIST(required_by); +} + +/** + * walk dependencies, showing dependencies of the target + */ +static void walk_deps(pmpkg_t *pkg, int depth) +{ +	alpm_list_t *i; + +	if((max_depth >= 0) && (depth == max_depth + 1)) { +		return; +	} + +	walked = alpm_list_add(walked, (void*)alpm_pkg_get_name(pkg)); + +	for(i = alpm_pkg_get_depends(pkg); i; i = alpm_list_next(i)) { +		pmdepend_t *depend = alpm_list_getdata(i); +		pmpkg_t *provider = alpm_find_satisfier(alpm_db_get_pkgcache(db_local), +				alpm_dep_get_name(depend)); + +		if(provider) { +			const char *provname = alpm_pkg_get_name(provider); + +			if(alpm_list_find_str(walked, provname)) { +				/* if we've already seen this package, don't print in "unique" output +				 * and don't recurse */ +				if(!unique) { +					print(alpm_pkg_get_name(pkg), provname, alpm_dep_get_name(depend), depth); +				} +			} else { +				print(alpm_pkg_get_name(pkg), provname, alpm_dep_get_name(depend), depth); +				walk_deps(provider, depth + 1); +			} +		} else { +			/* unresolvable package */ +			print(alpm_pkg_get_name(pkg), NULL, alpm_dep_get_name(depend), depth); +		} +	} +} + +int main(int argc, char *argv[]) +{ +	int ret; +	const char *target_name; +	pmpkg_t *pkg; + +	ret = parse_options(argc, argv); +	if(ret != 0) { +		usage(); +		goto finish; +	} + +	ret = alpm_local_init(); +	if(ret != 0) { +		fprintf(stderr, "error: cannot initialize alpm: %s\n", alpm_strerrorlast()); +		goto finish; +	} + +	/* we only care about the first non option arg for walking */ +	target_name = argv[optind]; + +	pkg = alpm_find_satisfier(alpm_db_get_pkgcache(db_local), target_name); +	if(!pkg) { +		fprintf(stderr, "error: package '%s' not found\n", target_name); +		ret = 1; +		goto finish; +	} + +	print_start(alpm_pkg_get_name(pkg), target_name); + +	if(reverse) { +		walk_reverse_deps(pkg, 1); +	} else { +		walk_deps(pkg, 1); +	} + +	print_end(); + +finish: +	cleanup(); +	return(ret); +} + +/* vim: set ts=2 sw=2 noet: */ diff --git a/src/util/testdb.c b/src/util/testdb.c index 6d351ebd..28f2b2b3 100644 --- a/src/util/testdb.c +++ b/src/util/testdb.c @@ -30,11 +30,6 @@  #define BASENAME "testdb" -int str_cmp(const void *s1, const void *s2) -{ -	return(strcmp(s1, s2)); -} -  static void cleanup(int signum) {  	if(alpm_release() == -1) {  		fprintf(stderr, "error releasing alpm: %s\n", alpm_strerrorlast()); @@ -69,7 +64,7 @@ static int db_test(char *dbpath, int local)  	}  	while ((ent = readdir(dir)) != NULL) { -		if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..") +		if(strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0  				|| ent->d_name[0] == '.') {  			continue;  		} @@ -100,7 +95,7 @@ static int db_test(char *dbpath, int local)  	return(ret);  } -int checkdeps(alpm_list_t *pkglist) +static int checkdeps(alpm_list_t *pkglist)  {  	alpm_list_t *data, *i;  	int ret = 0; @@ -119,7 +114,7 @@ int checkdeps(alpm_list_t *pkglist)  	return(ret);  } -int checkconflicts(alpm_list_t *pkglist) +static int checkconflicts(alpm_list_t *pkglist)  {  	alpm_list_t *data, *i;  	int ret = 0; @@ -135,7 +130,7 @@ int checkconflicts(alpm_list_t *pkglist)  	return(ret);  } -int check_localdb(char *dbpath) { +static int check_localdb(char *dbpath) {  	char localdbpath[PATH_MAX];  	int ret = 0;  	pmdb_t *db = NULL; @@ -159,7 +154,7 @@ int check_localdb(char *dbpath) {  	return(ret);  } -int check_syncdbs(char *dbpath, alpm_list_t *dbnames) { +static int check_syncdbs(char *dbpath, alpm_list_t *dbnames) {  	char syncdbpath[PATH_MAX];  	int ret = 0;  	pmdb_t *db = NULL; @@ -190,7 +185,7 @@ cleanup:  	return(ret);  } -void usage() { +static void usage(void) {  	fprintf(stderr, "usage:\n");  	fprintf(stderr,  			"\t%s [-b <pacman db>]                : check the local database\n", BASENAME); @@ -199,7 +194,7 @@ void usage() {  	exit(1);  } -int main(int argc, char **argv) +int main(int argc, char *argv[])  {  	int ret = 0;  	char *dbpath = DBPATH; diff --git a/src/util/testpkg.c b/src/util/testpkg.c index d86fb1e0..6fc0ce00 100644 --- a/src/util/testpkg.c +++ b/src/util/testpkg.c @@ -17,8 +17,6 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <stdio.h> /* printf */  #include <stdarg.h> /* va_list */ @@ -26,7 +24,7 @@  #define BASENAME "testpkg" -static void output_cb(pmloglevel_t level, char *fmt, va_list args) +void output_cb(pmloglevel_t level, char *fmt, va_list args)  {  	if(fmt[0] == '\0') {  		return; @@ -39,7 +37,7 @@ static void output_cb(pmloglevel_t level, char *fmt, va_list args)  	vprintf(fmt, args);  } -int main(int argc, char **argv) +int main(int argc, char *argv[])  {  	int retval = 1; /* default = false */  	pmpkg_t *pkg = NULL; diff --git a/src/util/vercmp.c b/src/util/vercmp.c index 959dc137..8a785bb8 100644 --- a/src/util/vercmp.c +++ b/src/util/vercmp.c @@ -18,20 +18,16 @@   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.   */ -#include "config.h" -  #include <stdio.h> /* printf */  #include <string.h> /* strncpy */  #define BASENAME "vercmp" -#define MAX_LEN 255 -  /* forward declaration, comes from vercmp.o in libalpm source that is linked in   * directly so we don't have any library deps */  int alpm_pkg_vercmp(const char *a, const char *b); -static void usage() +static void usage(void)  {  	fprintf(stderr, "usage: %s <ver1> <ver2>\n\n", BASENAME);  	fprintf(stderr, "return values:\n"); @@ -42,8 +38,8 @@ static void usage()  int main(int argc, char *argv[])  { -	char s1[MAX_LEN] = ""; -	char s2[MAX_LEN] = ""; +	const char *s1 = ""; +	const char *s2 = "";  	int ret;  	if(argc == 1) { @@ -56,16 +52,11 @@ int main(int argc, char *argv[])  		usage();  		return(0);  	} -	if(argc > 1) { -		strncpy(s1, argv[1], MAX_LEN); -		s1[MAX_LEN -1] = '\0'; -	}  	if(argc > 2) { -		strncpy(s2, argv[2], MAX_LEN); -		s2[MAX_LEN -1] = '\0'; -	} else { -		printf("0\n"); -		return(0); +		s2 = argv[2]; +	} +	if(argc > 1) { +		s1 = argv[1];  	}  	ret = alpm_pkg_vercmp(s1, s2); | 
