diff --git a/NEWS b/NEWS index 3217db71..00d6fbbc 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,10 @@ xbps-0.42 (???): + * Added a new configuration keyword "bestmatching", which expects "true" or "false" + and disabled by default. If enabled the pkg with the greatest version available + in all registered repositories will be choosen, rather than the first package + matching the expression. This keyword can be set in a configuration file. + * xbps-rindex(8): added -d/--debug option. * utils: the -C/--config option now expects a path to a directory storing diff --git a/data/xbps.conf b/data/xbps.conf index eaf9b267..54010638 100644 --- a/data/xbps.conf +++ b/data/xbps.conf @@ -13,6 +13,12 @@ # Set it to false to disable syslog logging. #syslog=true +# Enable package best matching (disabled by default). If enabled a package with +# the greatest version available in all repositories will be choosen, rather +# than on the firt package matching the expression. +# +#bestmatching=true + ## REPOSITORIES # # The `repository' keyword defines a repository. A complete URL or absolute diff --git a/include/xbps.h.in b/include/xbps.h.in index 614e94e8..a2544b44 100644 --- a/include/xbps.h.in +++ b/include/xbps.h.in @@ -48,7 +48,7 @@ * * This header documents the full API for the XBPS Library. */ -#define XBPS_API_VERSION "20141105" +#define XBPS_API_VERSION "20141107" #ifndef XBPS_VERSION #define XBPS_VERSION "UNSET" @@ -175,6 +175,13 @@ */ #define XBPS_FLAG_DISABLE_SYSLOG 0x00000080 +/** + * @def XBPS_FLAG_BESTMATCH + * Enable pkg best matching when resolving packages. + * Must be set through the xbps_handle::flags member. + */ +#define XBPS_FLAG_BESTMATCH 0x00000100 + /** * @def XBPS_FETCH_CACHECONN * Default (global) limit of cached connections used in libfetch. diff --git a/lib/initend.c b/lib/initend.c index 697c64d5..fc43bcbb 100644 --- a/lib/initend.c +++ b/lib/initend.c @@ -156,7 +156,8 @@ parse_option(char *buf, char **k, char **v) "repository", "virtualpkg", "include", - "preserve" + "preserve", + "bestmatching" }; bool found = false; @@ -263,6 +264,15 @@ parse_file(struct xbps_handle *xhp, const char *cwd, const char *path, bool nest store_vpkg(xhp, path, nlines, v); } else if (strcmp(k, "preserve") == 0) { store_preserved_file(xhp, v); + } else if (strcmp(k, "bestmatching") == 0) { + if (strcasecmp(v, "true") == 0) { + xhp->flags |= XBPS_FLAG_BESTMATCH; + xbps_dbg_printf(xhp, "%s: pkg best matching enabled\n", path); + } else { + xhp->flags &= ~XBPS_FLAG_BESTMATCH; + xbps_dbg_printf(xhp, "%s: pkg best matching disabled\n", path); + } + xbps_dbg_printf(xhp, "%s: enabling pkg best matching\n", path); } /* Avoid double-nested parsing, only allow it once */ if (nested) diff --git a/lib/rpool.c b/lib/rpool.c index 973d29d9..be92b9fe 100644 --- a/lib/rpool.c +++ b/lib/rpool.c @@ -275,6 +275,9 @@ xbps_rpool_get_virtualpkg(struct xbps_handle *xhp, const char *pkg) xbps_dictionary_t xbps_rpool_get_pkg(struct xbps_handle *xhp, const char *pkg) { + if (xhp->flags & XBPS_FLAG_BESTMATCH) + return repo_find_pkg(xhp, pkg, BEST_PKG); + return repo_find_pkg(xhp, pkg, REAL_PKG); } diff --git a/tests/xbps/libxbps/shell/install_test.sh b/tests/xbps/libxbps/shell/install_test.sh index adaa1213..1a25d845 100644 --- a/tests/xbps/libxbps/shell/install_test.sh +++ b/tests/xbps/libxbps/shell/install_test.sh @@ -204,12 +204,103 @@ install_dups_body() { atf_check_equal $out 1 } +atf_test_case install_bestmatch + +install_bestmatch_head() { + atf_set "descr" "Tests for pkg installations: install with bestmatching enabled" +} + +install_bestmatch_body() { + mkdir -p repo repo2 pkg_A/usr/bin + cd repo + xbps-create -A noarch -n A-1.0_1 -s "A pkg" ../pkg_A + atf_check_equal $? 0 + xbps-rindex -d -a $PWD/*.xbps + atf_check_equal $? 0 + cd ../repo2 + xbps-create -A noarch -n A-1.1_1 -s "A pkg" ../pkg_A + xbps-rindex -d -a $PWD/*.xbps + atf_check_equal $? 0 + + cd .. + mkdir -p root/xbps.d + echo "bestmatching=true" > root/xbps.d/bestmatch.conf + xbps-install -C xbps.d -r root --repository=$PWD/repo --repository=$PWD/repo2 -yvd A + atf_check_equal $? 0 + out=$(xbps-query -r root -p pkgver A) + atf_check_equal $out A-1.1_1 +} + +atf_test_case install_bestmatch_deps + +install_bestmatch_deps_head() { + atf_set "descr" "Tests for pkg installations: install with bestmatching enabled for deps" +} + +install_bestmatch_deps_body() { + mkdir -p repo repo2 pkg_A/usr/bin pkg_B/usr/bin + cd 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" --dependencies "A>=0" ../pkg_B + atf_check_equal $? 0 + xbps-rindex -d -a $PWD/*.xbps + atf_check_equal $? 0 + cd ../repo2 + xbps-create -A noarch -n A-1.1_1 -s "A pkg" ../pkg_A + atf_check_equal $? 0 + xbps-create -A noarch -n B-1.1_1 -s "B pkg" --dependencies "A>=0" ../pkg_B + atf_check_equal $? 0 + xbps-rindex -d -a $PWD/*.xbps + atf_check_equal $? 0 + + cd .. + mkdir -p root/xbps.d + echo "bestmatching=true" > root/xbps.d/bestmatch.conf + xbps-install -C xbps.d -r root --repository=$PWD/repo --repository=$PWD/repo2 -yvd B + atf_check_equal $? 0 + out=$(xbps-query -r root -p pkgver A) + atf_check_equal $out A-1.1_1 + out=$(xbps-query -r root -p pkgver B) + atf_check_equal $out B-1.1_1 +} + +atf_test_case install_bestmatch_disabled + +install_bestmatch_disabled_head() { + atf_set "descr" "Tests for pkg installations: install with bestmatching disabled" +} + +install_bestmatch_disabled_body() { + mkdir -p repo repo2 pkg_A/usr/bin + cd repo + xbps-create -A noarch -n A-1.0_1 -s "A pkg" ../pkg_A + atf_check_equal $? 0 + xbps-rindex -d -a $PWD/*.xbps + atf_check_equal $? 0 + cd ../repo2 + xbps-create -A noarch -n A-1.1_1 -s "A pkg" ../pkg_A + xbps-rindex -d -a $PWD/*.xbps + atf_check_equal $? 0 + + cd .. + mkdir -p root/xbps.d + echo "bestmatching=false" > root/xbps.d/bestmatch.conf + xbps-install -C xbps.d -r root --repository=$PWD/repo --repository=$PWD/repo2 -yvd A + atf_check_equal $? 0 + out=$(xbps-query -r root -p pkgver A) + atf_check_equal $out A-1.0_1 +} + atf_init_test_cases() { atf_add_test_case install_empty atf_add_test_case install_with_deps atf_add_test_case install_with_vpkg_deps atf_add_test_case install_if_not_installed_on_update atf_add_test_case install_dups + atf_add_test_case install_bestmatch + atf_add_test_case install_bestmatch_deps + atf_add_test_case install_bestmatch_disabled atf_add_test_case update_if_installed atf_add_test_case update_to_empty_pkg }