diff --git a/bin/xbps-query/show-deps.c b/bin/xbps-query/show-deps.c index 5b2dc85a..feebc471 100644 --- a/bin/xbps-query/show-deps.c +++ b/bin/xbps-query/show-deps.c @@ -32,152 +32,13 @@ #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 xbps_dictionary_t pkgdep_pvmap; - -static void -print_rdeps(struct xbps_handle *xhp, xbps_array_t rdeps, bool full, bool repo) -{ - xbps_array_t currdeps; - xbps_dictionary_t pkgd; - const char *curdep; - - for (unsigned int i = 0; i < xbps_array_count(rdeps); i++) { - struct pkgdep *pd; - const char *pkgver; - bool virtual = false, found = false; - - xbps_array_get_cstring_nocopy(rdeps, i, &curdep); - if (!full) { - printf("%s\n", curdep); - continue; - } - if (repo) { - if ((pkgd = xbps_rpool_get_pkg(xhp, curdep)) == NULL) { - pkgd = xbps_rpool_get_virtualpkg(xhp, curdep); - virtual = true; - } - } 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); - if (pkgdep_pvmap == NULL) - pkgdep_pvmap = xbps_dictionary_create(); - - xbps_dictionary_set_cstring_nocopy(pkgdep_pvmap, p, pkgver); - free(p); - } - /* uniquify dependencies, sorting will be done later */ - SLIST_FOREACH(pd, &pkgdep_list, pkgdep_entries) { - if (strcmp(pd->pkg, pkgver) == 0) { - found = true; - break; - } - } - if (!found) { - pd = malloc(sizeof(*pd)); - assert(pd); - pd->pkg = pkgver; - pd->rdeps = xbps_array_copy(currdeps); - SLIST_INSERT_HEAD(&pkgdep_list, pd, pkgdep_entries); - //printf("Added %s into the slist\n", pd->pkg); - } - 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); - if ((pkgname = xbps_pkgpattern_name(pkgdep)) == NULL) - pkgname = xbps_pkg_name(pkgdep); - - assert(pkgname); - if (xbps_match_pkgname_in_array(result, pkgname)) { - mdeps++; - free(pkgname); - continue; - } - if (xbps_dictionary_get(pkgdep_pvmap, pkgname)) { - mdeps++; - free(pkgname); - continue; - } - //printf("%s: missing dep %s\n", pd->pkg, pkgdep); - 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); - } - } - return result; -} int show_pkg_deps(struct xbps_handle *xhp, const char *pkgname, bool repomode, bool full) { - xbps_array_t rdeps, res; + xbps_array_t rdeps; xbps_dictionary_t pkgd; + unsigned int cnt; if (repomode) { if (((pkgd = xbps_rpool_get_pkg(xhp, pkgname)) == NULL) && @@ -187,16 +48,21 @@ show_pkg_deps(struct xbps_handle *xhp, const char *pkgname, bool repomode, bool 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; + if (repomode) + rdeps = xbps_rpool_get_pkg_fulldeptree(xhp, pkgname); + else + rdeps = xbps_pkgdb_get_pkg_fulldeptree(xhp, pkgname); + } else { + rdeps = xbps_dictionary_get(pkgd, "run_depends"); + } + if ((cnt = xbps_array_count(rdeps)) == 0) + return ENOENT; - xbps_array_get_cstring_nocopy(res, i, &pkgdep); - printf("%s\n", pkgdep); - } + for (unsigned int i = 0; i < cnt; i++) { + const char *pkgdep; + xbps_array_get_cstring_nocopy(rdeps, i, &pkgdep); + printf("%s\n", pkgdep); } return 0; } diff --git a/include/xbps.h.in b/include/xbps.h.in index 4fe08acb..a0b51557 100644 --- a/include/xbps.h.in +++ b/include/xbps.h.in @@ -48,7 +48,7 @@ * * This header documents the full API for the XBPS Library. */ -#define XBPS_API_VERSION "20141117-1" +#define XBPS_API_VERSION "20141120" #ifndef XBPS_VERSION #define XBPS_VERSION "UNSET" @@ -815,11 +815,25 @@ xbps_dictionary_t xbps_pkgdb_get_pkg_files(struct xbps_handle *xhp, * @param[in] xhp The pointer to the xbps_handle struct. * @param[in] pkg Package expression to match. * - * @return A proplib array of strings with reverse dependencies for \a pkg. + * @return A proplib array of strings with reverse dependencies for \a pkg, + * NULL otherwise. */ xbps_array_t xbps_pkgdb_get_pkg_revdeps(struct xbps_handle *xhp, const char *pkg); +/** + * Returns a proplib array of strings with a proper sorted list + * of packages of a full dependency graph for \a pkg. + * + * @param[in] xhp The pointer to the xbps_handle struct. + * @param[in] pkg Package expression to match. + * + * @return A proplib array of strings with the full dependency graph for \a pkg, + * NULL otherwise. + */ +xbps_array_t xbps_pkgdb_get_pkg_fulldeptree(struct xbps_handle *xhp, + const char *pkg); + /** * Updates the package database (pkgdb) with new contents from the * cached memory copy to disk. @@ -1310,6 +1324,18 @@ xbps_dictionary_t xbps_rpool_get_virtualpkg(struct xbps_handle *xhp, */ xbps_array_t xbps_rpool_get_pkg_revdeps(struct xbps_handle *xhp, const char *pkg); +/** + * Returns a proplib array of strings with a proper sorted list + * of packages of a full dependency graph for \a pkg. + * + * @param[in] xhp The pointer to the xbps_handle struct. + * @param[in] pkg Package expression to match. + * + * @return A proplib array of strings with the full dependency graph for \a pkg, + * NULL otherwise. + */ +xbps_array_t xbps_rpool_get_pkg_fulldeptree(struct xbps_handle *xhp, const char *pkg); + /** * Iterate over the the repository pool and search for a metadata plist * file in a binary package matching `pattern'. If a package is matched diff --git a/include/xbps_api_impl.h b/include/xbps_api_impl.h index 7c25abc0..432a9264 100644 --- a/include/xbps_api_impl.h +++ b/include/xbps_api_impl.h @@ -149,5 +149,7 @@ char HIDDEN *xbps_archive_get_file(struct archive *, struct archive_entry *); xbps_dictionary_t HIDDEN xbps_archive_get_dictionary(struct archive *, struct archive_entry *); const char HIDDEN *vpkg_user_conf(struct xbps_handle *, const char *, bool); +xbps_array_t HIDDEN xbps_get_pkg_fulldeptree(struct xbps_handle *, + const char *, bool); #endif /* !_XBPS_API_IMPL_H_ */ diff --git a/lib/Makefile b/lib/Makefile index 9ec1f617..28be17ec 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -39,7 +39,7 @@ OBJS += package_unpack.o package_register.o package_script.o verifysig.o OBJS += package_msg.o pkgdb_conversion.o transaction_shlibs.o OBJS += transaction_commit.o transaction_package_replace.o OBJS += transaction_dictionary.o transaction_ops.o transaction_store.o -OBJS += transaction_revdeps.o pubkey2fp.o +OBJS += transaction_revdeps.o pubkey2fp.o package_fulldeptree.o OBJS += download.o initend.o pkgdb.o package_conflicts.o OBJS += plist.o plist_find.o plist_match.o archive.o OBJS += plist_remove.o plist_fetch.o util.o util_hash.o diff --git a/lib/package_fulldeptree.c b/lib/package_fulldeptree.c new file mode 100644 index 00000000..7e3785ac --- /dev/null +++ b/lib/package_fulldeptree.c @@ -0,0 +1,194 @@ +/*- + * Copyright (c) 2014 Juan Romero Pardines. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#include "xbps_api_impl.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 xbps_dictionary_t pkgdep_pvmap; + +static int +collect_rdeps(struct xbps_handle *xhp, xbps_array_t rdeps, bool rpool) +{ + xbps_array_t currdeps; + xbps_dictionary_t pkgd; + const char *curdep; + + for (unsigned int i = 0; i < xbps_array_count(rdeps); i++) { + struct pkgdep *pd; + const char *pkgver; + bool virtual = false, found = false; + + xbps_array_get_cstring_nocopy(rdeps, i, &curdep); + if (rpool) { + if ((pkgd = xbps_rpool_get_pkg(xhp, curdep)) == NULL) { + pkgd = xbps_rpool_get_virtualpkg(xhp, curdep); + virtual = true; + } + } else { + if ((pkgd = xbps_pkgdb_get_pkg(xhp, curdep)) == NULL) { + pkgd = xbps_pkgdb_get_virtualpkg(xhp, curdep); + virtual = true; + } + } + if (pkgd == NULL) { + xbps_dbg_printf(xhp, "%s: cannot find `%s' dependency\n", + __func__, curdep); + return ENOENT; + } + 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)) == NULL)) + return EINVAL; + + if (pkgdep_pvmap == NULL) + pkgdep_pvmap = xbps_dictionary_create(); + + xbps_dictionary_set_cstring_nocopy(pkgdep_pvmap, p, pkgver); + free(p); + } + /* uniquify dependencies, sorting will be done later */ + SLIST_FOREACH(pd, &pkgdep_list, pkgdep_entries) { + if (strcmp(pd->pkg, pkgver) == 0) { + found = true; + break; + } + } + if (!found) { + pd = malloc(sizeof(*pd)); + assert(pd); + pd->pkg = pkgver; + pd->rdeps = xbps_array_copy(currdeps); + SLIST_INSERT_HEAD(&pkgdep_list, pd, pkgdep_entries); + } + if (xbps_array_count(currdeps)) { + int rv; + + if ((rv = collect_rdeps(xhp, currdeps, rpool)) != 0) + return rv; + } + } + return 0; +} + +static xbps_array_t +sortfulldeptree(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); + if (((pkgname = xbps_pkgpattern_name(pkgdep)) == NULL) && + ((pkgname = xbps_pkg_name(pkgdep)) == NULL)) + return NULL; + + if (xbps_match_pkgname_in_array(result, pkgname)) { + mdeps++; + free(pkgname); + continue; + } + if (xbps_dictionary_get(pkgdep_pvmap, pkgname)) { + mdeps++; + free(pkgname); + continue; + } + free(pkgname); + } + if (mdeps == rdeps) { + found = true; + break; + } + } + 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); + } + } + return result; +} + +xbps_array_t HIDDEN +xbps_get_pkg_fulldeptree(struct xbps_handle *xhp, const char *pkg, bool rpool) +{ + xbps_array_t rdeps; + xbps_dictionary_t pkgd; + int rv; + + if (rpool) { + if (((pkgd = xbps_rpool_get_pkg(xhp, pkg)) == NULL) && + ((pkgd = xbps_rpool_get_virtualpkg(xhp, pkg)) == NULL)) + return NULL; + } else { + if (((pkgd = xbps_pkgdb_get_pkg(xhp, pkg)) == NULL) && + ((pkgd = xbps_pkgdb_get_virtualpkg(xhp, pkg)) == NULL)) + return NULL; + } + if ((rdeps = xbps_dictionary_get(pkgd, "run_depends"))) { + if ((rv = collect_rdeps(xhp, rdeps, rpool)) != 0) + return NULL; + } + + return sortfulldeptree(); +} diff --git a/lib/pkgdb.c b/lib/pkgdb.c index 41784442..4a3971a5 100644 --- a/lib/pkgdb.c +++ b/lib/pkgdb.c @@ -385,6 +385,12 @@ xbps_pkgdb_get_pkg_revdeps(struct xbps_handle *xhp, const char *pkg) return res; } +xbps_array_t +xbps_pkgdb_get_pkg_fulldeptree(struct xbps_handle *xhp, const char *pkg) +{ + return xbps_get_pkg_fulldeptree(xhp, pkg, false); +} + xbps_dictionary_t xbps_pkgdb_get_pkg_files(struct xbps_handle *xhp, const char *pkg) { diff --git a/lib/rpool.c b/lib/rpool.c index 47c728f8..566d71e5 100644 --- a/lib/rpool.c +++ b/lib/rpool.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 @@ -287,6 +287,12 @@ xbps_rpool_get_pkg_revdeps(struct xbps_handle *xhp, const char *pkg) return repo_find_pkg(xhp, pkg, REVDEPS_PKG); } +xbps_array_t +xbps_rpool_get_pkg_fulldeptree(struct xbps_handle *xhp, const char *pkg) +{ + return xbps_get_pkg_fulldeptree(xhp, pkg, true); +} + xbps_dictionary_t xbps_rpool_get_pkg_plist(struct xbps_handle *xhp, const char *pkg,