diff --git a/NEWS b/NEWS index 409d7106..1b254eb2 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,8 @@ xbps-0.38 (???): + * xbps-query(8): added --fulldeptree long option to print a full dependency + tree for a package; this supersedes -xx which was broken since 0.37. + * xbps-query(8): fix a segfault with -Rf when there's no network connectivity. Reported by Gottox. diff --git a/bin/xbps-query/defs.h b/bin/xbps-query/defs.h index 05a3691d..44a60acf 100644 --- a/bin/xbps-query/defs.h +++ b/bin/xbps-query/defs.h @@ -35,10 +35,8 @@ #endif /* from show-deps.c */ -int show_pkg_deps(struct xbps_handle *, const char *, bool); -int show_pkg_revdeps(struct xbps_handle *, const char *); -int repo_show_pkg_deps(struct xbps_handle *, const char *, bool); -int repo_show_pkg_revdeps(struct xbps_handle *, const char *); +int show_pkg_deps(struct xbps_handle *, const char *, bool, bool); +int show_pkg_revdeps(struct xbps_handle *, const char *, bool); /* from show-info-files.c */ void show_pkg_info(xbps_dictionary_t); diff --git a/bin/xbps-query/main.c b/bin/xbps-query/main.c index 77c6e4e2..1d3bb28b 100644 --- a/bin/xbps-query/main.c +++ b/bin/xbps-query/main.c @@ -49,6 +49,7 @@ usage(bool fail) " to the top of the list. This option can be\n" " specified multiple times.\n" " --regex Use Extended Regular Expressions to match\n" + " --fulldeptree Full dependency tree for -x/--deps\n" " -r --rootdir Full path to rootdir\n" " -V --version Show XBPS version\n" " -v --verbose Verbose messages\n" @@ -62,7 +63,7 @@ usage(bool fail) " -S --show PKG Show information for PKG [default mode]\n" " -s --search PKG Search for packages by matching PKG, STRING or REGEX\n" " -f --files PKG Show package files for PKG\n" - " -x --deps PKG Show dependencies for PKG (set it twice for a full dependency tree)\n" + " -x --deps PKG Show dependencies for PKG\n" " -X --revdeps PKG Show reverse dependencies for PKG\n"); exit(fail ? EXIT_FAILURE : EXIT_SUCCESS); @@ -94,20 +95,21 @@ main(int argc, char **argv) { "files", required_argument, NULL, 'f' }, { "deps", required_argument, NULL, 'x' }, { "revdeps", required_argument, NULL, 'X' }, + { "fulldeptree", no_argument, NULL, 1 }, { NULL, 0, NULL, 0 }, }; struct xbps_handle xh; const char *pkg, *rootdir, *cachedir, *conffile, *props; - int c, flags, rv, show_deps = 0; + int c, flags, rv; bool list_pkgs, list_repos, orphans, own; - bool list_manual, list_hold, show_prop, show_files, show_rdeps; + bool list_manual, list_hold, show_prop, show_files, show_deps, show_rdeps; bool show, search, regex, repo_mode, opmode, fulldeptree; rootdir = cachedir = conffile = props = pkg = NULL; flags = rv = c = 0; list_pkgs = list_repos = list_hold = orphans = search = own = false; list_manual = show_prop = show_files = false; - regex = show = show_rdeps = fulldeptree = false; + regex = show = show_deps = show_rdeps = fulldeptree = false; repo_mode = opmode = false; memset(&xh, 0, sizeof(xh)); @@ -181,8 +183,7 @@ main(int argc, char **argv) exit(EXIT_SUCCESS); case 'x': pkg = optarg; - show_deps++; - opmode = true; + show_deps = opmode = true; break; case 'X': pkg = optarg; @@ -191,6 +192,9 @@ main(int argc, char **argv) case 0: regex = true; break; + case 1: + fulldeptree = true; + break; case '?': usage(true); /* NOTREACHED */ @@ -268,20 +272,11 @@ main(int argc, char **argv) } else if (show_deps) { /* show-deps mode */ - if (show_deps > 1) - fulldeptree = true; - - if (repo_mode) - rv = repo_show_pkg_deps(&xh, pkg, fulldeptree); - else - rv = show_pkg_deps(&xh, pkg, fulldeptree); + rv = show_pkg_deps(&xh, pkg, repo_mode, fulldeptree); } else if (show_rdeps) { /* show-rdeps mode */ - if (repo_mode) - rv = repo_show_pkg_revdeps(&xh, pkg); - else - rv = show_pkg_revdeps(&xh, pkg); + rv = show_pkg_revdeps(&xh, pkg, repo_mode); } exit(rv); diff --git a/bin/xbps-query/show-deps.c b/bin/xbps-query/show-deps.c index 0a9f8f0f..0364e66f 100644 --- a/bin/xbps-query/show-deps.c +++ b/bin/xbps-query/show-deps.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2009-2013 Juan Romero Pardines. + * Copyright (c) 2009-2014 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,74 +32,159 @@ #include #include "defs.h" +#include "queue.h" + +struct pkgdep { + SLIST_ENTRY(pkgdep) pkgdep_entries; + const char *pkg; + xbps_array_t rdeps; +}; + +static SLIST_HEAD(pkgdep_head, pkgdep) pkgdep_list = + SLIST_HEAD_INITIALIZER(pkgdep_list); static void -print_rdeps(struct xbps_handle *xhp, xbps_array_t rdeps, - bool full, bool repo, bool origin, int *indent) +print_rdeps(struct xbps_handle *xhp, xbps_array_t rdeps, bool full, bool repo) { xbps_array_t currdeps; xbps_dictionary_t pkgd; - const char *pkgdep; - - if (!origin) - (*indent)++; + const char *curdep; for (unsigned int i = 0; i < xbps_array_count(rdeps); i++) { - xbps_array_get_cstring_nocopy(rdeps, i, &pkgdep); - if (!origin || !full) - for (int j = 0; j < *indent; j++) - putchar(' '); + struct pkgdep *pd; + const char *pkgver; + char *vpkg; + bool virtual = false, found = false; - printf("%s\n", pkgdep); - if (!full) + xbps_array_get_cstring_nocopy(rdeps, i, &curdep); + if (!full) { + printf("%s\n", curdep); continue; - - if (repo) { - pkgd = xbps_rpool_get_pkg(xhp, pkgdep); - if (pkgd == NULL) - pkgd = xbps_rpool_get_virtualpkg(xhp, pkgdep); - } else { - pkgd = xbps_pkgdb_get_pkg(xhp, pkgdep); - if (pkgd == NULL) - pkgd = xbps_pkgdb_get_virtualpkg(xhp, pkgdep); } - if (pkgd != NULL) { - currdeps = xbps_dictionary_get(pkgd, "run_depends"); - if (currdeps != NULL) - print_rdeps(xhp, currdeps, - full, repo, false, indent); + if (repo) { + if ((pkgd = xbps_rpool_get_pkg(xhp, curdep)) == NULL) + pkgd = xbps_rpool_get_virtualpkg(xhp, curdep); + } else { + if ((pkgd = xbps_pkgdb_get_pkg(xhp, curdep)) == NULL) { + pkgd = xbps_pkgdb_get_virtualpkg(xhp, curdep); + virtual = true; + } + } + assert(pkgd); + currdeps = xbps_dictionary_get(pkgd, "run_depends"); + xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver); + assert(pkgver); + if (virtual) { + char *p; + + if ((p = xbps_pkgpattern_name(curdep)) == NULL) + p = xbps_pkg_name(curdep); + + assert(p); + vpkg = xbps_xasprintf("%s-0.1_1", p); + assert(vpkg); + free(p); + } + /* uniquify dependencies, sorting will be done later */ + SLIST_FOREACH(pd, &pkgdep_list, pkgdep_entries) { + if (virtual && strcmp(pd->pkg, vpkg) == 0) { + found = true; + break; + } else if (strcmp(pd->pkg, pkgver) == 0) { + found = true; + break; + } + } + if (!found) { + pd = malloc(sizeof(*pd)); + assert(pd); + if (virtual) + pd->pkg = vpkg; + else + pd->pkg = pkgver; + + pd->rdeps = xbps_array_copy(currdeps); + SLIST_INSERT_HEAD(&pkgdep_list, pd, pkgdep_entries); + } + if (xbps_array_count(currdeps)) + print_rdeps(xhp, currdeps, full, repo); + } +} + +static xbps_array_t +sort_rdeps(void) +{ + struct pkgdep *pd; + xbps_array_t result; + unsigned int ndeps = 0; + + result = xbps_array_create(); + assert(result); + + SLIST_FOREACH(pd, &pkgdep_list, pkgdep_entries) { + if (!pd->rdeps) { + xbps_array_add_cstring_nocopy(result, pd->pkg); + SLIST_REMOVE(&pkgdep_list, pd, pkgdep, pkgdep_entries); + } + ndeps++; + } + while (xbps_array_count(result) < ndeps) { + bool found = false; + + SLIST_FOREACH(pd, &pkgdep_list, pkgdep_entries) { + unsigned int i = 0, mdeps = 0, rdeps = 0; + + rdeps = xbps_array_count(pd->rdeps); + for (i = 0; i < rdeps; i++) { + const char *pkgdep; + char *pkgname; + + xbps_array_get_cstring_nocopy(pd->rdeps, i, &pkgdep); + pkgname = xbps_pkgpattern_name(pkgdep); + if (pkgname == NULL) + pkgname = xbps_pkg_name(pkgdep); + + if (xbps_match_pkgname_in_array(result, pkgname)) + mdeps++; + + free(pkgname); + } + if (mdeps == rdeps) { + found = true; + break; + } + //printf("%s ndeps: %u result: %u rdeps: %u mdeps: %u\n", pd->pkg, ndeps, xbps_array_count(result), rdeps, mdeps); + } + if (found && !xbps_match_string_in_array(result, pd->pkg)) { + xbps_array_add_cstring_nocopy(result, pd->pkg); + SLIST_REMOVE(&pkgdep_list, pd, pkgdep, pkgdep_entries); } } - (*indent)--; + return result; } int -show_pkg_deps(struct xbps_handle *xhp, const char *pkgname, bool full) +show_pkg_deps(struct xbps_handle *xhp, const char *pkgname, bool repomode, bool full) { - xbps_array_t rdeps; + xbps_array_t rdeps, res; xbps_dictionary_t pkgd; - int indent = 0; - pkgd = xbps_pkgdb_get_pkg(xhp, pkgname); - if (pkgd == NULL) - return ENOENT; + if (repomode) { + if (((pkgd = xbps_rpool_get_pkg(xhp, pkgname)) == NULL) && + ((pkgd = xbps_rpool_get_virtualpkg(xhp, pkgname)) == NULL)) + return errno; + } else { + if ((pkgd = xbps_pkgdb_get_pkg(xhp, pkgname)) == NULL) + return ENOENT; + } + if ((rdeps = xbps_dictionary_get(pkgd, "run_depends"))) + print_rdeps(xhp, rdeps, full, repomode); + if (full) { + res = sort_rdeps(); + for (unsigned int i = 0; i < xbps_array_count(res); i++) { + const char *pkgdep; - rdeps = xbps_dictionary_get(pkgd, "run_depends"); - if (rdeps != NULL) - print_rdeps(xhp, rdeps, full, false, true, &indent); - - return 0; -} - -int -show_pkg_revdeps(struct xbps_handle *xhp, const char *pkg) -{ - xbps_array_t reqby; - const char *pkgdep; - - if ((reqby = xbps_pkgdb_get_pkg_revdeps(xhp, pkg)) != NULL) { - for (unsigned int i = 0; i < xbps_array_count(reqby); i++) { - xbps_array_get_cstring_nocopy(reqby, i, &pkgdep); + xbps_array_get_cstring_nocopy(res, i, &pkgdep); printf("%s\n", pkgdep); } } @@ -107,37 +192,22 @@ show_pkg_revdeps(struct xbps_handle *xhp, const char *pkg) } int -repo_show_pkg_deps(struct xbps_handle *xhp, const char *pattern, bool full) -{ - xbps_array_t rdeps; - xbps_dictionary_t pkgd; - int indent = 0; - - if (((pkgd = xbps_rpool_get_pkg(xhp, pattern)) == NULL) && - ((pkgd = xbps_rpool_get_virtualpkg(xhp, pattern)) == NULL)) - return errno; - - rdeps = xbps_dictionary_get(pkgd, "run_depends"); - if (rdeps != NULL) - print_rdeps(xhp, rdeps, full, true, true, &indent); - - return 0; -} - -int -repo_show_pkg_revdeps(struct xbps_handle *xhp, const char *pkg) +show_pkg_revdeps(struct xbps_handle *xhp, const char *pkg, bool repomode) { xbps_array_t revdeps; - const char *pkgver; - int rv; + const char *pkgdep; - revdeps = xbps_rpool_get_pkg_revdeps(xhp, pkg); - rv = errno; + if (repomode) + revdeps = xbps_pkgdb_get_pkg_revdeps(xhp, pkg); + else + revdeps = xbps_rpool_get_pkg_revdeps(xhp, pkg); + + if (revdeps == NULL) + return ENOENT; for (unsigned int i = 0; i < xbps_array_count(revdeps); i++) { - xbps_array_get_cstring_nocopy(revdeps, i, &pkgver); - printf("%s\n", pkgver); + xbps_array_get_cstring_nocopy(revdeps, i, &pkgdep); + printf("%s\n", pkgdep); } - - return rv; + return 0; } diff --git a/bin/xbps-query/xbps-query.8 b/bin/xbps-query/xbps-query.8 index 744ff6a3..8c9a02a0 100644 --- a/bin/xbps-query/xbps-query.8 +++ b/bin/xbps-query/xbps-query.8 @@ -1,4 +1,4 @@ -.Dd May 27, 2014 +.Dd August 19, 2014 .Os Void Linux .Dt xbps-query 8 .Sh NAME @@ -77,6 +77,10 @@ currently in the and .Sy search modes. +.It Fl -fulldeptree +Prints a full dependency tree in the +.Sy show dependencies +mode. .It Fl r, Fl -rootdir Ar dir Specifies a full path for the target root directory. .It Fl v, Fl -verbose @@ -187,7 +191,8 @@ in repositories will be shown. .It Fl x, Fl -deps Ar PKG [ Fl -repository ] Show the required dependencies for .Ar PKG . -Only direct dependencies are shown. To see a full dependency tree set it twice. +Only direct dependencies are shown. To see a full dependency tree, also set +.Fl -fulldeptree . If the .Fl -repository option is set, the matched