Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
xbps-0.60.7 (2025-02-09):

* xbps-query(1): fix off-by-one error in list ellipsis. [@kkmisiaszek]

* xbps-query(1): fix jumbled lines in xbps-query.1 man page. [@leahneukirchen]

* libxbps: fix directory matching in file conflicts check. [@duncaen]

* libxbps: fix regression for installing packages by pkgver. [@duncaen]

* libxbps: fix handling on cyclic dependencies. [@duncaen]

xbps-0.60.6 (2025-11-16):

* libxbps: improved error messages for package checksum mismatch and package
Expand Down
2 changes: 1 addition & 1 deletion configure
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/sh
# Try and be like autotools configure, but without autotools

VERSION=0.60
VERSION=0.60.7

# Ensure that we do not inherit these from env
OS=
Expand Down
44 changes: 37 additions & 7 deletions lib/transaction_pkg_deps.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ add_missing_reqdep(struct xbps_handle *xhp, const char *reqpkg)
static int
repo_deps(struct xbps_handle *xhp,
xbps_array_t pkgs, /* array of pkgs */
xbps_array_t queued, /* queued packages */
xbps_dictionary_t pkg_repod, /* pkg repo dictionary */
unsigned short *depth) /* max recursion depth */
{
Expand Down Expand Up @@ -182,8 +183,19 @@ repo_deps(struct xbps_handle *xhp,
continue;
}
/*
* Pass 2: check if required dependency has been already
* added in the transaction dictionary.
* Pass 2: check if required dependency is currently queued or
* has been already added in the transaction dictionary.
*/
if ((curpkgd = xbps_find_pkg_in_array(queued, reqpkg, 0)) ||
(curpkgd = xbps_find_virtualpkg_in_array(xhp, queued, reqpkg, 0))) {
xbps_trans_type_t ttype_q = xbps_transaction_pkg_type(curpkgd);
xbps_dictionary_get_cstring_nocopy(curpkgd, "pkgver", &pkgver_q);
xbps_dbg_printf_append(" (%s queued %d)\n", pkgver_q, ttype_q);
continue;
}
/*
* Pass 3: check if required dependency has been already added
* in the transaction dictionary.
*/
if ((curpkgd = xbps_find_pkg_in_array(pkgs, reqpkg, 0)) ||
(curpkgd = xbps_find_virtualpkg_in_array(xhp, pkgs, reqpkg, 0))) {
Expand All @@ -195,7 +207,7 @@ repo_deps(struct xbps_handle *xhp,
}
}
/*
* Pass 3: check if required dependency is already installed
* Pass 4: check if required dependency is already installed
* and its version is fully matched.
*/
if ((curpkgd = xbps_pkgdb_get_pkg(xhp, pkgname)) == NULL) {
Expand Down Expand Up @@ -341,7 +353,7 @@ repo_deps(struct xbps_handle *xhp,
continue;
}
/*
* Pass 4: find required dependency in repository pool.
* Pass 5: find required dependency in repository pool.
* If dependency does not match add pkg into the missing
* deps array and pass to next one.
*/
Expand Down Expand Up @@ -431,6 +443,10 @@ repo_deps(struct xbps_handle *xhp,
if (error)
break;
}

if (!xbps_array_add(queued, repopkgd))
return -xbps_error_oom();

pkg_rdeps = xbps_dictionary_get(repopkgd, "run_depends");
if (xbps_array_count(pkg_rdeps)) {
/*
Expand All @@ -444,7 +460,7 @@ repo_deps(struct xbps_handle *xhp,
xbps_dbg_printf_append("%s: finding dependencies:\n", pkgver_q);
}
(*depth)++;
rv = repo_deps(xhp, pkgs, repopkgd, depth);
rv = repo_deps(xhp, pkgs, queued, repopkgd, depth);
if (rv != 0) {
xbps_dbg_printf("Error checking %s for rundeps: %s\n", reqpkg, strerror(rv));
break;
Expand All @@ -455,6 +471,9 @@ repo_deps(struct xbps_handle *xhp,
} else if (xbps_dictionary_get(curpkgd, "hold")) {
ttype = XBPS_TRANS_HOLD;
}

xbps_array_remove(queued, xbps_array_count(queued) - 1);

/*
* All deps were processed, store pkg in transaction.
*/
Expand Down Expand Up @@ -483,16 +502,27 @@ xbps_transaction_pkg_deps(struct xbps_handle *xhp,
{
const char *pkgver;
unsigned short depth = 0;
xbps_array_t queued;
int rv;

assert(xhp);
assert(pkgs);
assert(pkg_repod);

xbps_dictionary_get_cstring_nocopy(pkg_repod, "pkgver", &pkgver);
queued = xbps_array_create();
if (!queued)
return -xbps_error_oom();

if (!xbps_dictionary_get_cstring_nocopy(pkg_repod, "pkgver", &pkgver))
return EINVAL;

xbps_dbg_printf("Finding required dependencies for '%s':\n", pkgver);

/*
* This will find direct and indirect deps, if any of them is not
* there it will be added into the missing_deps array.
*/
return repo_deps(xhp, pkgs, pkg_repod, &depth);
rv = repo_deps(xhp, pkgs, queued, pkg_repod, &depth);
xbps_object_release(queued);
return rv;
}
219 changes: 207 additions & 12 deletions tests/xbps/libxbps/shell/cyclic_deps_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -36,22 +36,42 @@ cyclic_dep_vpkg2_head() {
}

cyclic_dep_vpkg2_body() {
mkdir some_repo
mkdir -p pkg_A/usr/bin pkg_B/usr/bin pkg_C/usr/bin pkg_D/usr/bin
mkdir -p some_repo pkg_A/usr/bin pkg_B/usr/bin pkg_C/usr/bin pkg_D/usr/bin

cd some_repo
xbps-create -A noarch -n A-1.0_1 -s "A pkg" --provides "libGL-7.11_1" --dependencies "xserver-abi-video<20" ../pkg_A
atf_check_equal $? 0
xbps-create -A noarch -n B-1.0_1 -s "B pkg" --dependencies "libGL>=7.11" --provides "xserver-abi-video-19_1" ../pkg_B
atf_check_equal $? 0
xbps-create -A noarch -n C-1.0_1 -s "C pkg" --dependencies "libGL>=7.11" ../pkg_C
atf_check_equal $? 0
atf_check -o ignore -- xbps-create -A noarch -n A-1.0_1 -s "A pkg" --provides "libGL-7.11_1" --dependencies "xserver-abi-video<20" ../pkg_A
atf_check -o ignore -- xbps-create -A noarch -n B-1.0_1 -s "B pkg" --dependencies "libGL>=7.11" --provides "xserver-abi-video-19_1" ../pkg_B
atf_check -o ignore -- xbps-create -A noarch -n C-1.0_1 -s "C pkg" --dependencies "libGL>=7.11" ../pkg_C
atf_check -o ignore -e ignore -- xbps-rindex -d -a $PWD/*.xbps
cd ..

xbps-rindex -d -a $PWD/*.xbps
atf_check_equal $? 0
atf_check \
-o match:"A-1\.0_1 install" \
-o match:"B-1\.0_1 install" \
-o match:"C-1\.0_1 install" \
-- xbps-install -r root --repository=$PWD/some_repo -ny C
}

atf_test_case cyclic_dep_vpkg3

cyclic_dep_vpkg3_head() {
atf_set "descr" "Tests for cyclic deps: unresolvable circular dependencies"
}

cyclic_dep_vpkg3_body() {
mkdir -p some_repo pkg_A/usr/bin pkg_B/usr/bin pkg_C/usr/bin pkg_D/usr/bin

cd some_repo
atf_check -o ignore -- xbps-create -A noarch -n A-1.0_1 -s "A pkg" --provides "libGL-7.11_1" --dependencies "xserver-abi-video<20" ../pkg_A
atf_check -o ignore -- xbps-create -A noarch -n B-1.0_1 -s "B pkg" --dependencies "libGL>=7.11" --provides "xserver-abi-video-21_1" ../pkg_B
atf_check -o ignore -- xbps-create -A noarch -n C-1.0_1 -s "C pkg" --dependencies "libGL>=7.11" ../pkg_C
atf_check -o ignore -e ignore -- xbps-rindex -d -a $PWD/*.xbps
cd ..

xbps-install -r root --repository=$PWD/some_repo -dy C
atf_check_equal $? 40
atf_check \
-s exit:19 \
-e match:"MISSING: xserver-abi-video<20" \
-- xbps-install -r root --repository=$PWD/some_repo -ny C
}

atf_test_case cyclic_dep_full
Expand Down Expand Up @@ -81,8 +101,183 @@ cyclic_dep_full_body() {
atf_check_equal $? 0
}


atf_test_case cyclic_dep_of_dep

cyclic_dep_of_dep_head() {
atf_set "descr" "Tests for cyclic deps: installing cylic deps directly and indirectly"
}

cyclic_dep_of_dep_body() {
mkdir repo pkg

cd repo
atf_check -o ignore -- xbps-create -A noarch -n base-system-1.0_1 -s "base-system" --dependencies "systemd>=0" ../pkg
atf_check -o ignore -- xbps-create -A noarch -n systemd-1.0_1 -s "systemd" --dependencies "systemd-libudev>=0 systemd-analyze>=0" ../pkg
atf_check -o ignore -- xbps-create -A noarch -n systemd-libudev-1.0_1 -s "systemd-libudev" ../pkg
atf_check -o ignore -- xbps-create -A noarch -n systemd-analyze-1.0_1 -s "systemd-analyze" --dependencies "systemd>=1.0_1" ../pkg
atf_check -o ignore -e ignore -- xbps-rindex -a *.xbps
cd ..

atf_check \
-o match:"systemd-libudev-1\.0_1 install" \
-o match:"systemd-analyze-1\.0_1 install" \
-o match:"systemd-1\.0_1 install" \
-- xbps-install -r root -R repo -n systemd

atf_check \
-o match:"base-system-1\.0_1 install" \
-o match:"systemd-libudev-1\.0_1 install" \
-o match:"systemd-analyze-1\.0_1 install" \
-o match:"systemd-1\.0_1 install" \
-- xbps-install -r root -R repo -n base-system
}

atf_test_case cyclic_dep_update

cyclic_dep_update_head() {
atf_set "descr" "Tests for cyclic deps: test cylic deps during updates"
}

cyclic_dep_update_body() {
mkdir repo pkg

cd repo
atf_check -o ignore -- xbps-create -A noarch -n base-system-1.0_1 -s "base-system" --dependencies "systemd>=0" ../pkg
atf_check -o ignore -- xbps-create -A noarch -n systemd-1.0_1 -s "systemd" ../pkg
atf_check -o ignore -e ignore -- xbps-rindex -a *.xbps
cd ..

atf_check \
-o match:"systemd-1\.0_1: installed successfully" \
-o match:"base-system-1\.0_1: installed successfully" \
-- xbps-install -r root -R repo -y base-system

cd repo
atf_check -o ignore -- xbps-create -A noarch -n base-system-2.0_1 -s "base-system" --dependencies "systemd>=0" ../pkg
atf_check -o ignore -- xbps-create -A noarch -n systemd-2.0_1 -s "systemd" --dependencies "systemd-libudev>=0 systemd-analyze>=0" ../pkg
atf_check -o ignore -- xbps-create -A noarch -n systemd-libudev-2.0_1 -s "systemd-libudev" ../pkg
atf_check -o ignore -- xbps-create -A noarch -n systemd-analyze-2.0_1 -s "systemd-analyze" --dependencies "systemd>=2.0_1" ../pkg
atf_check -o ignore -e ignore -- xbps-rindex -a *.xbps
cd ..

atf_check \
-o match:"base-system-2\.0_1 update" \
-- xbps-install -r root -R repo -n -u base-system

atf_check \
-o match:"systemd-libudev-2\.0_1 install" \
-o match:"systemd-analyze-2\.0_1 install" \
-o match:"systemd-2\.0_1 update" \
-- xbps-install -r root -R repo -n -u systemd
# XXX: xbps automatically updates revdeps...
# -o not-match:"base-system-2\.0_1 update"

atf_check \
-o match:"base-system-2\.0_1 update" \
-o match:"systemd-libudev-2\.0_1 install" \
-o match:"systemd-analyze-2\.0_1 install" \
-o match:"systemd-2\.0_1 update" \
-- xbps-install -r root -R repo -n -u

cd repo
atf_check -o ignore -- xbps-create -A noarch -n base-system-3.0_1 -s "base-system" --dependencies "systemd>=2" ../pkg
atf_check -o ignore -e ignore -- xbps-rindex -a *.xbps
cd ..

atf_check \
-o match:"base-system-3\.0_1 update" \
-o match:"systemd-libudev-2\.0_1 install" \
-o match:"systemd-analyze-2\.0_1 install" \
-o match:"systemd-2\.0_1 update" \
-- xbps-install -r root -R repo -n -u base-system

atf_check \
-o match:"systemd-libudev-2\.0_1 install" \
-o match:"systemd-analyze-2\.0_1 install" \
-o match:"systemd-2\.0_1 update" \
-- xbps-install -r root -R repo -n -u systemd
# XXX: xbps automatically updates revdeps...
# -o not-match:"base-system-3\.0_1 update"

atf_check \
-o match:"base-system-3\.0_1 update" \
-o match:"systemd-libudev-2\.0_1 install" \
-o match:"systemd-analyze-2\.0_1 install" \
-o match:"systemd-2\.0_1 update" \
-- xbps-install -r root -R repo -n -u
}

atf_test_case cyclic_dep_nested

cyclic_dep_nested_head() {
atf_set "descr" "Tests for cyclic deps: nested cyclic deps"
}

cyclic_dep_nested_body() {
mkdir -p repo pkg

cd repo
atf_check -o ignore -- xbps-create -A noarch -n A-1.0_1 -s "A pkg" --dependencies "B>=1" ../pkg
atf_check -o ignore -- xbps-create -A noarch -n B-1.0_1 -s "B pkg" --dependencies "C>=1" ../pkg
atf_check -o ignore -- xbps-create -A noarch -n C-1.0_1 -s "C pkg" --dependencies "A>=1" ../pkg
atf_check -o ignore -- xbps-create -A noarch -n D-1.0_1 -s "D pkg" --dependencies "E>=1" ../pkg
atf_check -o ignore -- xbps-create -A noarch -n E-1.0_1 -s "E pkg" --dependencies "A>=1 D>=1" ../pkg
atf_check -o ignore -- xbps-create -A noarch -n F-1.0_1 -s "F pkg" --dependencies "E>=1" ../pkg
atf_check -o ignore -e ignore -- xbps-rindex -d -a $PWD/*.xbps
cd ..

atf_check \
-o match:"A-1\.0_1 install" \
-o match:"B-1\.0_1 install" \
-o match:"C-1\.0_1 install" \
-- xbps-install -r root -R repo -n -u A
atf_check \
-o match:"C-1\.0_1 install" \
-o match:"B-1\.0_1 install" \
-o match:"A-1\.0_1 install" \
-o match:"E-1\.0_1 install" \
-o match:"D-1\.0_1 install" \
-- xbps-install -r root -R repo -n -u D
atf_check \
-o match:"C-1\.0_1 install" \
-o match:"B-1\.0_1 install" \
-o match:"A-1\.0_1 install" \
-o match:"E-1\.0_1 install" \
-o match:"D-1\.0_1 install" \
-o match:"F-1\.0_1 install" \
-- xbps-install -r root -R repo -n -u F
}

atf_test_case cyclic_dep_incompatible

cyclic_dep_incompatible_head() {
atf_set "descr" "Tests for cyclic deps: incompatible cyclic dep"
}

cyclic_dep_incompatible_body() {
mkdir -p repo pkg

cd repo
atf_check -o ignore -- xbps-create -A noarch -n A-1.0_1 -s "A pkg" --dependencies "B>=1" ../pkg
atf_check -o ignore -- xbps-create -A noarch -n B-1.0_1 -s "B pkg" --dependencies "C>=1" ../pkg
atf_check -o ignore -- xbps-create -A noarch -n C-1.0_1 -s "C pkg" --dependencies "A>=2" ../pkg
atf_check -o ignore -e ignore -- xbps-rindex -d -a $PWD/*.xbps
cd ..

atf_check \
-s exit:19 \
-e match:"MISSING: A>=2" \
-- xbps-install -r root -R repo -n -u A
}

atf_init_test_cases() {
atf_add_test_case cyclic_dep_vpkg
atf_add_test_case cyclic_dep_vpkg2
atf_add_test_case cyclic_dep_vpkg3
atf_add_test_case cyclic_dep_full
atf_add_test_case cyclic_dep_of_dep
atf_add_test_case cyclic_dep_update
atf_add_test_case cyclic_dep_nested
atf_add_test_case cyclic_dep_incompatible
}
Loading