mirror of
https://github.com/spalencsar/bearhub.git
synced 2026-07-07 18:34:16 +02:00
[arch] refactoring: conflict resolution checking (+ test cases)
This commit is contained in:
@@ -8,7 +8,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
- Arch
|
- Arch
|
||||||
- not properly mapping all provided packages by the system when checking for upgrade requirements
|
- not properly checking all provided packages by the system when checking for conflicts (upgrade requirements)
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
- Arch
|
||||||
|
- added several test cases to ensure conflicting scenarios are properly covered when checking for upgrade requirements
|
||||||
|
|
||||||
## [0.10.4] 2022-11-05
|
## [0.10.4] 2022-11-05
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ class SearchResult:
|
|||||||
|
|
||||||
class UpgradeRequirement:
|
class UpgradeRequirement:
|
||||||
|
|
||||||
def __init__(self, pkg: SoftwarePackage, reason: str = None, required_size: float = None, extra_size: float = None, sorting_priority: int = 0):
|
def __init__(self, pkg: SoftwarePackage, reason: Optional[str] = None, required_size: Optional[float] = None, extra_size: Optional[float] = None, sorting_priority: int = 0):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
:param pkg:
|
:param pkg:
|
||||||
@@ -77,6 +77,15 @@ class UpgradeRequirement:
|
|||||||
def sort_by_priority(req: "UpgradeRequirement") -> Tuple[int, str]:
|
def sort_by_priority(req: "UpgradeRequirement") -> Tuple[int, str]:
|
||||||
return -req.sorting_priority, req.pkg.name
|
return -req.sorting_priority, req.pkg.name
|
||||||
|
|
||||||
|
def __eq__(self, other) -> bool:
|
||||||
|
if isinstance(other, UpgradeRequirement):
|
||||||
|
return self.__dict__ == other.__dict__
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def __hash__(self) -> int:
|
||||||
|
return sum((hash(k) + hash(v) for k, v in self.__dict__.items()))
|
||||||
|
|
||||||
|
|
||||||
class UpgradeRequirements:
|
class UpgradeRequirements:
|
||||||
|
|
||||||
|
|||||||
@@ -464,9 +464,9 @@ class DependenciesAnalyser:
|
|||||||
if missing_deps:
|
if missing_deps:
|
||||||
self._fill_single_providers_data(missing_deps, repo_missing, aur_missing, deps_data)
|
self._fill_single_providers_data(missing_deps, repo_missing, aur_missing, deps_data)
|
||||||
|
|
||||||
missing_subdeps = self.map_missing_deps(pkgs_data={**deps_data}, provided_map=provided_map, aur_index=aur_index,
|
missing_subdeps = self.map_missing_deps(pkgs_data={**deps_data}, provided_map=provided_map,
|
||||||
deps_checked=deps_checked, sort=False, deps_data=deps_data,
|
aur_index=aur_index, deps_checked=deps_checked, sort=False,
|
||||||
watcher=watcher,
|
deps_data=deps_data, watcher=watcher,
|
||||||
remote_provided_map=remote_provided_map,
|
remote_provided_map=remote_provided_map,
|
||||||
remote_repo_map=remote_repo_map,
|
remote_repo_map=remote_repo_map,
|
||||||
automatch_providers=automatch_providers,
|
automatch_providers=automatch_providers,
|
||||||
@@ -650,7 +650,7 @@ class DependenciesAnalyser:
|
|||||||
if pkgnames:
|
if pkgnames:
|
||||||
to_ignore.update(pkgnames)
|
to_ignore.update(pkgnames)
|
||||||
|
|
||||||
all_requirements = {req for reqs in pacman.map_required_by(pkgnames).values() for req in reqs if req not in to_ignore}
|
all_requirements = {r for reqs in pacman.map_required_by(pkgnames).values() for r in reqs if r not in to_ignore}
|
||||||
|
|
||||||
if all_requirements:
|
if all_requirements:
|
||||||
sub_requirements = self.map_all_required_by(all_requirements, to_ignore)
|
sub_requirements = self.map_all_required_by(all_requirements, to_ignore)
|
||||||
|
|||||||
@@ -396,7 +396,7 @@ def get_version_for_not_installed(pkgname: str) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def map_repositories(pkgnames: Iterable[str] = None) -> Dict[str, str]:
|
def map_repositories(pkgnames: Iterable[str] = None) -> Dict[str, str]:
|
||||||
info = run_cmd('pacman -Si {}'.format(' '.join(pkgnames) if pkgnames else ''), print_error=False, ignore_return_code=True)
|
info = run_cmd(f"pacman -Si {' '.join(pkgnames) if pkgnames else ''}", print_error=False, ignore_return_code=True)
|
||||||
if info:
|
if info:
|
||||||
repos = re.findall(r'(Name|Repository)\s*:\s*(.+)', info)
|
repos = re.findall(r'(Name|Repository)\s*:\s*(.+)', info)
|
||||||
|
|
||||||
@@ -529,7 +529,7 @@ def upgrade_system(root_password: Optional[str]) -> SimpleProcess:
|
|||||||
return SimpleProcess(cmd=['pacman', '-Syyu', '--noconfirm'], root_password=root_password)
|
return SimpleProcess(cmd=['pacman', '-Syyu', '--noconfirm'], root_password=root_password)
|
||||||
|
|
||||||
|
|
||||||
def fill_provided_map(key: str, val: str, output: dict):
|
def _fill_provided_map(key: str, val: str, output: Dict[str, Set[str]]):
|
||||||
current_val = output.get(key)
|
current_val = output.get(key)
|
||||||
|
|
||||||
if current_val is None:
|
if current_val is None:
|
||||||
@@ -558,19 +558,19 @@ def map_provided(remote: bool = False, pkgs: Iterable[str] = None) -> Optional[D
|
|||||||
elif field == 'Version':
|
elif field == 'Version':
|
||||||
latest_version = val.split('=')[0]
|
latest_version = val.split('=')[0]
|
||||||
elif field == 'Provides':
|
elif field == 'Provides':
|
||||||
fill_provided_map(latest_name, latest_name, provided_map)
|
_fill_provided_map(latest_name, latest_name, provided_map)
|
||||||
fill_provided_map(f'{latest_name}={latest_version}', latest_name, provided_map)
|
_fill_provided_map(f'{latest_name}={latest_version}', latest_name, provided_map)
|
||||||
|
|
||||||
if val != 'None':
|
if val != 'None':
|
||||||
for w in val.split(' '):
|
for w in val.split(' '):
|
||||||
if w:
|
if w:
|
||||||
word = w.strip()
|
word = w.strip()
|
||||||
fill_provided_map(word, latest_name, provided_map)
|
_fill_provided_map(word, latest_name, provided_map)
|
||||||
|
|
||||||
word_split = word.split('=')
|
word_split = word.split('=')
|
||||||
|
|
||||||
if word_split[0] != word:
|
if word_split[0] != word:
|
||||||
fill_provided_map(word_split[0], latest_name, provided_map)
|
_fill_provided_map(word_split[0], latest_name, provided_map)
|
||||||
else:
|
else:
|
||||||
provided = True
|
provided = True
|
||||||
|
|
||||||
@@ -583,12 +583,12 @@ def map_provided(remote: bool = False, pkgs: Iterable[str] = None) -> Optional[D
|
|||||||
for w in l.split(' '):
|
for w in l.split(' '):
|
||||||
if w:
|
if w:
|
||||||
word = w.strip()
|
word = w.strip()
|
||||||
fill_provided_map(word, latest_name, provided_map)
|
_fill_provided_map(word, latest_name, provided_map)
|
||||||
|
|
||||||
word_split = word.split('=')
|
word_split = word.split('=')
|
||||||
|
|
||||||
if word_split[0] != word:
|
if word_split[0] != word:
|
||||||
fill_provided_map(word_split[0], latest_name, provided_map)
|
_fill_provided_map(word_split[0], latest_name, provided_map)
|
||||||
|
|
||||||
return provided_map
|
return provided_map
|
||||||
|
|
||||||
@@ -857,7 +857,8 @@ def get_cache_dir() -> str:
|
|||||||
|
|
||||||
|
|
||||||
def map_required_by(names: Iterable[str] = None, remote: bool = False) -> Dict[str, Set[str]]:
|
def map_required_by(names: Iterable[str] = None, remote: bool = False) -> Dict[str, Set[str]]:
|
||||||
output = run_cmd('pacman -{} {}'.format('Sii' if remote else 'Qi', ' '.join(names) if names else ''), print_error=False)
|
output = run_cmd(f"pacman -{'Sii' if remote else 'Qi'} {' '.join(names) if names else ''}".strip(),
|
||||||
|
print_error=False)
|
||||||
|
|
||||||
if output:
|
if output:
|
||||||
latest_name, required = None, None
|
latest_name, required = None, None
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import logging
|
|||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from typing import Dict, Set, List, Tuple, Iterable, Optional
|
from typing import Dict, Set, List, Tuple, Iterable, Optional, Any
|
||||||
|
|
||||||
from bauh.api.abstract.controller import UpgradeRequirements, UpgradeRequirement
|
from bauh.api.abstract.controller import UpgradeRequirements, UpgradeRequirement
|
||||||
from bauh.api.abstract.handler import ProcessWatcher
|
from bauh.api.abstract.handler import ProcessWatcher
|
||||||
@@ -47,12 +47,26 @@ class UpdateRequirementsContext:
|
|||||||
if self.provided_map is None:
|
if self.provided_map is None:
|
||||||
self.provided_map = {**update}
|
self.provided_map = {**update}
|
||||||
else:
|
else:
|
||||||
for key, val in update.items():
|
for provider, provided in update.items():
|
||||||
if key not in self.provided_map:
|
provided_set = self.provided_map.get(provider)
|
||||||
self.provided_map[key] = val
|
|
||||||
elif val:
|
if provided_set is None:
|
||||||
current_val = self.provided_map[key]
|
provided_set = set()
|
||||||
current_val.update(val)
|
self.provided_map[provider] = provided_set
|
||||||
|
|
||||||
|
provided_set.update(provided)
|
||||||
|
|
||||||
|
def add_to_provided_map(self, provider: str, provided: str):
|
||||||
|
if self.provided_map is None:
|
||||||
|
self.provided_map = dict()
|
||||||
|
|
||||||
|
provided_set = self.provided_map.get(provider)
|
||||||
|
|
||||||
|
if provided_set is None:
|
||||||
|
provided_set = set()
|
||||||
|
self.provided_map[provider] = provided_set
|
||||||
|
|
||||||
|
provided_set.add(provided)
|
||||||
|
|
||||||
|
|
||||||
class UpdatesSummarizer:
|
class UpdatesSummarizer:
|
||||||
@@ -72,8 +86,7 @@ class UpdatesSummarizer:
|
|||||||
for src_pkg in {p for p, data in context.pkgs_data.items() if
|
for src_pkg in {p for p, data in context.pkgs_data.items() if
|
||||||
data['d'] and pkg1 in data['d'] or pkg2 in data['d']}:
|
data['d'] and pkg1 in data['d'] or pkg2 in data['d']}:
|
||||||
if src_pkg not in context.cannot_upgrade:
|
if src_pkg not in context.cannot_upgrade:
|
||||||
reason = self.i18n['arch.update_summary.to_install.dep_conflict'].format("'{}'".format(pkg1),
|
reason = self.i18n['arch.update_summary.to_install.dep_conflict'].format(f"'{pkg1}'", f"'{pkg2}'")
|
||||||
"'{}'".format(pkg2))
|
|
||||||
context.cannot_upgrade[src_pkg] = UpgradeRequirement(context.to_update[src_pkg], reason)
|
context.cannot_upgrade[src_pkg] = UpgradeRequirement(context.to_update[src_pkg], reason)
|
||||||
|
|
||||||
del context.to_update[src_pkg]
|
del context.to_update[src_pkg]
|
||||||
@@ -137,11 +150,11 @@ class UpdatesSummarizer:
|
|||||||
|
|
||||||
def _handle_conflict_both_to_update(self, pkg1: str, pkg2: str, context: UpdateRequirementsContext):
|
def _handle_conflict_both_to_update(self, pkg1: str, pkg2: str, context: UpdateRequirementsContext):
|
||||||
if pkg1 not in context.cannot_upgrade:
|
if pkg1 not in context.cannot_upgrade:
|
||||||
reason = "{} '{}'".format(self.i18n['arch.info.conflicts with'].capitalize(), pkg2)
|
reason = f"{self.i18n['arch.info.conflicts with'].capitalize()} '{pkg2}'"
|
||||||
context.cannot_upgrade[pkg1] = UpgradeRequirement(pkg=context.to_update[pkg1], reason=reason)
|
context.cannot_upgrade[pkg1] = UpgradeRequirement(pkg=context.to_update[pkg1], reason=reason)
|
||||||
|
|
||||||
if pkg2 not in context.cannot_upgrade:
|
if pkg2 not in context.cannot_upgrade:
|
||||||
reason = "{} '{}'".format(self.i18n['arch.info.conflicts with'].capitalize(), pkg1)
|
reason = f"{self.i18n['arch.info.conflicts with'].capitalize()} '{pkg1}'"
|
||||||
context.cannot_upgrade[pkg2] = UpgradeRequirement(pkg=context.to_update[pkg2], reason=reason)
|
context.cannot_upgrade[pkg2] = UpgradeRequirement(pkg=context.to_update[pkg2], reason=reason)
|
||||||
|
|
||||||
for p in (pkg1, pkg2):
|
for p in (pkg1, pkg2):
|
||||||
@@ -153,65 +166,101 @@ class UpdatesSummarizer:
|
|||||||
else:
|
else:
|
||||||
del context.aur_to_update[p]
|
del context.aur_to_update[p]
|
||||||
|
|
||||||
def _filter_and_map_conflicts(self, context: UpdateRequirementsContext) -> Dict[str, str]:
|
def _map_conflicts(self, data: Dict[str, Dict[str, Any]], providers: Dict[str, Set[str]],
|
||||||
|
versions: Dict[str, str]) -> Tuple[Dict[str, str], Dict[str, str]]:
|
||||||
|
"""
|
||||||
|
Parameters
|
||||||
|
pkgs_data: a dict mapping the packages whose conflicts need to be analyzed to their data
|
||||||
|
providers: a dict mapping the available providers on the context (installed and to be installed) to their
|
||||||
|
respective package
|
||||||
|
versions: a dict mapping the package name to it's version (the updated or to be installed version)
|
||||||
|
Return
|
||||||
|
a tuple with two dictionaries:
|
||||||
|
- first: containing all conflicts
|
||||||
|
- second: containing mutual conflicts
|
||||||
|
"""
|
||||||
root_conflict = {}
|
root_conflict = {}
|
||||||
mutual_conflicts = {}
|
mutual_conflicts = {}
|
||||||
|
|
||||||
for p, data in context.pkgs_data.items():
|
for pkg_name, data in data.items():
|
||||||
if data['c']:
|
if data['c']:
|
||||||
for c in data['c']:
|
for c in data['c']:
|
||||||
if c:
|
if c:
|
||||||
name_op_exp = DependenciesAnalyser.re_dep_operator().split(c)
|
name_op_exp = DependenciesAnalyser.re_dep_operator().split(c)
|
||||||
conflict_name = name_op_exp[0]
|
conflict_name = name_op_exp[0]
|
||||||
|
|
||||||
if conflict_name != p:
|
if conflict_name != pkg_name:
|
||||||
conflict_version = context.installed.get(conflict_name)
|
conflict_providers = providers.get(conflict_name)
|
||||||
|
|
||||||
if conflict_version:
|
if conflict_providers:
|
||||||
if len(name_op_exp) == 1 or match_required_version(conflict_version,
|
checked_conflicts = []
|
||||||
name_op_exp[1],
|
for provider in conflict_providers:
|
||||||
name_op_exp[2]):
|
if provider != pkg_name:
|
||||||
root_conflict[conflict_name] = p
|
if len(name_op_exp) == 1:
|
||||||
|
checked_conflicts.append(provider)
|
||||||
|
else:
|
||||||
|
provider_version = versions.get(provider)
|
||||||
|
|
||||||
if (p, conflict_name) in root_conflict.items():
|
if match_required_version(provider_version,
|
||||||
mutual_conflicts[conflict_name] = p
|
name_op_exp[1],
|
||||||
|
name_op_exp[2]):
|
||||||
|
checked_conflicts.append(provider)
|
||||||
|
|
||||||
if mutual_conflicts:
|
for provider in checked_conflicts:
|
||||||
for pkg1, pkg2 in mutual_conflicts.items():
|
root_conflict[provider] = pkg_name
|
||||||
pkg1_to_install = pkg1 in context.to_install
|
|
||||||
pkg2_to_install = pkg2 in context.to_install
|
|
||||||
|
|
||||||
if pkg1_to_install and pkg2_to_install: # remove both from to install and mark their source packages as 'cannot_update'
|
if (pkg_name, provider) in root_conflict.items():
|
||||||
self._handle_conflict_both_to_install(pkg1, pkg2, context)
|
mutual_conflicts[provider] = pkg_name
|
||||||
elif (pkg1_to_install and not pkg2_to_install) or (not pkg1_to_install and pkg2_to_install):
|
|
||||||
self._handle_conflict_to_update_and_to_install(pkg1, pkg2, pkg1_to_install, context)
|
|
||||||
else:
|
|
||||||
self._handle_conflict_both_to_update(pkg1, pkg2, context) # adding both to the 'cannot update' list
|
|
||||||
|
|
||||||
for pkg1, pkg2 in mutual_conflicts.items(): # removing conflicting packages from the packages selected to upgrade
|
return root_conflict, mutual_conflicts
|
||||||
for p in (pkg1, pkg2):
|
|
||||||
if p in context.pkgs_data:
|
|
||||||
if context.pkgs_data[p].get('c'):
|
|
||||||
for c in context.pkgs_data[p]['c']:
|
|
||||||
# source = provided_map[c]
|
|
||||||
if c in root_conflict:
|
|
||||||
del root_conflict[c]
|
|
||||||
|
|
||||||
del context.pkgs_data[p]
|
def _handle_mutual_conflicts(self, mutual_conflicts: Dict[str, str], all_conflicts: Dict[str, str],
|
||||||
|
context: UpdateRequirementsContext):
|
||||||
|
for pkg1, pkg2 in mutual_conflicts.items():
|
||||||
|
pkg1_to_install = pkg1 in context.to_install
|
||||||
|
pkg2_to_install = pkg2 in context.to_install
|
||||||
|
|
||||||
return root_conflict
|
if pkg1_to_install and pkg2_to_install:
|
||||||
|
# remove both from to install and mark their source packages as 'cannot_update'
|
||||||
|
self._handle_conflict_both_to_install(pkg1, pkg2, context)
|
||||||
|
elif (pkg1_to_install and not pkg2_to_install) or (not pkg1_to_install and pkg2_to_install):
|
||||||
|
self._handle_conflict_to_update_and_to_install(pkg1, pkg2, pkg1_to_install, context)
|
||||||
|
else:
|
||||||
|
# adding both to the 'cannot update' list
|
||||||
|
self._handle_conflict_both_to_update(pkg1, pkg2, context)
|
||||||
|
|
||||||
def _fill_conflicts(self, context: UpdateRequirementsContext, blacklist: Iterable[str] = None):
|
# removing conflicting packages from the packages selected to upgrade
|
||||||
|
for pkg1, pkg2 in mutual_conflicts.items():
|
||||||
|
for pkg_name in (pkg1, pkg2):
|
||||||
|
if pkg_name in context.pkgs_data:
|
||||||
|
if context.pkgs_data[pkg_name].get('c'):
|
||||||
|
for c in context.pkgs_data[pkg_name]['c']:
|
||||||
|
# source = provided_map[c]
|
||||||
|
if c in all_conflicts:
|
||||||
|
del all_conflicts[c]
|
||||||
|
|
||||||
|
del context.pkgs_data[pkg_name]
|
||||||
|
|
||||||
|
def _fill_conflicts(self, context: UpdateRequirementsContext, blacklist: Optional[Iterable[str]] = None):
|
||||||
self.logger.info("Checking conflicts")
|
self.logger.info("Checking conflicts")
|
||||||
|
|
||||||
root_conflict = self._filter_and_map_conflicts(context)
|
conflicts, mutual_conflicts = self._map_conflicts(data=context.pkgs_data,
|
||||||
|
providers=context.provided_map,
|
||||||
|
versions=context.installed)
|
||||||
|
|
||||||
if root_conflict:
|
if mutual_conflicts:
|
||||||
for dep, source in root_conflict.items():
|
self._handle_mutual_conflicts(mutual_conflicts, conflicts, context)
|
||||||
if dep not in context.to_remove and (not blacklist or dep not in blacklist):
|
|
||||||
req = ArchPackage(name=dep, installed=True, i18n=self.i18n)
|
if conflicts:
|
||||||
reason = "{} '{}'".format(self.i18n['arch.info.conflicts with'].capitalize(), source)
|
for conflict_name, source_name in conflicts.items():
|
||||||
context.to_remove[dep] = UpgradeRequirement(req, reason)
|
if conflict_name not in context.to_remove and (not blacklist or conflict_name not in blacklist):
|
||||||
|
if conflict_name in context.to_update:
|
||||||
|
conflict = context.to_update[conflict_name]
|
||||||
|
else:
|
||||||
|
conflict = ArchPackage(name=conflict_name, installed=True, i18n=self.i18n)
|
||||||
|
|
||||||
|
reason = f"{self.i18n['arch.info.conflicts with'].capitalize()} '{source_name}'"
|
||||||
|
context.to_remove[conflict_name] = UpgradeRequirement(conflict, reason)
|
||||||
|
|
||||||
def _map_and_add_package(self, pkg_data: Tuple[str, str], idx: int, output: dict):
|
def _map_and_add_package(self, pkg_data: Tuple[str, str], idx: int, output: dict):
|
||||||
version = None
|
version = None
|
||||||
@@ -234,6 +283,31 @@ class UpdatesSummarizer:
|
|||||||
|
|
||||||
output[idx] = ArchPackage(name=pkg_data[0], version=version, latest_version=version, repository=pkg_data[1], i18n=self.i18n)
|
output[idx] = ArchPackage(name=pkg_data[0], version=version, latest_version=version, repository=pkg_data[1], i18n=self.i18n)
|
||||||
|
|
||||||
|
def _fill_conflicts_to_install(self, context: UpdateRequirementsContext, install_data: Dict[str, Dict[str, Any]]):
|
||||||
|
"""
|
||||||
|
Parameters
|
||||||
|
context: update context
|
||||||
|
install_data: a dict mapping the packages to be installed names by their data
|
||||||
|
"""
|
||||||
|
# to properly fill conflicts considering new packages to be installed:
|
||||||
|
# - the 'context.provided_map' should contain the providers of these new packages
|
||||||
|
# - the 'context.installed' should contain the versions of these new packages
|
||||||
|
provided_map_bkp = {**context.provided_map}
|
||||||
|
self.__fill_provided_map(context=context, pkgs=context.to_install, fill_installed=False)
|
||||||
|
|
||||||
|
# adding the new packages to install as 'installed'
|
||||||
|
for pkg, data in install_data.items():
|
||||||
|
context.installed[pkg] = data["v"]
|
||||||
|
|
||||||
|
self._fill_conflicts(context, context.to_remove.keys())
|
||||||
|
|
||||||
|
# restoring the original data structures
|
||||||
|
context.provided_map = provided_map_bkp
|
||||||
|
|
||||||
|
for pkg in install_data:
|
||||||
|
if pkg in context.installed:
|
||||||
|
del context.installed[pkg]
|
||||||
|
|
||||||
def _fill_to_install(self, context: UpdateRequirementsContext) -> bool:
|
def _fill_to_install(self, context: UpdateRequirementsContext) -> bool:
|
||||||
ti = time.time()
|
ti = time.time()
|
||||||
self.logger.info("Discovering updates missing packages")
|
self.logger.info("Discovering updates missing packages")
|
||||||
@@ -266,7 +340,8 @@ class UpdatesSummarizer:
|
|||||||
|
|
||||||
for idx, dep in enumerate(deps):
|
for idx, dep in enumerate(deps):
|
||||||
data = deps_data[dep[0]]
|
data = deps_data[dep[0]]
|
||||||
pkg = ArchPackage(name=dep[0], version=data['v'], latest_version=data['v'], repository=dep[1], i18n=self.i18n, package_base=data.get('b', dep[0]))
|
pkg = ArchPackage(name=dep[0], version=data['v'], latest_version=data['v'], repository=dep[1],
|
||||||
|
i18n=self.i18n, package_base=data.get('b', dep[0]))
|
||||||
sorted_pkgs[idx] = pkg
|
sorted_pkgs[idx] = pkg
|
||||||
context.to_install[dep[0]] = pkg
|
context.to_install[dep[0]] = pkg
|
||||||
|
|
||||||
@@ -284,16 +359,17 @@ class UpdatesSummarizer:
|
|||||||
|
|
||||||
if all_to_install_data:
|
if all_to_install_data:
|
||||||
context.pkgs_data.update(all_to_install_data)
|
context.pkgs_data.update(all_to_install_data)
|
||||||
self._fill_conflicts(context, context.to_remove.keys())
|
self._fill_conflicts_to_install(context, all_to_install_data)
|
||||||
|
|
||||||
if context.to_install:
|
if context.to_install:
|
||||||
self.__fill_provided_map(context=context, pkgs=context.to_install, fill_installed=False)
|
self.__fill_provided_map(context=context, pkgs=context.to_install, fill_installed=False)
|
||||||
|
|
||||||
tf = time.time()
|
tf = time.time()
|
||||||
self.logger.info("It took {0:.2f} seconds to retrieve required upgrade packages".format(tf - ti))
|
self.logger.info(f"It took {tf - ti:.2f} seconds to retrieve required upgrade packages")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def __fill_provided_map(self, context: UpdateRequirementsContext, pkgs: Dict[str, ArchPackage], fill_installed: bool = True):
|
def __fill_provided_map(self, context: UpdateRequirementsContext, pkgs: Dict[str, ArchPackage],
|
||||||
|
fill_installed: bool = True):
|
||||||
if pkgs:
|
if pkgs:
|
||||||
ti = time.time()
|
ti = time.time()
|
||||||
self.logger.info("Filling provided names")
|
self.logger.info("Filling provided names")
|
||||||
@@ -304,26 +380,26 @@ class UpdatesSummarizer:
|
|||||||
installed_to_ignore = set()
|
installed_to_ignore = set()
|
||||||
|
|
||||||
for pkgname in pkgs:
|
for pkgname in pkgs:
|
||||||
pacman.fill_provided_map(pkgname, pkgname, context.provided_map)
|
context.add_to_provided_map(pkgname, pkgname)
|
||||||
|
|
||||||
if fill_installed:
|
if fill_installed:
|
||||||
installed_to_ignore.add(pkgname)
|
installed_to_ignore.add(pkgname)
|
||||||
|
|
||||||
pdata = context.pkgs_data.get(pkgname)
|
pdata = context.pkgs_data.get(pkgname)
|
||||||
if pdata and pdata['p']:
|
if pdata and pdata['p']:
|
||||||
pacman.fill_provided_map('{}={}'.format(pkgname, pdata['v']), pkgname, context.provided_map)
|
context.add_to_provided_map(f"{pkgname}={pdata['v']}", pkgname)
|
||||||
|
|
||||||
ver_split = pdata['v'].split('-')
|
ver_split = pdata['v'].split('-')
|
||||||
|
|
||||||
if len(ver_split) > 1:
|
if len(ver_split) > 1:
|
||||||
pacman.fill_provided_map('{}={}'.format(pkgname, '-'.join(ver_split[0:-1])), pkgname, context.provided_map)
|
context.add_to_provided_map(f"{pkgname}={'-'.join(ver_split[0:-1])}", pkgname)
|
||||||
|
|
||||||
for p in pdata['p']:
|
for p in pdata['p']:
|
||||||
pacman.fill_provided_map(p, pkgname, context.provided_map)
|
context.add_to_provided_map(p, pkgname)
|
||||||
split_provided = p.split('=')
|
split_provided = p.split('=')
|
||||||
|
|
||||||
if len(split_provided) > 1 and split_provided[0] != p:
|
if len(split_provided) > 1 and split_provided[0] != p:
|
||||||
pacman.fill_provided_map(split_provided[0], pkgname, context.provided_map)
|
context.add_to_provided_map(split_provided[0], pkgname)
|
||||||
|
|
||||||
if context.installed and installed_to_ignore: # filling the provided names of the installed
|
if context.installed and installed_to_ignore: # filling the provided names of the installed
|
||||||
installed_to_query = {*context.installed}.difference(installed_to_ignore)
|
installed_to_query = {*context.installed}.difference(installed_to_ignore)
|
||||||
@@ -343,7 +419,10 @@ class UpdatesSummarizer:
|
|||||||
context.aur_index.update(names)
|
context.aur_index.update(names)
|
||||||
self.logger.info("AUR index loaded on the context")
|
self.logger.info("AUR index loaded on the context")
|
||||||
|
|
||||||
def _map_requirement(self, pkg: ArchPackage, context: UpdateRequirementsContext, installed_sizes: Dict[str, int] = None, to_install: bool = False, to_sync: Set[str] = None) -> UpgradeRequirement:
|
def _map_requirement(self, pkg: ArchPackage, context: UpdateRequirementsContext,
|
||||||
|
installed_sizes: Optional[Dict[str, float]] = None, to_install: bool = False,
|
||||||
|
to_sync: Set[str] = None) -> UpgradeRequirement:
|
||||||
|
|
||||||
requirement = UpgradeRequirement(pkg)
|
requirement = UpgradeRequirement(pkg)
|
||||||
|
|
||||||
if pkg.repository != 'aur':
|
if pkg.repository != 'aur':
|
||||||
@@ -383,13 +462,15 @@ class UpdatesSummarizer:
|
|||||||
required_by.add(p)
|
required_by.add(p)
|
||||||
break
|
break
|
||||||
|
|
||||||
requirement.reason = '{}: {}'.format(self.i18n['arch.info.required by'].capitalize(), ','.join(required_by) if required_by else '?')
|
requirement.reason = f"{self.i18n['arch.info.required by'].capitalize()}: " \
|
||||||
|
f"{','.join(required_by) if required_by else '?'}"
|
||||||
|
|
||||||
return requirement
|
return requirement
|
||||||
|
|
||||||
def summarize(self, pkgs: List[ArchPackage], root_password: Optional[str], arch_config: dict) -> Optional[UpgradeRequirements]:
|
def summarize(self, pkgs: List[ArchPackage], root_password: Optional[str], arch_config: dict) \
|
||||||
res = UpgradeRequirements([], [], [], [])
|
-> Optional[UpgradeRequirements]:
|
||||||
|
|
||||||
|
res = UpgradeRequirements([], [], [], [])
|
||||||
remote_provided_map = pacman.map_provided(remote=True)
|
remote_provided_map = pacman.map_provided(remote=True)
|
||||||
remote_repo_map = pacman.map_repositories()
|
remote_repo_map = pacman.map_repositories()
|
||||||
context = UpdateRequirementsContext(to_update={}, repo_to_update={}, aur_to_update={}, repo_to_install={},
|
context = UpdateRequirementsContext(to_update={}, repo_to_update={}, aur_to_update={}, repo_to_install={},
|
||||||
@@ -434,20 +515,22 @@ class UpdatesSummarizer:
|
|||||||
self.logger.info("The operation was cancelled by the user")
|
self.logger.info("The operation was cancelled by the user")
|
||||||
return
|
return
|
||||||
except PackageNotFoundException as e:
|
except PackageNotFoundException as e:
|
||||||
self.logger.error("Package '{}' not found".format(e.name))
|
self.logger.error(f"Package '{e.name}' not found")
|
||||||
return
|
return
|
||||||
|
|
||||||
if context.pkgs_data:
|
if context.pkgs_data:
|
||||||
self._fill_dependency_breakage(context)
|
self._fill_dependency_breakage(context)
|
||||||
|
|
||||||
self.__update_context_based_on_to_remove(context)
|
if context.to_remove:
|
||||||
|
self.__update_context_based_on_to_remove(context)
|
||||||
|
|
||||||
if context.to_update:
|
if context.to_update:
|
||||||
installed_sizes = pacman.get_installed_size(list(context.to_update.keys()))
|
installed_sizes = pacman.get_installed_size(list(context.to_update.keys()))
|
||||||
|
|
||||||
sorted_pkgs = []
|
sorted_pkgs = []
|
||||||
|
|
||||||
if context.repo_to_update: # only sorting by name ( pacman already knows the best order to perform the upgrade )
|
if context.repo_to_update:
|
||||||
|
# only sorting by name (pacman already knows the best order to perform the upgrade)
|
||||||
sorted_pkgs.extend(context.repo_to_update.values())
|
sorted_pkgs.extend(context.repo_to_update.values())
|
||||||
sorted_pkgs.sort(key=lambda pkg: pkg.name)
|
sorted_pkgs.sort(key=lambda pkg: pkg.name)
|
||||||
|
|
||||||
@@ -468,101 +551,121 @@ class UpdatesSummarizer:
|
|||||||
if context.to_install:
|
if context.to_install:
|
||||||
to_sync = {r.pkg.name for r in res.to_upgrade} if res.to_upgrade else {}
|
to_sync = {r.pkg.name for r in res.to_upgrade} if res.to_upgrade else {}
|
||||||
to_sync.update(context.to_install.keys())
|
to_sync.update(context.to_install.keys())
|
||||||
res.to_install = [self._map_requirement(p, context, to_install=True, to_sync=to_sync) for p in context.to_install.values()]
|
res.to_install = [self._map_requirement(p, context, to_install=True, to_sync=to_sync)
|
||||||
|
for p in context.to_install.values()]
|
||||||
|
|
||||||
res.context['data'] = context.pkgs_data
|
res.context['data'] = context.pkgs_data
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def __update_context_based_on_to_remove(self, context: UpdateRequirementsContext):
|
def __update_context_based_on_to_remove(self, context: UpdateRequirementsContext):
|
||||||
if context.to_remove:
|
# filtering all package to synchronization from the transaction context
|
||||||
to_remove_provided = {}
|
to_sync = set()
|
||||||
# filtering all package to synchronization from the transaction context
|
|
||||||
to_sync = {*(context.to_update.keys() if context.to_update else set()), *(context.to_install.keys() if context.to_install else set())}
|
|
||||||
if to_sync: # checking if any packages to sync on the context rely on the 'to remove' ones
|
|
||||||
to_remove_provided.update(pacman.map_provided(remote=False, pkgs=context.to_remove.keys()))
|
|
||||||
to_remove_from_sync = {} # will store all packages that should be removed
|
|
||||||
|
|
||||||
for pname in to_sync:
|
if context.to_update:
|
||||||
if pname in context.pkgs_data:
|
to_sync.update(context.to_update.keys())
|
||||||
deps = context.pkgs_data[pname].get('d')
|
|
||||||
|
|
||||||
if deps:
|
if context.to_install:
|
||||||
required = set()
|
to_sync.update(context.to_install.keys())
|
||||||
|
|
||||||
for pkg in context.to_remove:
|
to_remove_provided = {}
|
||||||
for provided in to_remove_provided[pkg]:
|
if to_sync: # checking if any packages to sync on the context rely on the 'to remove' ones
|
||||||
if provided in deps:
|
to_remove_provided.update(pacman.map_provided(remote=False, pkgs=context.to_remove.keys()))
|
||||||
required.add(pkg)
|
to_remove_from_sync = {} # will store all packages that should be removed
|
||||||
break
|
|
||||||
|
|
||||||
if required:
|
for pname in to_sync:
|
||||||
to_remove_from_sync[pname] = required
|
if pname in context.pkgs_data:
|
||||||
|
deps = context.pkgs_data[pname].get('d')
|
||||||
|
|
||||||
|
if deps:
|
||||||
|
required = set()
|
||||||
|
|
||||||
|
for pkg in context.to_remove:
|
||||||
|
for provided in to_remove_provided[pkg]:
|
||||||
|
if provided in deps:
|
||||||
|
required.add(pkg)
|
||||||
|
break
|
||||||
|
|
||||||
|
if required:
|
||||||
|
to_remove_from_sync[pname] = required
|
||||||
|
else:
|
||||||
|
self.logger.warning(f"Conflict resolution: package '{pname}' marked to synchronization "
|
||||||
|
f"has no data loaded")
|
||||||
|
|
||||||
|
if to_remove_from_sync: # removing all these packages and their dependents from the context
|
||||||
|
self._add_to_remove(to_sync, to_remove_from_sync, context)
|
||||||
|
|
||||||
|
# checking if the installed packages that are not in the transaction context rely on the current
|
||||||
|
# packages to be removed:
|
||||||
|
current_to_remove = {*context.to_remove.keys()}
|
||||||
|
required_by_to_remove = self.deps_analyser.map_all_required_by(current_to_remove, {*to_sync})
|
||||||
|
|
||||||
|
if required_by_to_remove:
|
||||||
|
# updating provided context:
|
||||||
|
provided_not_mapped = set()
|
||||||
|
for pkg in current_to_remove.difference({*to_remove_provided.keys()}):
|
||||||
|
if pkg not in context.pkgs_data:
|
||||||
|
provided_not_mapped.add(pkg)
|
||||||
|
else:
|
||||||
|
provided = context.pkgs_data[pkg].get('p')
|
||||||
|
if provided:
|
||||||
|
to_remove_provided[pkg] = provided
|
||||||
else:
|
else:
|
||||||
self.logger.warning("Conflict resolution: package '{}' marked to synchronization has no data loaded")
|
|
||||||
|
|
||||||
if to_remove_from_sync: # removing all these packages and their dependents from the context
|
|
||||||
self._add_to_remove(to_sync, to_remove_from_sync, context)
|
|
||||||
|
|
||||||
# checking if the installed packages that are not in the transaction context rely on the current packages to be removed:
|
|
||||||
current_to_remove = {*context.to_remove.keys()}
|
|
||||||
required_by_installed = self.deps_analyser.map_all_required_by(current_to_remove, {*to_sync})
|
|
||||||
|
|
||||||
if required_by_installed:
|
|
||||||
# updating provided context:
|
|
||||||
provided_not_mapped = set()
|
|
||||||
for pkg in current_to_remove.difference({*to_remove_provided.keys()}):
|
|
||||||
if pkg not in context.pkgs_data:
|
|
||||||
provided_not_mapped.add(pkg)
|
provided_not_mapped.add(pkg)
|
||||||
|
|
||||||
|
if provided_not_mapped:
|
||||||
|
to_remove_provided.update(pacman.map_provided(remote=False, pkgs=provided_not_mapped))
|
||||||
|
|
||||||
|
deps_no_data = {dep for dep in required_by_to_remove if dep not in context.pkgs_data}
|
||||||
|
deps_nodata_deps = pacman.map_required_dependencies(*deps_no_data) if deps_no_data else {}
|
||||||
|
|
||||||
|
reverse_to_remove_provided = {p: name for name, provided in to_remove_provided.items() for p in provided}
|
||||||
|
|
||||||
|
for pkg in required_by_to_remove:
|
||||||
|
if pkg not in context.to_remove:
|
||||||
|
if pkg in context.pkgs_data:
|
||||||
|
dep_deps = context.pkgs_data[pkg].get('d')
|
||||||
else:
|
else:
|
||||||
provided = context.pkgs_data[pkg].get('p')
|
dep_deps = deps_nodata_deps.get(pkg)
|
||||||
if provided:
|
|
||||||
to_remove_provided[pkg] = provided
|
|
||||||
else:
|
|
||||||
provided_not_mapped.add(pkg)
|
|
||||||
|
|
||||||
if provided_not_mapped:
|
if dep_deps:
|
||||||
to_remove_provided.update(pacman.map_provided(remote=False, pkgs=provided_not_mapped))
|
source = ', '.join(
|
||||||
|
(reverse_to_remove_provided[d] for d in dep_deps if d in reverse_to_remove_provided))
|
||||||
|
reason = f"{self.i18n['arch.info.depends on'].capitalize()} '{source if source else '?'}'"
|
||||||
|
else:
|
||||||
|
reason = '?'
|
||||||
|
|
||||||
deps_no_data = {dep for dep in required_by_installed if dep in context.pkgs_data}
|
pkg_repo = context.remote_repo_map.get(pkg)
|
||||||
deps_nodata_deps = pacman.map_required_dependencies(*deps_no_data) if deps_no_data else {}
|
pkg_version = context.installed.get(pkg)
|
||||||
|
context.to_remove[pkg] = UpgradeRequirement(pkg=ArchPackage(name=pkg,
|
||||||
|
installed=True,
|
||||||
|
i18n=self.i18n,
|
||||||
|
version=pkg_version,
|
||||||
|
latest_version=pkg_version,
|
||||||
|
repository=pkg_repo),
|
||||||
|
reason=reason)
|
||||||
|
|
||||||
reverse_to_remove_provided = {p: name for name, provided in to_remove_provided.items() for p in provided}
|
for name in context.to_remove: # upgrading lists
|
||||||
|
if name in context.pkgs_data:
|
||||||
|
del context.pkgs_data[name]
|
||||||
|
|
||||||
for pkg in required_by_installed:
|
if name in context.aur_to_update:
|
||||||
if pkg not in context.to_remove:
|
del context.aur_to_update[name]
|
||||||
if pkg in context.pkgs_data:
|
|
||||||
dep_deps = context.pkgs_data[pkg].get('d')
|
|
||||||
else:
|
|
||||||
dep_deps = deps_nodata_deps.get(pkg)
|
|
||||||
|
|
||||||
if dep_deps:
|
if name in context.repo_to_update:
|
||||||
source = ', '.join((reverse_to_remove_provided[d] for d in dep_deps if d in reverse_to_remove_provided))
|
del context.repo_to_update[name]
|
||||||
reason = "{} '{}'".format(self.i18n['arch.info.depends on'].capitalize(), source if source else '?')
|
|
||||||
context.to_remove[pkg] = UpgradeRequirement(pkg=ArchPackage(name=pkg,
|
|
||||||
installed=True,
|
|
||||||
i18n=self.i18n),
|
|
||||||
reason=reason)
|
|
||||||
|
|
||||||
for name in context.to_remove: # upgrading lists
|
removed_size = pacman.get_installed_size([*context.to_remove.keys()])
|
||||||
if name in context.pkgs_data:
|
|
||||||
del context.pkgs_data[name]
|
|
||||||
|
|
||||||
if name in context.aur_to_update:
|
if removed_size:
|
||||||
del context.aur_to_update[name]
|
for name, size in removed_size.items():
|
||||||
|
if size is not None:
|
||||||
|
req = context.to_remove.get(name)
|
||||||
|
if req:
|
||||||
|
req.extra_size = size
|
||||||
|
|
||||||
if name in context.repo_to_update:
|
def _add_to_remove(self, pkgs_to_sync: Set[str], names: Dict[str, Set[str]], context: UpdateRequirementsContext,
|
||||||
del context.repo_to_update[name]
|
to_ignore: Set[str] = None):
|
||||||
|
|
||||||
removed_size = pacman.get_installed_size([*context.to_remove.keys()])
|
|
||||||
|
|
||||||
if removed_size:
|
|
||||||
for name, size in removed_size.items():
|
|
||||||
if size is not None:
|
|
||||||
req = context.to_remove.get(name)
|
|
||||||
if req:
|
|
||||||
req.extra_size = size
|
|
||||||
|
|
||||||
def _add_to_remove(self, pkgs_to_sync: Set[str], names: Dict[str, Set[str]], context: UpdateRequirementsContext, to_ignore: Set[str] = None):
|
|
||||||
blacklist = to_ignore if to_ignore else set()
|
blacklist = to_ignore if to_ignore else set()
|
||||||
blacklist.update(names)
|
blacklist.update(names)
|
||||||
|
|
||||||
@@ -582,20 +685,19 @@ class UpdatesSummarizer:
|
|||||||
dependents[n] = all_deps
|
dependents[n] = all_deps
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.logger.warning("Package '{}' to sync could not be removed from the transaction context because its data was not loaded")
|
self.logger.warning(f"Package '{pname}' to sync could not be removed from the transaction context "
|
||||||
|
f"because its data was not loaded")
|
||||||
|
|
||||||
for n in names:
|
for n in names:
|
||||||
if n in context.pkgs_data:
|
if n in context.pkgs_data:
|
||||||
if n not in context.to_remove:
|
if n not in context.to_remove:
|
||||||
depends_on = names.get(n)
|
depends_on = names.get(n)
|
||||||
if depends_on:
|
if depends_on:
|
||||||
reason = "{} '{}'".format(self.i18n['arch.info.depends on'].capitalize(), ', '.join(depends_on))
|
reason = f"{self.i18n['arch.info.depends on'].capitalize()} '{', '.join(depends_on)}'"
|
||||||
else:
|
else:
|
||||||
reason = '?'
|
reason = '?'
|
||||||
|
|
||||||
context.to_remove[n] = UpgradeRequirement(pkg=ArchPackage(name=n,
|
context.to_remove[n] = UpgradeRequirement(pkg=ArchPackage(name=n, installed=True, i18n=self.i18n),
|
||||||
installed=True,
|
|
||||||
i18n=self.i18n),
|
|
||||||
reason=reason)
|
reason=reason)
|
||||||
|
|
||||||
all_deps = dependents.get(n)
|
all_deps = dependents.get(n)
|
||||||
@@ -603,7 +705,8 @@ class UpdatesSummarizer:
|
|||||||
if all_deps:
|
if all_deps:
|
||||||
self._add_to_remove(pkgs_to_sync, {dep: {n} for dep in all_deps}, context, blacklist)
|
self._add_to_remove(pkgs_to_sync, {dep: {n} for dep in all_deps}, context, blacklist)
|
||||||
else:
|
else:
|
||||||
self.logger.warning("Package '{}' could not be removed from the transaction context because its data was not loaded")
|
self.logger.warning(f"Package '{n}' could not be removed from the transaction context because its "
|
||||||
|
f"data was not loaded")
|
||||||
|
|
||||||
def _fill_dependency_breakage(self, context: UpdateRequirementsContext):
|
def _fill_dependency_breakage(self, context: UpdateRequirementsContext):
|
||||||
if bool(context.arch_config['check_dependency_breakage']) and (context.to_update or context.to_install):
|
if bool(context.arch_config['check_dependency_breakage']) and (context.to_update or context.to_install):
|
||||||
@@ -667,9 +770,10 @@ class UpdatesSummarizer:
|
|||||||
context=context)
|
context=context)
|
||||||
|
|
||||||
if cannot_upgrade:
|
if cannot_upgrade:
|
||||||
|
pkgs_available = {*context.to_update.values(), *context.to_install.values()}
|
||||||
cannot_upgrade.update(self._add_dependents_as_cannot_upgrade(context=context,
|
cannot_upgrade.update(self._add_dependents_as_cannot_upgrade(context=context,
|
||||||
names=cannot_upgrade,
|
names=cannot_upgrade,
|
||||||
pkgs_available={*context.to_update.values(), *context.to_install.values()}))
|
pkgs_available=pkgs_available))
|
||||||
|
|
||||||
for p in cannot_upgrade:
|
for p in cannot_upgrade:
|
||||||
if p in context.to_update:
|
if p in context.to_update:
|
||||||
@@ -696,7 +800,9 @@ class UpdatesSummarizer:
|
|||||||
tf = time.time()
|
tf = time.time()
|
||||||
self.logger.info("End: checking dependency breakage. Time: {0:.2f} seconds".format(tf - ti))
|
self.logger.info("End: checking dependency breakage. Time: {0:.2f} seconds".format(tf - ti))
|
||||||
|
|
||||||
def _add_dependents_as_cannot_upgrade(self, context: UpdateRequirementsContext, names: Iterable[str], pkgs_available: Set[ArchPackage], already_removed: Optional[Set[str]] = None, iteration_level: int = 0) -> Set[str]:
|
def _add_dependents_as_cannot_upgrade(self, context: UpdateRequirementsContext, names: Iterable[str],
|
||||||
|
pkgs_available: Set[ArchPackage], already_removed: Optional[Set[str]] = None,
|
||||||
|
iteration_level: int = 0) -> Set[str]:
|
||||||
removed = set() if already_removed is None else already_removed
|
removed = set() if already_removed is None else already_removed
|
||||||
removed.update(names)
|
removed.update(names)
|
||||||
|
|
||||||
@@ -718,11 +824,10 @@ class UpdatesSummarizer:
|
|||||||
to_remove.add(pkg.name)
|
to_remove.add(pkg.name)
|
||||||
|
|
||||||
if pkg.name not in context.cannot_upgrade:
|
if pkg.name not in context.cannot_upgrade:
|
||||||
reason = "{} {}".format(self.i18n['arch.info.depends on'].capitalize(), p)
|
reason = f"{self.i18n['arch.info.depends on'].capitalize()} {p}"
|
||||||
context.cannot_upgrade[pkg.name] = UpgradeRequirement(pkg=pkg,
|
req = UpgradeRequirement(pkg=pkg, reason=reason,
|
||||||
reason=reason,
|
sorting_priority=iteration_level - 1)
|
||||||
sorting_priority=iteration_level - 1)
|
context.cannot_upgrade[pkg.name] = req
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
if to_remove:
|
if to_remove:
|
||||||
@@ -732,7 +837,9 @@ class UpdatesSummarizer:
|
|||||||
|
|
||||||
return to_remove
|
return to_remove
|
||||||
|
|
||||||
def _add_dependency_breakage(self, pkgname: str, pkgdeps: Optional[Set[str]], provided_versions: Dict[str, Set[str]], cannot_upgrade: Set[str], context: UpdateRequirementsContext):
|
def _add_dependency_breakage(self, pkgname: str, pkgdeps: Optional[Set[str]],
|
||||||
|
provided_versions: Dict[str, Set[str]], cannot_upgrade: Set[str],
|
||||||
|
context: UpdateRequirementsContext):
|
||||||
if pkgdeps:
|
if pkgdeps:
|
||||||
for dep in pkgdeps:
|
for dep in pkgdeps:
|
||||||
dep_split = RE_DEP_OPERATORS.split(dep)
|
dep_split = RE_DEP_OPERATORS.split(dep)
|
||||||
@@ -750,11 +857,14 @@ class UpdatesSummarizer:
|
|||||||
|
|
||||||
for v in versions:
|
for v in versions:
|
||||||
try:
|
try:
|
||||||
if match_required_version(current_version=v, operator=op, required_version=dep_split[1]):
|
if match_required_version(current_version=v,
|
||||||
|
operator=op,
|
||||||
|
required_version=dep_split[1]):
|
||||||
version_match = True
|
version_match = True
|
||||||
break
|
break
|
||||||
except:
|
except:
|
||||||
self.logger.error("Error when comparing versions {} (provided) and {} (required)".format(v, dep_split[1]))
|
self.logger.error(f"Error when comparing versions {v} (provided) and "
|
||||||
|
f"{dep_split[1]} (required)")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
if not version_match:
|
if not version_match:
|
||||||
|
|||||||
@@ -1,52 +1,52 @@
|
|||||||
Australia=Australia
|
Australia=Australia
|
||||||
Austria=Austria
|
Austria=Austria
|
||||||
Bangladesh=Bangladesh
|
Bangladesh=Bangladesh
|
||||||
Belarus=Belarus
|
Belarus=Biellorussia
|
||||||
Belgium=Belgium
|
Belgium=Belgio
|
||||||
Brazil=Brazil
|
Brazil=Brasile
|
||||||
Bulgaria=Bulgaria
|
Bulgaria=Bulgaria
|
||||||
Canada=Canada
|
Canada=Canada
|
||||||
Chile=Chile
|
Chile=Cile
|
||||||
China=China
|
China=Cina
|
||||||
Costa Rica=Costa Rica
|
Costa Rica=Costa Rica
|
||||||
Czech=Czech
|
Czech=Cecoslovacchia
|
||||||
Denmark=Denmark
|
Denmark=Danimarca
|
||||||
Ecuador=Ecuador
|
Ecuador=Ecuador
|
||||||
France=France
|
France=Francia
|
||||||
Georgia=Georgia
|
Georgia=Georgia
|
||||||
Germany=Germany
|
Germany=Germania
|
||||||
Greece=Greece
|
Greece=Grecia
|
||||||
Hong Kong=Hong Kong
|
Hong Kong=Hong Kong
|
||||||
Hungary=Hungary
|
Hungary=Ungheria
|
||||||
Iceland=Iceland
|
Iceland=Islanda
|
||||||
India=India
|
India=India
|
||||||
Indonesia=Indonesia
|
Indonesia=Indonesia
|
||||||
Iran=Iran
|
Iran=Iran
|
||||||
Italy=Italy
|
Italy=Italia
|
||||||
Japan=Japan
|
Japan=Giappone
|
||||||
Kenya=Kenya
|
Kenya=Kenya
|
||||||
Netherlands=Netherlands
|
Netherlands=Olanda
|
||||||
New Zealand=New Zealand
|
New Zealand=Nuova Zelanda
|
||||||
Norway=Norway
|
Norway=Norvegia
|
||||||
Philippines=Philippines
|
Philippines=Filippine
|
||||||
Poland=Poland
|
Poland=Polonia
|
||||||
Portugal=Portugal
|
Portugal=Portogallo
|
||||||
Russia=Russia
|
Russia=Russia
|
||||||
Singapore=Singapore
|
Singapore=Singapore
|
||||||
South Africa=South Africa
|
South Africa=South Africa
|
||||||
South Korea=South Korea
|
South Korea=Korea del Sud
|
||||||
Spain=Spain
|
Spain=Spagna
|
||||||
Sweden=Sweden
|
Sweden=Svezia
|
||||||
Switzerland=Switzerland
|
Switzerland=Svizzera
|
||||||
Taiwan=Taiwan
|
Taiwan=Taiwan
|
||||||
Thailand=Thailand
|
Thailand=Tailandia
|
||||||
Turkey=Turkey
|
Turkey=Turchia
|
||||||
Ukraine=Ukraine
|
Ukraine=Ucraina
|
||||||
United Kingdom=United Kingdom
|
United Kingdom=Regno Unito
|
||||||
United States=United States
|
United States=Stati Uniti
|
||||||
action.backup.error.create=It was not possible to generate a new system copy
|
action.backup.error.create=Non è stato possibile generare una nuova copia di sistema
|
||||||
action.backup.error.delete=It was not possible to delete all the old system copies
|
action.backup.error.delete=Non è stato possibile eliminare tutte le vecchie copie di sistema
|
||||||
action.backup.error.proceed=Proceed anyway ?
|
action.backup.error.proceed=Procedere comunque ?
|
||||||
action.backup.invalid_mode=Invalid backup mode
|
action.backup.invalid_mode=Invalid backup mode
|
||||||
action.backup.msg=Do you want to generate a system copy before proceeding ?
|
action.backup.msg=Do you want to generate a system copy before proceeding ?
|
||||||
action.backup.substatus.create=Generating a new system backup
|
action.backup.substatus.create=Generating a new system backup
|
||||||
|
|||||||
1228
tests/gems/arch/test_updates.py
Normal file
1228
tests/gems/arch/test_updates.py
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user