From c1176447f3733de5bc8ee1775155e4eddaddd43a Mon Sep 17 00:00:00 2001 From: Duncan Overbruck Date: Tue, 30 May 2023 20:38:40 +0200 Subject: [PATCH] lib: fix preservation of install mode for updated dependencies --- lib/transaction_pkg_deps.c | 36 +++--- lib/transaction_store.c | 3 +- tests/xbps/libxbps/shell/installmode_test.sh | 109 +++++++++++++++++++ 3 files changed, 134 insertions(+), 14 deletions(-) diff --git a/lib/transaction_pkg_deps.c b/lib/transaction_pkg_deps.c index 002350e1..ae0602ec 100644 --- a/lib/transaction_pkg_deps.c +++ b/lib/transaction_pkg_deps.c @@ -115,7 +115,7 @@ repo_deps(struct xbps_handle *xhp, unsigned short *depth) /* max recursion depth */ { xbps_array_t pkg_rdeps = NULL, pkg_provides = NULL; - xbps_dictionary_t curpkgd = NULL; + xbps_dictionary_t curpkgd = NULL, repopkgd = NULL; xbps_trans_type_t ttype; pkg_state_t state; xbps_object_t obj; @@ -146,6 +146,7 @@ repo_deps(struct xbps_handle *xhp, while ((obj = xbps_object_iterator_next(iter))) { bool error = false, foundvpkg = false; + bool autoinst = true; ttype = XBPS_TRANS_UNKNOWN; reqpkg = xbps_string_cstring_nocopy(obj); @@ -328,17 +329,17 @@ repo_deps(struct xbps_handle *xhp, xbps_dbg_printf("`%s' is repolocked, looking at single repository.\n", reqpkg); xbps_dictionary_get_cstring_nocopy(curpkgd, "repository", &repourl); if (repourl && (repo = xbps_regget_repo(xhp, repourl))) { - curpkgd = xbps_repo_get_pkg(repo, reqpkg); + repopkgd = xbps_repo_get_pkg(repo, reqpkg); } else { - curpkg = NULL; + repopkgd = NULL; } } else { - curpkgd = xbps_rpool_get_pkg(xhp, reqpkg); - if (!curpkgd) { - curpkgd = xbps_rpool_get_virtualpkg(xhp, reqpkg); + repopkgd = xbps_rpool_get_pkg(xhp, reqpkg); + if (!repopkgd) { + repopkgd = xbps_rpool_get_virtualpkg(xhp, reqpkg); } } - if (curpkgd == NULL) { + if (repopkgd == NULL) { /* pkg not found, there was some error */ if (errno && errno != ENOENT) { xbps_dbg_printf("failed to find pkg for `%s' in rpool: %s\n", reqpkg, strerror(errno)); @@ -360,7 +361,7 @@ repo_deps(struct xbps_handle *xhp, } - xbps_dictionary_get_cstring_nocopy(curpkgd, "pkgver", &pkgver_q); + xbps_dictionary_get_cstring_nocopy(repopkgd, "pkgver", &pkgver_q); if (!xbps_pkg_name(reqpkgname, sizeof(reqpkgname), pkgver_q)) { rv = EINVAL; break; @@ -408,7 +409,7 @@ repo_deps(struct xbps_handle *xhp, if (error) break; } - pkg_rdeps = xbps_dictionary_get(curpkgd, "run_depends"); + pkg_rdeps = xbps_dictionary_get(repopkgd, "run_depends"); if (xbps_array_count(pkg_rdeps)) { /* * Process rundeps for current pkg found in rpool. @@ -421,7 +422,7 @@ repo_deps(struct xbps_handle *xhp, xbps_dbg_printf_append("%s: finding dependencies:\n", pkgver_q); } (*depth)++; - rv = repo_deps(xhp, pkgs, curpkgd, depth); + rv = repo_deps(xhp, pkgs, repopkgd, depth); if (rv != 0) { xbps_dbg_printf("Error checking %s for rundeps: %s\n", reqpkg, strerror(rv)); break; @@ -432,15 +433,24 @@ repo_deps(struct xbps_handle *xhp, } else if (xbps_dictionary_get(curpkgd, "hold")) { ttype = XBPS_TRANS_HOLD; } + if (ttype == XBPS_TRANS_UPDATE || ttype == XBPS_TRANS_CONFIGURE) { + /* + * If the package is already installed preserve the installation mode, + * which is not automatic if automatic-install is not set. + */ + bool pkgd_auto = false; + xbps_dictionary_get_bool(curpkgd, "automatic-install", &pkgd_auto); + autoinst = pkgd_auto; + } /* * All deps were processed, store pkg in transaction. */ - if (!xbps_transaction_pkg_type_set(curpkgd, ttype)) { + if (!xbps_transaction_pkg_type_set(repopkgd, ttype)) { rv = EINVAL; - xbps_dbg_printf("xbps_transaction_store failed for `%s': %s\n", reqpkg, strerror(rv)); + xbps_dbg_printf("xbps_transaction_pkg_type_set failed for `%s': %s\n", reqpkg, strerror(rv)); break; } - if (!xbps_transaction_store(xhp, pkgs, curpkgd, true)) { + if (!xbps_transaction_store(xhp, pkgs, repopkgd, autoinst)) { rv = EINVAL; xbps_dbg_printf("xbps_transaction_store failed for `%s': %s\n", reqpkg, strerror(rv)); break; diff --git a/lib/transaction_store.c b/lib/transaction_store.c index 13e0c24e..89d7c1fc 100644 --- a/lib/transaction_store.c +++ b/lib/transaction_store.c @@ -105,7 +105,8 @@ xbps_transaction_store(struct xbps_handle *xhp, xbps_array_t pkgs, xbps_set_cb_state(xhp, XBPS_STATE_TRANS_ADDPKG, 0, pkgver, "Found %s in repository %s", pkgver, repo); - xbps_dbg_printf("[trans] `%s' stored (%s)\n", pkgver, repo); + xbps_dbg_printf("[trans] `%s' stored%s (%s)\n", pkgver, + autoinst ? " as automatic install" : "", repo); xbps_object_release(pkgd); return true; diff --git a/tests/xbps/libxbps/shell/installmode_test.sh b/tests/xbps/libxbps/shell/installmode_test.sh index 99dd9958..a9e767a3 100644 --- a/tests/xbps/libxbps/shell/installmode_test.sh +++ b/tests/xbps/libxbps/shell/installmode_test.sh @@ -123,9 +123,118 @@ instmode_reinstall_body() { atf_check_equal $out yes } +atf_test_case instmode_dependency_update + +instmode_dependency_update_head() { + atf_set "descr" "Installation mode: preserve on install with dependency update" +} + +instmode_dependency_update_body() { + mkdir some_repo + mkdir -p pkg_A/usr/bin pkg_B/usr/bin + touch -f pkg_A/usr/bin/foo pkg_B/usr/bin/blah + + cd some_repo + xbps-create -A noarch -n A-1.0_1 -s "foo pkg" ../pkg_A + atf_check_equal $? 0 + xbps-rindex -d -a $PWD/*.xbps + atf_check_equal $? 0 + + cd .. + xbps-install -r root -C null.conf --repository=$PWD/some_repo -yd A-1.0_1 + atf_check_equal $? 0 + + cd some_repo + xbps-create -A noarch -n A-1.1_1 -s "foo pkg" ../pkg_A + atf_check_equal $? 0 + xbps-create -A noarch -n B-1.1_1 -s "foo pkg" -D "A>=1.1_1" ../pkg_B + atf_check_equal $? 0 + xbps-rindex -d -a $PWD/*.xbps + atf_check_equal $? 0 + + cd .. + xbps-install -r root -C null.conf --repository=$PWD/some_repo -yd B + atf_check_equal $? 0 + out="$(xbps-query -r root --property=automatic-install A)" + atf_check_equal $out "" +} + +atf_test_case instmode_dependency_update_automatic + +instmode_dependency_update_automatic_head() { + atf_set "descr" "Installation mode: preserve on install with dependency update marked automatic" +} + +instmode_dependency_update_automatic_body() { + mkdir some_repo + mkdir -p pkg_A/usr/bin pkg_B/usr/bin + touch -f pkg_A/usr/bin/foo pkg_B/usr/bin/blah + + cd some_repo + xbps-create -A noarch -n A-1.0_1 -s "foo pkg" ../pkg_A + atf_check_equal $? 0 + xbps-rindex -d -a $PWD/*.xbps + atf_check_equal $? 0 + + cd .. + xbps-install -r root -C null.conf --repository=$PWD/some_repo -Ayd A-1.0_1 + atf_check_equal $? 0 + + cd some_repo + xbps-create -A noarch -n A-1.1_1 -s "foo pkg" ../pkg_A + atf_check_equal $? 0 + xbps-create -A noarch -n B-1.1_1 -s "foo pkg" -D "A>=1.1_1" ../pkg_B + atf_check_equal $? 0 + xbps-rindex -d -a $PWD/*.xbps + atf_check_equal $? 0 + + cd .. + xbps-install -r root -C null.conf --repository=$PWD/some_repo -yd B + atf_check_equal $? 0 + out="$(xbps-query -r root --property=automatic-install A)" + atf_check_equal $out "yes" +} + +atf_test_case instmode_dependency_configure + +instmode_dependency_configure_head() { + atf_set "descr" "Installation mode: preserve on install with dependency configure" +} + +instmode_dependency_configure_body() { + mkdir some_repo + mkdir -p pkg_A/usr/bin pkg_B/usr/bin + touch -f pkg_A/usr/bin/foo pkg_B/usr/bin/blah + + cd some_repo + xbps-create -A noarch -n A-1.0_1 -s "foo pkg" ../pkg_A + atf_check_equal $? 0 + xbps-rindex -d -a $PWD/*.xbps + atf_check_equal $? 0 + + cd .. + xbps-install -r root -C null.conf --repository=$PWD/some_repo -Uyd A-1.0_1 + atf_check_equal $? 0 + + cd some_repo + xbps-create -A noarch -n B-1.1_1 -s "foo pkg" -D "A>=0" ../pkg_B + atf_check_equal $? 0 + xbps-rindex -d -a $PWD/*.xbps + atf_check_equal $? 0 + + cd .. + xbps-install -r root -C null.conf --repository=$PWD/some_repo -yd B + atf_check_equal $? 0 + out="$(xbps-query -r root --property=automatic-install A)" + atf_check_equal $out "" +} + atf_init_test_cases() { atf_add_test_case instmode atf_add_test_case instmode_auto atf_add_test_case instmode_update atf_add_test_case instmode_reinstall + atf_add_test_case instmode_dependency_update + atf_add_test_case instmode_dependency_update_automatic + atf_add_test_case instmode_dependency_configure }