From fba65ad9dad992603eb31e10a7d458318cc573db Mon Sep 17 00:00:00 2001 From: Juan RP Date: Fri, 14 Feb 2020 08:19:55 +0100 Subject: [PATCH] xbps_transaction_store: ensure no multiple versions. This change ensures that no multiple versions of the same pkg are added to the transaction; if a new version of the same package is being added as a dependency, compare stored and current and use the greatest one. This fixes the recent issue seen in the aarch64 builders, where two versions of the same package were added to the transaction. Added a new test case. --- lib/transaction_store.c | 41 ++++++++++++++---- .../xbps/libxbps/shell/incorrect_deps_test.sh | 43 +++++++++++++++++++ 2 files changed, 75 insertions(+), 9 deletions(-) diff --git a/lib/transaction_store.c b/lib/transaction_store.c index 53976e50..ec249f07 100644 --- a/lib/transaction_store.c +++ b/lib/transaction_store.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2014-2015 Juan Romero Pardines. + * Copyright (c) 2014-2020 Juan Romero Pardines. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,14 +34,40 @@ int HIDDEN xbps_transaction_store(struct xbps_handle *xhp, xbps_array_t pkgs, xbps_dictionary_t pkgrd, const char *tract, bool autoinst) { - xbps_dictionary_t pkgd; + xbps_dictionary_t d, pkgd; xbps_array_t replaces; - const char *pkgver, *repo; + const char *pkgver, *curpkgver, *repo; char pkgname[XBPS_NAME_SIZE], *self_replaced; + int rv; - xbps_dictionary_get_cstring_nocopy(pkgrd, "pkgver", &pkgver); - if (xbps_find_pkg_in_array(pkgs, pkgver, NULL)) - return 0; + if (!xbps_dictionary_get_cstring_nocopy(pkgrd, "pkgver", &pkgver)) { + abort(); + } + if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) { + abort(); + } + d = xbps_find_pkg_in_array(pkgs, pkgname, NULL); + if (xbps_object_type(d) == XBPS_TYPE_DICTIONARY) { + /* compare version stored in transaction vs current */ + if (!xbps_dictionary_get_cstring_nocopy(d, "pkgver", &curpkgver)) { + abort(); + } + rv = xbps_cmpver(pkgver, curpkgver); + if (rv == 0 || rv == -1) { + /* same version or stored version greater than current */ + return 0; + } else { + /* + * Current version is greater than stored, + * replace stored with current. + */ + if (!xbps_remove_pkg_from_array_by_pkgver(pkgs, curpkgver)) { + abort(); + } + xbps_dbg_printf(xhp, "[trans] replaced %s with %s\n", + curpkgver, pkgver); + } + } if ((pkgd = xbps_dictionary_copy_mutable(pkgrd)) == NULL) return ENOMEM; @@ -58,9 +84,6 @@ xbps_transaction_store(struct xbps_handle *xhp, xbps_array_t pkgs, if ((replaces = xbps_dictionary_get(pkgd, "replaces")) == NULL) replaces = xbps_array_create(); - if (!xbps_pkg_name(pkgname, sizeof(pkgname), pkgver)) { - abort(); - } self_replaced = xbps_xasprintf("%s>=0", pkgname); xbps_array_add_cstring(replaces, self_replaced); free(self_replaced); diff --git a/tests/xbps/libxbps/shell/incorrect_deps_test.sh b/tests/xbps/libxbps/shell/incorrect_deps_test.sh index addfc911..c6f2f13e 100644 --- a/tests/xbps/libxbps/shell/incorrect_deps_test.sh +++ b/tests/xbps/libxbps/shell/incorrect_deps_test.sh @@ -130,10 +130,53 @@ missing_deps_body() { } +atf_test_case multiple_versions + +multiple_versions_head() { + atf_set "descr" "Test for package deps: two versions of the same pkg in multiple repos" +} + +multiple_versions_body() { + mkdir -p repo repo2 pkg_A/usr/bin pkg/usr/bin + touch pkg_A/usr/bin/foo + cd repo + xbps-create -A noarch -n kconfig-5.66_1 -s "kconfig" ../pkg_A + atf_check_equal $? 0 + xbps-rindex -d -a *.xbps + atf_check_equal $? 0 + cd ../repo2 + xbps-create -A noarch -n kconfigwidgets-1.0_1 -s "kconfigwidgets" --dependencies "kconfig>=5.60_1" ../pkg + atf_check_equal $? 0 + xbps-create -A noarch -n kconfig-5.67_1 -s "kconfig" ../pkg_A + atf_check_equal $? 0 + xbps-create -A noarch -n kconfig-devel-5.67_1 -s "kconfig-devel" --dependencies "kconfig>=5.67_1" ../pkg + atf_check_equal $? 0 + xbps-create -A noarch -n foo-1.0_1 -s "foo" --dependencies "kconfig-devel>=5.67_1" ../pkg + atf_check_equal $? 0 + xbps-rindex -d -a *.xbps + atf_check_equal $? 0 + cd .. + + out=$(xbps-install -r root --repo=repo --repo=repo2 -n kconfigwidgets foo|wc -l) + atf_check_equal $? 0 + atf_check_equal "$out" 4 + + xbps-install -r root --repo=repo --repo=repo2 -yd kconfigwidgets foo + atf_check_equal $? 0 + + xbps-pkgdb -r root -a + atf_check_equal $? 0 + + out=$(xbps-query -r root -l|wc -l) + atf_check_equal $? 0 + atf_check_equal "$out" 4 +} + atf_init_test_cases() { atf_add_test_case incorrect_dep atf_add_test_case incorrect_dep_vpkg atf_add_test_case incorrect_dep_issue45 atf_add_test_case incorrect_dep_dups atf_add_test_case missing_deps + atf_add_test_case multiple_versions }