From dc47dfd5935119dca1c9b64a38fab0aaef1c7636 Mon Sep 17 00:00:00 2001 From: Juan RP Date: Fri, 20 Mar 2015 08:03:06 +0100 Subject: [PATCH] xbps_get_pkg_fulldeptree: detect pkgs depending on itself via virtual pkgs. Reported by Duncan Overbrook. Update NEWS with recent changes. --- NEWS | 6 ++ lib/package_fulldeptree.c | 74 ++++++++++++++----------- tests/xbps/libxbps/shell/Kyuafile | 1 + tests/xbps/libxbps/shell/Makefile | 2 +- tests/xbps/libxbps/shell/cyclic_deps.sh | 34 ++++++++++++ 5 files changed, 83 insertions(+), 34 deletions(-) create mode 100644 tests/xbps/libxbps/shell/cyclic_deps.sh diff --git a/NEWS b/NEWS index fcbe11b8..3b2462fe 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,11 @@ xbps-0.44.1 (???): + * libxbps: fixed xbps_get_pkg_fulldeptree() when a pkg depends on itself via + virtual packages. Reported by Duncan Overbrook. + + * portableproplib: fixed a regression introduced in 0.44 resulting in EBADF + while internalizing plists. + * xbps-uunshare(8): does not fork and run cmd in the child process anymore, replaces the execution environment with cmd instead. diff --git a/lib/package_fulldeptree.c b/lib/package_fulldeptree.c index 7e3785ac..36e7eeb6 100644 --- a/lib/package_fulldeptree.c +++ b/lib/package_fulldeptree.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2014 Juan Romero Pardines. + * Copyright (c) 2014-2015 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,53 +43,60 @@ static SLIST_HEAD(pkgdep_head, pkgdep) pkgdep_list = static xbps_dictionary_t pkgdep_pvmap; static int -collect_rdeps(struct xbps_handle *xhp, xbps_array_t rdeps, bool rpool) +collect_rdeps(struct xbps_handle *xhp, xbps_dictionary_t pkgd, bool rpool) { - xbps_array_t currdeps; - xbps_dictionary_t pkgd; - const char *curdep; + xbps_array_t rdeps, currdeps, provides = NULL; + struct pkgdep *pd; + const char *pkgver; + + xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver); + assert(pkgver); + rdeps = xbps_dictionary_get(pkgd, "run_depends"); + provides = xbps_dictionary_get(pkgd, "provides"); for (unsigned int i = 0; i < xbps_array_count(rdeps); i++) { - struct pkgdep *pd; - const char *pkgver; + xbps_dictionary_t curpkgd; + const char *curdep, *curpkgver; + char *curdepname; 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); + if ((curpkgd = xbps_rpool_get_pkg(xhp, curdep)) == NULL) { + curpkgd = 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); + if ((curpkgd = xbps_pkgdb_get_pkg(xhp, curdep)) == NULL) { + curpkgd = xbps_pkgdb_get_virtualpkg(xhp, curdep); virtual = true; } } - if (pkgd == NULL) { + if (curpkgd == 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 (((curdepname = xbps_pkgpattern_name(curdep)) == NULL) && + ((curdepname = xbps_pkg_name(curdep)) == NULL)) + return EINVAL; - if (((p = xbps_pkgpattern_name(curdep)) == NULL) && - ((p = xbps_pkg_name(curdep)) == NULL)) - return EINVAL; + xbps_dictionary_get_cstring_nocopy(curpkgd, "pkgver", &curpkgver); + currdeps = xbps_dictionary_get(curpkgd, "run_depends"); - if (pkgdep_pvmap == NULL) - pkgdep_pvmap = xbps_dictionary_create(); - - xbps_dictionary_set_cstring_nocopy(pkgdep_pvmap, p, pkgver); - free(p); + if (provides && xbps_match_pkgname_in_array(provides, curdepname)) { + xbps_dbg_printf(xhp, "%s: ignoring dependency %s " + "already in provides\n", pkgver, curdep); + free(curdepname); + continue; } + if (virtual) { + xbps_dictionary_set_cstring_nocopy(pkgdep_pvmap, curdepname, pkgver); + } + free(curdepname); /* uniquify dependencies, sorting will be done later */ SLIST_FOREACH(pd, &pkgdep_list, pkgdep_entries) { - if (strcmp(pd->pkg, pkgver) == 0) { + if (strcmp(pd->pkg, curpkgver) == 0) { found = true; break; } @@ -97,14 +104,14 @@ collect_rdeps(struct xbps_handle *xhp, xbps_array_t rdeps, bool rpool) if (!found) { pd = malloc(sizeof(*pd)); assert(pd); - pd->pkg = pkgver; + pd->pkg = curpkgver; 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) + if ((rv = collect_rdeps(xhp, curpkgd, rpool)) != 0) return rv; } } @@ -164,6 +171,7 @@ sortfulldeptree(void) 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); + free(pd); } } return result; @@ -172,7 +180,6 @@ sortfulldeptree(void) 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; @@ -185,10 +192,11 @@ xbps_get_pkg_fulldeptree(struct xbps_handle *xhp, const char *pkg, bool rpool) ((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; - } + if (pkgdep_pvmap == NULL) + pkgdep_pvmap = xbps_dictionary_create(); + + if ((rv = collect_rdeps(xhp, pkgd, rpool)) != 0) + return NULL; return sortfulldeptree(); } diff --git a/tests/xbps/libxbps/shell/Kyuafile b/tests/xbps/libxbps/shell/Kyuafile index 29203594..cec7361b 100644 --- a/tests/xbps/libxbps/shell/Kyuafile +++ b/tests/xbps/libxbps/shell/Kyuafile @@ -19,3 +19,4 @@ atf_test_program{name="preserve_files_test"} atf_test_program{name="update_shlibs"} atf_test_program{name="update_hold"} atf_test_program{name="update_repolock"} +atf_test_program{name="cyclic_deps"} diff --git a/tests/xbps/libxbps/shell/Makefile b/tests/xbps/libxbps/shell/Makefile index 0b191262..f65bb17c 100644 --- a/tests/xbps/libxbps/shell/Makefile +++ b/tests/xbps/libxbps/shell/Makefile @@ -6,7 +6,7 @@ TESTSHELL = conf_files_test issue6_test issue18_test issue20_test remove_test TESTSHELL+= replace_test installmode_test obsoletefiles_test TESTSHELL+= issue31_test scripts_test incorrect_deps_test TESTSHELL+= vpkg_test install_test preserve_files_test -TESTSHELL+= update_shlibs update_hold update_repolock +TESTSHELL+= update_shlibs update_hold update_repolock cyclic_deps EXTRA_FILES = Kyuafile include $(TOPDIR)/mk/test.mk diff --git a/tests/xbps/libxbps/shell/cyclic_deps.sh b/tests/xbps/libxbps/shell/cyclic_deps.sh new file mode 100644 index 00000000..cb0562e4 --- /dev/null +++ b/tests/xbps/libxbps/shell/cyclic_deps.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env atf-sh +# + +atf_test_case cyclic_dep_vpkg + +cyclic_dep_vpkg_head() { + atf_set "descr" "Tests for cyclic deps: pkg depends on a cyclic vpkg" +} + +cyclic_dep_vpkg_body() { + mkdir some_repo + mkdir -p pkg_{A,B,C,D}/usr/bin + cd some_repo + xbps-create -A noarch -n A-1.0_1 -s "A pkg" --provides "libGL-7.11_1" --dependencies "libGL>=7.11" ../pkg_A + atf_check_equal $? 0 + xbps-create -A noarch -n B-1.0_1 -s "B pkg" --dependencies "libGL>=7.11" ../pkg_B + atf_check_equal $? 0 + xbps-create -A noarch -n C-1.0_1 -s "C pkg" --dependencies "B>=0" ../pkg_C + atf_check_equal $? 0 + + xbps-rindex -d -a $PWD/*.xbps + atf_check_equal $? 0 + cd .. + + xbps-install -r root --repository=$PWD/some_repo -dy C + atf_check_equal $? 0 + + xbps-query -r root --fulldeptree -x C + atf_check_equal $? 0 +} + +atf_init_test_cases() { + atf_add_test_case cyclic_dep_vpkg +}