From 071ec4c21454d951a8e0dffb7e6cd352bc25adb1 Mon Sep 17 00:00:00 2001 From: Oliver Smith Date: Wed, 20 Dec 2017 16:04:28 +0000 Subject: [PATCH] build necessary logic: look at the package with the highest version (#1004) Fixes #955. Previously we did not look through all APKINDEXes while looking for the package with a given name and the highest version. This caused pmbootstrap to build packages even if they are in the binary repo and up to date. --- pmb/parse/apkindex.py | 38 ++++++++++++++++++++---- test/test_parse_apkindex.py | 59 +++++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 6 deletions(-) create mode 100644 test/test_parse_apkindex.py diff --git a/pmb/parse/apkindex.py b/pmb/parse/apkindex.py index 5365f26d..64845cdd 100644 --- a/pmb/parse/apkindex.py +++ b/pmb/parse/apkindex.py @@ -242,18 +242,44 @@ def read_any_index(args, package, arch=None): """ Get information about a single package from any APKINDEX.tar.gz. + We iterate through the index files in the order they are listed in + /etc/apk/repositories (we write that file in pmbootstrap, so we know the + order). That way it is possible to override a package from an upstream + binary repository (pmOS or Alpine) with a package built locally with + pmbootstrap. + + If a package is in multiple APKINDEX files in multiple versions, then the + highest one gets returned (even if it is not in the first APKINDEX we look + at). + :param arch: defaults to native architecture :returns: the same format as read() """ if not arch: arch = args.arch_native - # Return first match + # Iterate over indexes + ret = None + version_last = None for index in pmb.helpers.repo.apkindex_files(args, arch): + # Skip indexes without the package index_data = read(args, package, index, False) - if index_data: - logging.verbose(package + ": found in " + index) - return index_data + if not index_data: + continue - logging.verbose(package + ": no match found in any APKINDEX.tar.gz!") - return None + # Skip lower versions + version = index_data["version"] + if ret and pmb.parse.version.compare(version, version_last) == -1: + logging.verbose(package + ": " + version + " found in " + index + + " (but " + version_last + " is bigger)") + continue + + # Save as result + logging.verbose(package + ": " + version + " found in " + index) + ret = index_data + version_last = version + + # No result log entry + if not ret: + logging.verbose(package + ": no match found in any APKINDEX.tar.gz!") + return ret diff --git a/test/test_parse_apkindex.py b/test/test_parse_apkindex.py new file mode 100644 index 00000000..5d26fdc5 --- /dev/null +++ b/test/test_parse_apkindex.py @@ -0,0 +1,59 @@ +""" +Copyright 2017 Oliver Smith + +This file is part of pmbootstrap. + +pmbootstrap is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +pmbootstrap is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with pmbootstrap. If not, see . +""" + +import os +import pytest +import sys + +# Import from parent directory +sys.path.append(os.path.realpath( + os.path.join(os.path.dirname(__file__) + "/.."))) +import pmb.parse.apkindex +import pmb.helpers.logging +import pmb.helpers.repo + + +@pytest.fixture +def args(tmpdir, request): + import pmb.parse + sys.argv = ["pmbootstrap", "init"] + args = pmb.parse.arguments() + args.log = args.work + "/log_testsuite.txt" + pmb.helpers.logging.init(args) + request.addfinalizer(args.logfd.close) + return args + + +def test_read_any_index_highest_version(args, monkeypatch): + # Return 3 fake "files" for pmb.helpers.repo.apkindex_files() + def return_fake_files(*arguments): + return ["0", "1", "2"] + monkeypatch.setattr(pmb.helpers.repo, "apkindex_files", + return_fake_files) + + # Return fake index data for the "files" + def return_fake_read(args, package, path, must_exist=True): + return {"0": {"pkgname": "test", "version": "2"}, + "1": {"pkgname": "test", "version": "3"}, + "2": {"pkgname": "test", "version": "1"}}[path] + monkeypatch.setattr(pmb.parse.apkindex, "read", return_fake_read) + + # Verify that it picks the highest version + func = pmb.parse.apkindex.read_any_index + assert func(args, "test")["version"] == "3"