diff --git a/lib/transaction_ops.c b/lib/transaction_ops.c index d4fef601..d1f4b342 100644 --- a/lib/transaction_ops.c +++ b/lib/transaction_ops.c @@ -55,7 +55,7 @@ static int trans_find_pkg(struct xbps_handle *xhp, const char *pkg, bool force) { - xbps_dictionary_t pkg_pkgdb = NULL, pkg_repod = NULL; + xbps_dictionary_t pkg_pkgdb = NULL, pkg_repod = NULL, vpkg_pkgdb = NULL; xbps_object_t obj; xbps_array_t pkgs; pkg_state_t state = 0; @@ -72,8 +72,12 @@ trans_find_pkg(struct xbps_handle *xhp, const char *pkg, bool force) */ if (xbps_pkg_name(buf, sizeof(buf), pkg)) { pkg_pkgdb = xbps_pkgdb_get_pkg(xhp, buf); + if (!pkg_pkgdb) + vpkg_pkgdb = xbps_pkgdb_get_virtualpkg(xhp, buf); } else { pkg_pkgdb = xbps_pkgdb_get_pkg(xhp, pkg); + if (!pkg_pkgdb) + vpkg_pkgdb = xbps_pkgdb_get_virtualpkg(xhp, pkg); } if (xhp->flags & XBPS_FLAG_DOWNLOAD_ONLY) { @@ -81,23 +85,24 @@ trans_find_pkg(struct xbps_handle *xhp, const char *pkg, bool force) ttype = XBPS_TRANS_DOWNLOAD; } - /* - * Find out if the pkg has been found in repository pool. - */ - if (pkg_pkgdb == NULL) { - /* pkg not installed, perform installation */ - ttype = XBPS_TRANS_INSTALL; - if (((pkg_repod = xbps_rpool_get_pkg(xhp, pkg)) == NULL) && - ((pkg_repod = xbps_rpool_get_virtualpkg(xhp, pkg)) == NULL)) { - /* not found */ - return ENOENT; - } - } else { + if (vpkg_pkgdb) { + // virtual package installed, if there is no real package in + // the rpool, we are keeping the virtual package. + pkg_repod = xbps_rpool_get_pkg(xhp, pkg); + if (!pkg_repod) + pkg_pkgdb = vpkg_pkgdb; + } + if (pkg_pkgdb) { + // package already installed if (force) { ttype = XBPS_TRANS_REINSTALL; } else { ttype = XBPS_TRANS_UPDATE; } + if (!xbps_dictionary_get_cstring_nocopy(pkg_pkgdb, "pkgname", &pkgname)) { + xbps_error_printf("missing `pkgname` property\n"); + return EINVAL; + } if (xbps_dictionary_get(pkg_pkgdb, "repolock")) { struct xbps_repo *repo; /* find update from repo */ @@ -107,15 +112,21 @@ trans_find_pkg(struct xbps_handle *xhp, const char *pkg, bool force) /* not found */ return ENOENT; } - pkg_repod = xbps_repo_get_pkg(repo, pkg); + pkg_repod = xbps_repo_get_pkg(repo, pkgname); } else { /* find update from rpool */ - pkg_repod = xbps_rpool_get_pkg(xhp, pkg); - } - if (pkg_repod == NULL) { - /* not found */ - return ENOENT; + pkg_repod = xbps_rpool_get_pkg(xhp, pkgname); } + } else { + ttype = XBPS_TRANS_INSTALL; + pkg_repod = xbps_rpool_get_pkg(xhp, pkg); + if (!pkg_repod) + pkg_repod = xbps_rpool_get_virtualpkg(xhp, pkg); + } + + if (!pkg_repod) { + /* not found */ + return ENOENT; } xbps_dictionary_get_cstring_nocopy(pkg_repod, "pkgver", &repopkgver); @@ -179,6 +190,7 @@ trans_find_pkg(struct xbps_handle *xhp, const char *pkg, bool force) } if (!xbps_dictionary_get_cstring_nocopy(pkg_repod, "pkgname", &pkgname)) { + xbps_error_printf("missing `pkgname` property\n"); return EINVAL; } /* diff --git a/tests/xbps/libxbps/shell/install_test.sh b/tests/xbps/libxbps/shell/install_test.sh index c0fe9a1a..930bcba5 100644 --- a/tests/xbps/libxbps/shell/install_test.sh +++ b/tests/xbps/libxbps/shell/install_test.sh @@ -336,6 +336,53 @@ install_and_update_revdeps_body() { atf_check_equal $(xbps-query -r root -p pkgver D) D-1.0_1 } +atf_test_case install_virtual_already_installed + +install_virtual_already_installed_head() { + atf_set "descr" "Tests for pkg install: do not reinstall an already installed virtual package" +} + +install_virtual_already_installed_body() { + mkdir -p repo1 repo1-dbg repo2 pkg/usr/bin + + cd repo1 + touch ../pkg/usr/bin/A + atf_check -o ignore -e ignore -- xbps-create -A noarch -n A-1.0_1 -s "A pkg" --provides "cmd:A-1.0_1" ../pkg + atf_check -o ignore -- xbps-rindex -a $PWD/*.xbps + cd .. + + atf_check -o match:'A-1\.0_1: installed successfully\.' -- \ + xbps-install -r root -R repo1 -yv A + + atf_check -o not-match:'A-1\.0_1: installed successfully\.' \ + -e inline:"ERROR: Package \`cmd:A' already installed.\n" -- \ + xbps-install -r root -R repo1 -yv cmd:A +} + +atf_test_case install_virtual_already_installed_as_dep + +install_virtual_already_installed_as_dep_head() { + atf_set "descr" "Tests for pkg install: do not reinstall an already installed virtual package as dependency" +} + +install_virtual_already_installed_as_dep_body() { + mkdir -p repo1 pkg_A/usr/bin pkg_B/usr/bin + + cd repo1 + touch ../pkg_A/usr/bin/A + touch ../pkg_B/usr/bin/B + atf_check -o ignore -e ignore -- xbps-create -A noarch -n A-1.0_1 -s "A pkg" --provides "cmd:A-1.0_1" ../pkg_A + atf_check -o ignore -e ignore -- xbps-create -A noarch -n B-1.0_1 -s "B pkg" --dependencies "cmd:A-1.0_1" ../pkg_B + atf_check -o ignore -- xbps-rindex -a $PWD/*.xbps + cd .. + + atf_check -o match:'A-1\.0_1: installed successfully\.' -- \ + xbps-install -r root -R repo1 -yv A + + atf_check -o not-match:'A-1\.0_1: installed successfully\.' -- \ + xbps-install -r root -R repo1 -yv B +} + atf_test_case update_file_timestamps update_file_timestamps_head() { @@ -735,6 +782,8 @@ atf_init_test_cases() { atf_add_test_case install_bestmatch_deps atf_add_test_case install_bestmatch_disabled atf_add_test_case install_and_update_revdeps + atf_add_test_case install_virtual_already_installed + atf_add_test_case install_virtual_already_installed_as_dep atf_add_test_case update_and_install atf_add_test_case update_if_installed atf_add_test_case update_to_empty_pkg diff --git a/tests/xbps/libxbps/shell/replace_test.sh b/tests/xbps/libxbps/shell/replace_test.sh index daa1af22..15f80384 100644 --- a/tests/xbps/libxbps/shell/replace_test.sh +++ b/tests/xbps/libxbps/shell/replace_test.sh @@ -88,23 +88,18 @@ self_replace_body() { echo "A-1.0_1" > pkg_A/usr/bin/foo echo "B-1.0_1" > pkg_B/usr/bin/foo cd some_repo - xbps-create -A noarch -n A-1.0_1 -s "A pkg" ../pkg_A - atf_check_equal $? 0 - xbps-create -A noarch -n B-1.0_1 -s "B pkg" --replaces "A>=0" --provides="A-1.0_1" ../pkg_B - atf_check_equal $? 0 - xbps-rindex -d -a $PWD/*.xbps - atf_check_equal $? 0 + atf_check -o ignore -- xbps-create -A noarch -n A-1.0_1 -s "A pkg" ../pkg_A + atf_check -o ignore -- xbps-create -A noarch -n B-1.0_1 -s "B pkg" --replaces "A>=0" --provides="A-1.0_1" ../pkg_B + atf_check -o ignore -- xbps-rindex -a $PWD/*.xbps cd .. - xbps-install -C xbps.d -r root --repository=$PWD/some_repo -yd A - atf_check_equal $? 0 - xbps-install -C xbps.d -r root --repository=$PWD/some_repo -yd B - atf_check_equal $? 0 - xbps-install -C xbps.d -r root --repository=$PWD/some_repo -yd A - atf_check_equal $? 0 - out=$(xbps-query -C xbps.d -r root -l|awk '{print $2}') - exp="A-1.0_1" - atf_check_equal $out $exp - atf_check_equal $(xbps-query -C xbps.d -r root -p state A) installed + atf_check -o ignore -e ignore -- xbps-install -C xbps.d -r root --repository=$PWD/some_repo -yd A + atf_check -o ignore -e ignore -- xbps-install -C xbps.d -r root --repository=$PWD/some_repo -yd B + atf_check -e ignore \ + -o match:'A-1\.0_1: installed successfully.' \ + -o match:'B-1\.0_1: removed successfully.' \ + -- xbps-install -C xbps.d -r root --repository=$PWD/some_repo -yd A + atf_check -o inline:"A-1.0_1\n" -- xbps-query -C xbps.d -r root -p pkgver A + atf_check -o inline:"installed\n" -- xbps-query -C xbps.d -r root -p state A } atf_test_case replace_vpkg