xbps_get_pkg_fulldeptree: detect pkgs depending on itself via virtual pkgs.

Reported by Duncan Overbrook.

Update NEWS with recent changes.
This commit is contained in:
Juan RP 2015-03-20 08:03:06 +01:00
parent 1eeaa99438
commit dc47dfd593
5 changed files with 83 additions and 34 deletions

6
NEWS
View File

@ -1,5 +1,11 @@
xbps-0.44.1 (???): 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, * xbps-uunshare(8): does not fork and run cmd in the child process anymore,
replaces the execution environment with cmd instead. replaces the execution environment with cmd instead.

View File

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2014 Juan Romero Pardines. * Copyright (c) 2014-2015 Juan Romero Pardines.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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 xbps_dictionary_t pkgdep_pvmap;
static int 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_array_t rdeps, currdeps, provides = NULL;
xbps_dictionary_t pkgd;
const char *curdep;
for (unsigned int i = 0; i < xbps_array_count(rdeps); i++) {
struct pkgdep *pd; struct pkgdep *pd;
const char *pkgver; 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++) {
xbps_dictionary_t curpkgd;
const char *curdep, *curpkgver;
char *curdepname;
bool virtual = false, found = false; bool virtual = false, found = false;
xbps_array_get_cstring_nocopy(rdeps, i, &curdep); xbps_array_get_cstring_nocopy(rdeps, i, &curdep);
if (rpool) { if (rpool) {
if ((pkgd = xbps_rpool_get_pkg(xhp, curdep)) == NULL) { if ((curpkgd = xbps_rpool_get_pkg(xhp, curdep)) == NULL) {
pkgd = xbps_rpool_get_virtualpkg(xhp, curdep); curpkgd = xbps_rpool_get_virtualpkg(xhp, curdep);
virtual = true; virtual = true;
} }
} else { } else {
if ((pkgd = xbps_pkgdb_get_pkg(xhp, curdep)) == NULL) { if ((curpkgd = xbps_pkgdb_get_pkg(xhp, curdep)) == NULL) {
pkgd = xbps_pkgdb_get_virtualpkg(xhp, curdep); curpkgd = xbps_pkgdb_get_virtualpkg(xhp, curdep);
virtual = true; virtual = true;
} }
} }
if (pkgd == NULL) { if (curpkgd == NULL) {
xbps_dbg_printf(xhp, "%s: cannot find `%s' dependency\n", xbps_dbg_printf(xhp, "%s: cannot find `%s' dependency\n",
__func__, curdep); __func__, curdep);
return ENOENT; return ENOENT;
} }
currdeps = xbps_dictionary_get(pkgd, "run_depends"); if (((curdepname = xbps_pkgpattern_name(curdep)) == NULL) &&
xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver); ((curdepname = xbps_pkg_name(curdep)) == NULL))
assert(pkgver);
if (virtual) {
char *p;
if (((p = xbps_pkgpattern_name(curdep)) == NULL) &&
((p = xbps_pkg_name(curdep)) == NULL))
return EINVAL; return EINVAL;
if (pkgdep_pvmap == NULL) xbps_dictionary_get_cstring_nocopy(curpkgd, "pkgver", &curpkgver);
pkgdep_pvmap = xbps_dictionary_create(); currdeps = xbps_dictionary_get(curpkgd, "run_depends");
xbps_dictionary_set_cstring_nocopy(pkgdep_pvmap, p, pkgver); if (provides && xbps_match_pkgname_in_array(provides, curdepname)) {
free(p); 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 */ /* uniquify dependencies, sorting will be done later */
SLIST_FOREACH(pd, &pkgdep_list, pkgdep_entries) { SLIST_FOREACH(pd, &pkgdep_list, pkgdep_entries) {
if (strcmp(pd->pkg, pkgver) == 0) { if (strcmp(pd->pkg, curpkgver) == 0) {
found = true; found = true;
break; break;
} }
@ -97,14 +104,14 @@ collect_rdeps(struct xbps_handle *xhp, xbps_array_t rdeps, bool rpool)
if (!found) { if (!found) {
pd = malloc(sizeof(*pd)); pd = malloc(sizeof(*pd));
assert(pd); assert(pd);
pd->pkg = pkgver; pd->pkg = curpkgver;
pd->rdeps = xbps_array_copy(currdeps); pd->rdeps = xbps_array_copy(currdeps);
SLIST_INSERT_HEAD(&pkgdep_list, pd, pkgdep_entries); SLIST_INSERT_HEAD(&pkgdep_list, pd, pkgdep_entries);
} }
if (xbps_array_count(currdeps)) { if (xbps_array_count(currdeps)) {
int rv; int rv;
if ((rv = collect_rdeps(xhp, currdeps, rpool)) != 0) if ((rv = collect_rdeps(xhp, curpkgd, rpool)) != 0)
return rv; return rv;
} }
} }
@ -164,6 +171,7 @@ sortfulldeptree(void)
if (found && !xbps_match_string_in_array(result, pd->pkg)) { if (found && !xbps_match_string_in_array(result, pd->pkg)) {
xbps_array_add_cstring_nocopy(result, pd->pkg); xbps_array_add_cstring_nocopy(result, pd->pkg);
SLIST_REMOVE(&pkgdep_list, pd, pkgdep, pkgdep_entries); SLIST_REMOVE(&pkgdep_list, pd, pkgdep, pkgdep_entries);
free(pd);
} }
} }
return result; return result;
@ -172,7 +180,6 @@ sortfulldeptree(void)
xbps_array_t HIDDEN xbps_array_t HIDDEN
xbps_get_pkg_fulldeptree(struct xbps_handle *xhp, const char *pkg, bool rpool) xbps_get_pkg_fulldeptree(struct xbps_handle *xhp, const char *pkg, bool rpool)
{ {
xbps_array_t rdeps;
xbps_dictionary_t pkgd; xbps_dictionary_t pkgd;
int rv; 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)) ((pkgd = xbps_pkgdb_get_virtualpkg(xhp, pkg)) == NULL))
return NULL; return NULL;
} }
if ((rdeps = xbps_dictionary_get(pkgd, "run_depends"))) { if (pkgdep_pvmap == NULL)
if ((rv = collect_rdeps(xhp, rdeps, rpool)) != 0) pkgdep_pvmap = xbps_dictionary_create();
if ((rv = collect_rdeps(xhp, pkgd, rpool)) != 0)
return NULL; return NULL;
}
return sortfulldeptree(); return sortfulldeptree();
} }

View File

@ -19,3 +19,4 @@ atf_test_program{name="preserve_files_test"}
atf_test_program{name="update_shlibs"} atf_test_program{name="update_shlibs"}
atf_test_program{name="update_hold"} atf_test_program{name="update_hold"}
atf_test_program{name="update_repolock"} atf_test_program{name="update_repolock"}
atf_test_program{name="cyclic_deps"}

View File

@ -6,7 +6,7 @@ TESTSHELL = conf_files_test issue6_test issue18_test issue20_test remove_test
TESTSHELL+= replace_test installmode_test obsoletefiles_test TESTSHELL+= replace_test installmode_test obsoletefiles_test
TESTSHELL+= issue31_test scripts_test incorrect_deps_test TESTSHELL+= issue31_test scripts_test incorrect_deps_test
TESTSHELL+= vpkg_test install_test preserve_files_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 EXTRA_FILES = Kyuafile
include $(TOPDIR)/mk/test.mk include $(TOPDIR)/mk/test.mk

View File

@ -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
}