From 66037186a4c9ef86d5fcad3136259fdcfae01017 Mon Sep 17 00:00:00 2001 From: Vinicius Moreira Date: Tue, 2 Mar 2021 10:58:46 -0300 Subject: [PATCH] [arch] fixes related to dependency checking --- CHANGELOG.md | 7 +++- bauh/gems/arch/dependencies.py | 65 ++++++++++++++++++++++------------ bauh/gems/arch/util.py | 12 +++++++ tests/gems/arch/test_util.py | 27 ++++++++++++++ 4 files changed, 88 insertions(+), 23 deletions(-) create mode 100644 bauh/gems/arch/util.py create mode 100644 tests/gems/arch/test_util.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 5540b618..c5ae7cfe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Fixes - AppImage - crashing when trying to upgrade and the internet connection is off - + +- Arch + - Upgrading: when an installed package does not meet a dependency expression, it is displayed to be installed (e.g: 'optimus-manager-qt' relies on 'optimus-manager' >= 1.4, but the current provided version is '1.3'. Even so, 'optimus-manager' will be displayed to be installed) + - Not checking the dependency version expression when it is only available on AUR + - Not properly treating a dependency version before comparing with others (could display that a given dependency was not found) + ## [0.9.14] 2021-02-03 ### Improvements diff --git a/bauh/gems/arch/dependencies.py b/bauh/gems/arch/dependencies.py index b611c126..1e8180c0 100644 --- a/bauh/gems/arch/dependencies.py +++ b/bauh/gems/arch/dependencies.py @@ -1,7 +1,7 @@ import re import traceback from threading import Thread -from typing import Set, List, Tuple, Dict, Iterable +from typing import Set, List, Tuple, Dict, Iterable, Optional from packaging.version import parse as parse_version @@ -9,6 +9,7 @@ from bauh.api.abstract.handler import ProcessWatcher from bauh.gems.arch import pacman, message, sorting, confirmation from bauh.gems.arch.aur import AURClient from bauh.gems.arch.exceptions import PackageNotFoundException +from bauh.gems.arch.util import clean_version from bauh.view.util.translation import I18n @@ -204,7 +205,7 @@ class DependenciesAnalyser: if match: providers = {match} - if providers and len(providers) > 1: + if providers: no_mapped_data = {p for p in providers if p not in deps_data} # checking providers with no mapped data @@ -219,7 +220,7 @@ class DependenciesAnalyser: matched_providers = set() split_informed_dep = self.re_dep_operator.split(dep_exp) try: - version_informed = parse_version(split_informed_dep[2]) + version_required = parse_version(clean_version(split_informed_dep[2])) exp_op = split_informed_dep[1] if split_informed_dep[1] != '=' else '==' for p in providers: @@ -229,9 +230,9 @@ class DependenciesAnalyser: split_dep = self.re_dep_operator.split(provided_exp) if len(split_dep) == 3 and split_dep[0] == dep_name: - provided_version = parse_version(split_dep[2]) + version_provided = parse_version(clean_version(split_dep[2])) - if eval('provided_version {} version_informed'.format(exp_op)): + if eval('version_provided {} version_required'.format(exp_op)): matched_providers.add(p) break @@ -259,14 +260,40 @@ class DependenciesAnalyser: missing_deps.add(dep_data) elif aur_index and dep_name in aur_index: - aur_deps.add(dep_name) - missing_deps.add((dep_name, 'aur')) - else: - if watcher: - message.show_dep_not_found(dep_exp, self.i18n, watcher) - raise PackageNotFoundException(dep_exp) + if dep_name == dep_exp: + aur_deps.add(dep_name) + missing_deps.add((dep_name, 'aur')) else: - raise PackageNotFoundException(dep_exp) + dep_info = self.aur_client.get_info({dep_name}) + + if not dep_info: + self.__raise_dependency_not_found(dep_exp, watcher) + else: + try: + dep_version = parse_version(clean_version(dep_info[0]['Version'])) + except: + traceback.print_exc() + self.__raise_dependency_not_found(dep_exp, watcher) + + split_informed_dep = self.re_dep_operator.split(dep_exp) + try: + version_required = parse_version(clean_version(split_informed_dep[2])) + exp_op = split_informed_dep[1] if split_informed_dep[1] != '=' else '==' + + if eval('dep_version {} version_required'.format(exp_op)): + aur_deps.add(dep_name) + missing_deps.add((dep_name, 'aur')) + except: + self.__raise_dependency_not_found(dep_exp, watcher) + else: + self.__raise_dependency_not_found(dep_exp, watcher) + + def __raise_dependency_not_found(self, dep_exp: str, watcher: Optional[ProcessWatcher]): + if watcher: + message.show_dep_not_found(dep_exp, self.i18n, watcher) + raise PackageNotFoundException(dep_exp) + else: + raise PackageNotFoundException(dep_exp) def __fill_aur_update_data(self, pkgname: str, output: dict): output[pkgname] = self.aur_client.map_update_data(pkgname, None) @@ -307,21 +334,15 @@ class DependenciesAnalyser: version_found = [p for p in provided_map if p.startswith(version_pattern)] if version_found: - version_found = version_found[0].split('=')[1] - version_informed = dep_split[2].strip() - - if ':' not in version_informed: - version_found = version_found.split(':')[-1] - - if '-' not in version_informed: - version_found = version_found.split('-')[0] + version_found = clean_version(version_found[0].split('=')[1]) + version_required = clean_version(dep_split[2]) try: version_found = parse_version(version_found) - version_informed = parse_version(version_informed) + version_required = parse_version(version_required) op = dep_split[1] if dep_split[1] != '=' else '==' - match = eval('version_found {} version_informed'.format(op)) + match = eval('version_found {} version_required'.format(op)) except: match = False traceback.print_exc() diff --git a/bauh/gems/arch/util.py b/bauh/gems/arch/util.py new file mode 100644 index 00000000..96edb380 --- /dev/null +++ b/bauh/gems/arch/util.py @@ -0,0 +1,12 @@ +import re + +RE_STRIP_EPIC = re.compile(r'^\d+:') +RE_STRIP_RELEASE = re.compile(r'-[\d\.?]+$') + + +def clean_version(version: str) -> str: + treated_version = version.strip() + if treated_version: + return RE_STRIP_RELEASE.split(RE_STRIP_EPIC.split(treated_version)[-1])[0] + + return treated_version diff --git a/tests/gems/arch/test_util.py b/tests/gems/arch/test_util.py new file mode 100644 index 00000000..55175b82 --- /dev/null +++ b/tests/gems/arch/test_util.py @@ -0,0 +1,27 @@ +from unittest import TestCase + +from bauh.gems.arch.util import clean_version + + +class TestUtil(TestCase): + + def test_clean_version__blank_version(self): + self.assertEqual('', clean_version('')) + + def test_clean_version__blank_version_with_several_spaces(self): + self.assertEqual('', clean_version(' ')) + + def test_clean_version__with_epic(self): + self.assertEqual('12.0.0', clean_version('1:12.0.0')) + + def test_clean_version__with_release(self): + self.assertEqual('12.0.0', clean_version('12.0.0-1')) + + def test_clean_version__with_epic_and_release(self): + self.assertEqual('12.0.0', clean_version('1:12.0.0-2')) + + def test_clean_version__with_several_releases(self): + self.assertEqual('12.0.0-1-2', clean_version('12.0.0-1-2-3')) + + def test_clean_version__(self): + self.assertEqual('29', clean_version('29-1.0'))