diff --git a/bin/xbps-install/state_cb.c b/bin/xbps-install/state_cb.c index e40ef654..2960bcf3 100644 --- a/bin/xbps-install/state_cb.c +++ b/bin/xbps-install/state_cb.c @@ -158,6 +158,18 @@ state_cb(const struct xbps_state_cb_data *xscd, void *cbdata UNUSED) case XBPS_STATE_UNPACK_FILE_PRESERVED: printf("%s\n", xscd->desc); break; + case XBPS_STATE_OUTOFDATE: + if (!xbps_pkg_name(pkgname, sizeof(pkgname), xscd->arg)) { + abort(); + } + newver = xscd->arg; + pkgd = xbps_pkgdb_get_pkg(xscd->xhp, pkgname); + xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &instver); + fprintf(stderr, "WARNING: The '%s' package is out of date, '%s' is available.\n", instver, newver); + if (xscd->desc) + fprintf(stderr, "%s\n", xscd->desc); + fprintf(stderr, "NOTE: This can be resolved by running `xbps-install -u`\n"); + break; /* errors */ case XBPS_STATE_TRANS_FAIL: case XBPS_STATE_UNPACK_FAIL: diff --git a/bin/xbps-install/transaction.c b/bin/xbps-install/transaction.c index d2fac3b0..58fdace8 100644 --- a/bin/xbps-install/transaction.c +++ b/bin/xbps-install/transaction.c @@ -316,13 +316,6 @@ dist_upgrade(struct xbps_handle *xhp, unsigned int cols, bool yes, bool drun) if (rv == ENOENT) { xbps_error_printf("No packages currently registered.\n"); return 0; - } else if (rv == EBUSY) { - if (drun) { - rv = 0; - } else { - xbps_error_printf("The 'xbps' package must be updated, please run `xbps-install -u xbps`\n"); - return rv; - } } else if (rv == EEXIST) { return 0; } else if (rv == ENOTSUP) { @@ -350,8 +343,6 @@ install_new_pkg(struct xbps_handle *xhp, const char *pkg, bool force) xbps_error_printf("No repositories currently registered!\n"); else if (rv == ENXIO) xbps_error_printf("Package `%s' contains invalid dependencies, exiting.\n", pkg); - else if (rv == EBUSY) - xbps_error_printf("The 'xbps' package must be updated, please run `xbps-install -u xbps`\n"); else if (rv != 0) { xbps_error_printf("Unexpected error: %s\n", strerror(rv)); rv = -1; @@ -375,8 +366,6 @@ update_pkg(struct xbps_handle *xhp, const char *pkg, bool force) xbps_error_printf("No repositories currently registered!\n"); else if (rv == ENXIO) xbps_error_printf("Package `%s' contains invalid dependencies, exiting.\n", pkg); - else if (rv == EBUSY) - xbps_error_printf("The 'xbps' package must be updated, please run `xbps-install -u xbps`\n"); else if (rv != 0) { xbps_error_printf("Unexpected error: %s\n", strerror(rv)); return -1; diff --git a/include/xbps.h.in b/include/xbps.h.in index 226c42a7..deb8eff6 100644 --- a/include/xbps.h.in +++ b/include/xbps.h.in @@ -374,7 +374,8 @@ typedef enum xbps_state { XBPS_STATE_ALTGROUP_REMOVED, XBPS_STATE_ALTGROUP_SWITCHED, XBPS_STATE_ALTGROUP_LINK_ADDED, - XBPS_STATE_ALTGROUP_LINK_REMOVED + XBPS_STATE_ALTGROUP_LINK_REMOVED, + XBPS_STATE_OUTOFDATE } xbps_state_t; /** diff --git a/lib/cb_util.c b/lib/cb_util.c index 35fbaa77..b3ca9e00 100644 --- a/lib/cb_util.c +++ b/lib/cb_util.c @@ -82,6 +82,7 @@ xbps_set_cb_state(struct xbps_handle *xhp, xscd.state = state; xscd.err = err; xscd.arg = arg; + xscd.desc = NULL; if (fmt != NULL) { va_start(va, fmt); retval = vasprintf(&buf, fmt, va); diff --git a/lib/transaction_ops.c b/lib/transaction_ops.c index d4fef601..1ee087c9 100644 --- a/lib/transaction_ops.c +++ b/lib/transaction_ops.c @@ -226,19 +226,18 @@ trans_find_pkg(struct xbps_handle *xhp, const char *pkg, bool force) * Returns 1 if there's an update, 0 if none or -1 on error. */ static int -xbps_autoupdate(struct xbps_handle *xhp) +trans_check_uptodate(struct xbps_handle *xhp, const char *checkpkg, const char **new_pkgver) { - xbps_array_t rdeps; - xbps_dictionary_t pkgd; - const char *pkgver = NULL, *pkgname = NULL; - int rv; + xbps_array_t pkgs; + xbps_dictionary_t pkgd = NULL, pkg_repod = NULL; + const char *pkgver = NULL, *pkgname = NULL, *repopkgver = NULL, *repoloc = NULL; /* * Check if there's a new update for XBPS before starting * another transaction. */ - if (((pkgd = xbps_pkgdb_get_pkg(xhp, "xbps")) == NULL) && - ((pkgd = xbps_pkgdb_get_virtualpkg(xhp, "xbps")) == NULL)) + if (((pkgd = xbps_pkgdb_get_pkg(xhp, checkpkg)) == NULL) && + ((pkgd = xbps_pkgdb_get_virtualpkg(xhp, checkpkg)) == NULL)) return 0; if (!xbps_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver)) { @@ -248,52 +247,59 @@ xbps_autoupdate(struct xbps_handle *xhp) return EINVAL; } - rv = trans_find_pkg(xhp, pkgname, false); - - xbps_dbg_printf("%s: trans_find_pkg xbps: %d\n", __func__, rv); - - if (rv == 0) { - if (xhp->flags & XBPS_FLAG_DOWNLOAD_ONLY) { + if (xbps_dictionary_get(pkgd, "repolock")) { + struct xbps_repo *repo; + /* find update from repo */ + xbps_dictionary_get_cstring_nocopy(pkgd, "repository", &repoloc); + assert(repoloc); + if ((repo = xbps_regget_repo(xhp, repoloc)) == NULL) { + /* not found */ return 0; } - /* a new xbps version is available, check its revdeps */ - rdeps = xbps_pkgdb_get_pkg_revdeps(xhp, "xbps"); - for (unsigned int i = 0; i < xbps_array_count(rdeps); i++) { - const char *curpkgver = NULL; - char curpkgn[XBPS_NAME_SIZE] = {0}; + pkg_repod = xbps_repo_get_pkg(repo, pkgname); + } else { + /* find update from rpool */ + pkg_repod = xbps_rpool_get_pkg(xhp, pkgname); + } + if (pkg_repod == NULL) { + /* not found */ + return 0; + } - xbps_array_get_cstring_nocopy(rdeps, i, &curpkgver); - xbps_dbg_printf("%s: processing revdep %s\n", __func__, curpkgver); + xbps_dictionary_get_cstring_nocopy(pkg_repod, "pkgver", &repopkgver); + + /* + * Compare installed version vs best pkg available in repos + * for pkg updates. + */ + xbps_dictionary_get_cstring_nocopy(pkgd, + "pkgver", &pkgver); + if (xbps_cmpver(repopkgver, pkgver) <= 0 && + !xbps_pkg_reverts(pkg_repod, pkgver)) { + xbps_dictionary_get_cstring_nocopy(pkg_repod, + "repository", &repoloc); + xbps_dbg_printf("%s: [rpool] Skipping `%s' " + "(installed: %s) from repository `%s'\n", + __func__, repopkgver, pkgver, repoloc); + return 0; + } - if (!xbps_pkg_name(curpkgn, sizeof(curpkgn), curpkgver)) { - abort(); - } - rv = trans_find_pkg(xhp, curpkgn, false); - xbps_dbg_printf("%s: trans_find_pkg revdep %s: %d\n", __func__, curpkgver, rv); - if (rv && rv != ENOENT && rv != EEXIST && rv != ENODEV) - return -1; - } - /* - * Set XBPS_FLAG_FORCE_REMOVE_REVDEPS to ignore broken - * reverse dependencies in xbps_transaction_prepare(). - * - * This won't skip revdeps of the xbps pkg, rather other - * packages in rootdir that could be broken indirectly. - * - * A sysup transaction after updating xbps should fix them - * again. - */ - xhp->flags |= XBPS_FLAG_FORCE_REMOVE_REVDEPS; - return 1; - } else if (rv == ENOENT || rv == EEXIST || rv == ENODEV) { - /* no update */ + pkgs = xbps_dictionary_get(xhp->transd, "packages"); + /* + * Find out if package being checked already has a queued + * transaction, in that case ignore it. + */ + if (xbps_find_pkg_in_array(pkgs, repopkgver, 0)) { + xbps_dbg_printf("%s: [update] `%s' already queued in " + "transaction.\n", __func__, repopkgver); return 0; - } else { - /* error */ - return -1; } - return 0; + if (xhp->flags & XBPS_FLAG_DOWNLOAD_ONLY) { + return 0; + } + if (new_pkgver) *new_pkgver = repopkgver; + return 1; } int @@ -305,17 +311,8 @@ xbps_transaction_update_packages(struct xbps_handle *xhp) bool newpkg_found = false; int rv = 0; - rv = xbps_autoupdate(xhp); - switch (rv) { - case 1: - /* xbps needs to be updated, don't allow any other update */ - return EBUSY; - case -1: - /* error */ + if (xbps_pkgdb_init(xhp) != 0) return EINVAL; - default: - break; - } iter = xbps_dictionary_iterator(xhp->pkgdb); assert(iter); @@ -346,6 +343,13 @@ xbps_transaction_update_packages(struct xbps_handle *xhp) } xbps_object_iterator_release(iter); + /* Notify consumer if xbps is out of date */ + { + const char *pkgver = NULL; + if (trans_check_uptodate(xhp, "xbps", &pkgver) == 1) + xbps_set_cb_state(xhp, XBPS_STATE_OUTOFDATE, 0, pkgver, NULL); + } + return newpkg_found ? rv : EEXIST; } @@ -355,22 +359,6 @@ xbps_transaction_update_pkg(struct xbps_handle *xhp, const char *pkg, bool force xbps_array_t rdeps; int rv; - rv = xbps_autoupdate(xhp); - xbps_dbg_printf("%s: xbps_autoupdate %d\n", __func__, rv); - switch (rv) { - case 1: - /* xbps needs to be updated, only allow xbps to be updated */ - if (strcmp(pkg, "xbps")) - return EBUSY; - return 0; - case -1: - /* error */ - return EINVAL; - default: - /* no update */ - break; - } - /* update its reverse dependencies */ rdeps = xbps_pkgdb_get_pkg_revdeps(xhp, pkg); if (xhp->flags & XBPS_FLAG_DOWNLOAD_ONLY) { @@ -397,6 +385,14 @@ xbps_transaction_update_pkg(struct xbps_handle *xhp, const char *pkg, bool force /* add pkg repod */ rv = trans_find_pkg(xhp, pkg, force); xbps_dbg_printf("%s: trans_find_pkg %s: %d\n", __func__, pkg, rv); + + /* Notify consumer if xbps is out of date */ + { + const char *pkgver = NULL; + if (trans_check_uptodate(xhp, "xbps", &pkgver) == 1) + xbps_set_cb_state(xhp, XBPS_STATE_OUTOFDATE, 0, pkgver, NULL); + } + return rv; } @@ -406,21 +402,6 @@ xbps_transaction_install_pkg(struct xbps_handle *xhp, const char *pkg, bool forc xbps_array_t rdeps; int rv; - rv = xbps_autoupdate(xhp); - switch (rv) { - case 1: - /* xbps needs to be updated, only allow xbps to be updated */ - if (strcmp(pkg, "xbps")) - return EBUSY; - return 0; - case -1: - /* error */ - return EINVAL; - default: - /* no update */ - break; - } - /* update its reverse dependencies */ rdeps = xbps_pkgdb_get_pkg_revdeps(xhp, pkg); if (xhp->flags & XBPS_FLAG_DOWNLOAD_ONLY) { @@ -446,6 +427,14 @@ xbps_transaction_install_pkg(struct xbps_handle *xhp, const char *pkg, bool forc } rv = trans_find_pkg(xhp, pkg, force); xbps_dbg_printf("%s: trans_find_pkg %s: %d\n", __func__, pkg, rv); + + /* Notify consumer if xbps is out of date */ + { + const char *pkgver = NULL; + if (trans_check_uptodate(xhp, "xbps", &pkgver) == 1) + xbps_set_cb_state(xhp, XBPS_STATE_OUTOFDATE, 0, pkgver, NULL); + } + return rv; } diff --git a/tests/xbps/libxbps/shell/install_test.sh b/tests/xbps/libxbps/shell/install_test.sh index c0fe9a1a..98b744fb 100644 --- a/tests/xbps/libxbps/shell/install_test.sh +++ b/tests/xbps/libxbps/shell/install_test.sh @@ -484,10 +484,7 @@ update_xbps_body() { cd .. xbps-rindex -d -a repo/*.xbps atf_check_equal $? 0 - out=$(xbps-install -r root --repository=repo -yun) - set -- $out - exp="$1 $2 $3 $4" - atf_check_equal "$exp" "xbps-1.1_1 update noarch $(readlink -f repo)" + atf_check -s exit:0 -o ignore -e match:"^WARNING: The 'xbps-1\.0_1' package is out of date, 'xbps-1\.1_1' is available\.$" -- xbps-install -r root --repository=repo -yn B xbps-install -r root --repository=repo -yu xbps atf_check_equal $? 0 @@ -537,10 +534,7 @@ update_xbps_virtual_body() { cd .. xbps-rindex -d -a repo/*.xbps atf_check_equal $? 0 - out=$(xbps-install -r root --repository=repo -yun) - set -- $out - exp="$1 $2 $3 $4" - atf_check_equal "$exp" "xbps-git-1.1_1 update noarch $(readlink -f repo)" + atf_check -s exit:0 -o ignore -e match:"^WARNING: The 'xbps-git-1\.0_1' package is out of date, 'xbps-git-1\.1_1' is available\.$" -- xbps-install -r root --repository=repo -yn B xbps-install -r root --repository=repo -yu xbps atf_check_equal $? 0 diff --git a/tests/xbps/libxbps/shell/update_itself_test.sh b/tests/xbps/libxbps/shell/update_itself_test.sh index 1045ac3a..8d3c8ae7 100644 --- a/tests/xbps/libxbps/shell/update_itself_test.sh +++ b/tests/xbps/libxbps/shell/update_itself_test.sh @@ -7,17 +7,20 @@ update_xbps_head() { } update_xbps_body() { - mkdir -p repo xbps + mkdir -p repo xbps bar touch xbps/foo + touch bar/bar cd repo xbps-create -A noarch -n xbps-1.0_1 -s "xbps pkg" ../xbps atf_check_equal $? 0 + xbps-create -A noarch -n bar-1.0_1 -s "bar pkg" ../bar + atf_check_equal $? 0 xbps-rindex -d -a $PWD/*.xbps atf_check_equal $? 0 cd .. - xbps-install -r root --repository=$PWD/repo -yd xbps + xbps-install -r root --repository=$PWD/repo -yd xbps bar atf_check_equal $? 0 out=$(xbps-query -r root -p pkgver xbps) @@ -26,13 +29,17 @@ update_xbps_body() { cd repo xbps-create -A noarch -n xbps-1.1_1 -s "xbps pkg" ../xbps atf_check_equal $? 0 - xbps-rindex -d -a $PWD/xbps-1.1_1.noarch.xbps + xbps-create -A noarch -n bar-1.1_1 -s "bar pkg" ../bar + atf_check_equal $? 0 + xbps-rindex -d -a $PWD/*.xbps atf_check_equal $? 0 cd .. - # EBUSY - xbps-install -r root --repository=$PWD/repo -yud - atf_check_equal $? 16 + # Ensure warning is printed + atf_check -s exit:0 -o ignore -e match:"^WARNING: The 'xbps-1\.0_1' package is out of date, 'xbps-1\.1_1' is available\.$" -- xbps-install -r root --repository=$PWD/repo -yd bar + + out=$(xbps-query -r root -p pkgver bar) + atf_check_equal $out bar-1.1_1 out=$(xbps-query -r root -p pkgver xbps) atf_check_equal $out xbps-1.0_1 @@ -51,8 +58,8 @@ update_xbps_with_revdeps_head() { } update_xbps_with_revdeps_body() { - mkdir -p repo xbps xbps-dbg baz - touch xbps/foo xbps-dbg/bar baz/blah + mkdir -p repo xbps xbps-dbg bar baz + touch xbps/foo xbps-dbg/bar bar/sailor baz/blah cd repo xbps-create -A noarch -n xbps-1.0_1 -s "xbps pkg" ../xbps @@ -67,6 +74,8 @@ update_xbps_with_revdeps_body() { cd repo xbps-create -A noarch -n baz-1.0_1 -s "baz pkg" ../baz atf_check_equal $? 0 + xbps-create -A noarch -n bar-1.0_1 -s "bar pkg" ../bar + atf_check_equal $? 0 xbps-create -A noarch -n xbps-dbg-1.0_1 -s "xbps-dbg pkg" --dependencies "xbps-1.0_1" ../xbps-dbg atf_check_equal $? 0 xbps-rindex -d -a $PWD/*.xbps @@ -87,12 +96,11 @@ update_xbps_with_revdeps_body() { atf_check_equal $? 0 cd .. - # first time, xbps must be updated (returns EBUSY) - xbps-install -r root --repository=$PWD/repo -yud - atf_check_equal $? 16 + # first time, warning must be printed + atf_check -s exit:0 -o ignore -e match:"^WARNING: The 'xbps-1\.0_1' package is out of date, 'xbps-1\.1_1' is available\.$" -- xbps-install -r root --repository=$PWD/repo -yd bar - xbps-install -r root --repository=$PWD/repo -yu xbps - atf_check_equal $? 0 + # don't print warning while updating xbps + atf_check -s exit:0 -o ignore -e not-match:"^WARNING: The 'xbps-1\.0_1' package is out of date, 'xbps-1\.1_1' is available\.$" -- xbps-install -r root --repository=$PWD/repo -yu xbps out=$(xbps-query -r root -p pkgver xbps) atf_check_equal $out xbps-1.1_1 @@ -152,11 +160,8 @@ update_xbps_with_uptodate_revdeps_body() { atf_check_equal $? 0 cd .. - xbps-install -r root --repository=$PWD/repo -yud - atf_check_equal $? 16 - - xbps-install -r root --repository=$PWD/repo -yu xbps - atf_check_equal $? 0 + # don't print warning while updating xbps + atf_check -s exit:0 -o ignore -e not-match:"^WARNING: The 'xbps-1\.0_1' package is out of date, 'xbps-1\.1_1' is available\.$" -- xbps-install -r root --repository=$PWD/repo -yu xbps out=$(xbps-query -r root -p pkgver xbps) atf_check_equal $out xbps-1.1_1 @@ -174,6 +179,8 @@ update_xbps_with_indirect_revdeps_head() { update_xbps_with_indirect_revdeps_body() { mkdir -p repo pkg + atf_expect_fail "Integrity checks are no longer bypassed for xbps self-update: https://github.com/void-linux/xbps/pull/597" + cd repo xbps-create -A noarch -n xbps-1.0_1 -s "xbps pkg" --dependencies "libcrypto-1.0_1 cacerts>=0" ../pkg atf_check_equal $? 0