diff --git a/NEWS b/NEWS index 3fd1da06..fe8f97a6 100644 --- a/NEWS +++ b/NEWS @@ -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 diff --git a/configure b/configure index 5b4b3ae9..43ef7e74 100755 --- a/configure +++ b/configure @@ -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= diff --git a/lib/transaction_pkg_deps.c b/lib/transaction_pkg_deps.c index 25c3332a..c325731f 100644 --- a/lib/transaction_pkg_deps.c +++ b/lib/transaction_pkg_deps.c @@ -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 */ { @@ -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))) { @@ -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) { @@ -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. */ @@ -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)) { /* @@ -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; @@ -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. */ @@ -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; } diff --git a/tests/xbps/libxbps/shell/cyclic_deps_test.sh b/tests/xbps/libxbps/shell/cyclic_deps_test.sh index 786fedd7..0a1474e9 100644 --- a/tests/xbps/libxbps/shell/cyclic_deps_test.sh +++ b/tests/xbps/libxbps/shell/cyclic_deps_test.sh @@ -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 @@ -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 }