mirror of
https://github.com/spalencsar/bearhub.git
synced 2026-07-09 08:44:15 +02:00
[arch] improvement: allowing AUR packages to be installed as dependencies of a repository package | fix: not displaying all possible AUR providers for a given dependency
This commit is contained in:
@@ -2,7 +2,7 @@ import logging
|
||||
import os
|
||||
import re
|
||||
import urllib.parse
|
||||
from typing import Set, List, Iterable, Dict, Optional
|
||||
from typing import Set, List, Iterable, Dict, Optional, Generator, Tuple
|
||||
|
||||
import requests
|
||||
|
||||
@@ -119,6 +119,43 @@ class AURClient:
|
||||
except:
|
||||
return []
|
||||
|
||||
def map_provided(self, pkgname: str, pkgver: str, provided: Optional[Iterable[str]] = None, strip_epoch: bool = True) -> Set[str]:
|
||||
all_provided = {pkgname, f"{pkgname}={pkgver.split('-')[0] if strip_epoch else pkgver}"}
|
||||
|
||||
if provided:
|
||||
for provided in provided:
|
||||
all_provided.add(provided)
|
||||
all_provided.add(provided.split('=', 1)[0])
|
||||
|
||||
return all_provided
|
||||
|
||||
def gen_updates_data(self, names: Iterable[str]) -> Generator[Tuple[str, dict], None, None]:
|
||||
for package in self.get_info(names):
|
||||
pkgname, pkgver = package['Name'], package['Version'].split('-')[0]
|
||||
|
||||
deps = set()
|
||||
|
||||
for dtype in ('Depends', 'MakeDepends', 'CheckDepends'):
|
||||
dep_set = package.get(dtype)
|
||||
if dep_set:
|
||||
deps.update(dep_set)
|
||||
|
||||
conflicts = set()
|
||||
pkg_conflicts = package.get('Conflicts')
|
||||
|
||||
if pkg_conflicts:
|
||||
conflicts.update(pkg_conflicts)
|
||||
|
||||
yield pkgname, {
|
||||
'v': pkgver,
|
||||
'b': package.get('PackageBase', pkgname),
|
||||
'r': 'aur',
|
||||
'p': self.map_provided(pkgname=pkgname, pkgver=pkgver, provided=package.get('Provides'), strip_epoch=False),
|
||||
'd': deps,
|
||||
'c': conflicts,
|
||||
'ds': None,
|
||||
's': None}
|
||||
|
||||
def get_src_info(self, name: str, real_name: Optional[str] = None) -> dict:
|
||||
srcinfo = self.srcinfo_cache.get(name)
|
||||
|
||||
@@ -229,7 +266,7 @@ class AURClient:
|
||||
def clean_caches(self):
|
||||
self.srcinfo_cache.clear()
|
||||
|
||||
def map_update_data(self, pkgname: str, latest_version: Optional[str], srcinfo: Optional[dict] = None) -> dict:
|
||||
def map_update_data(self, pkgname: str, latest_version: Optional[str] = None, srcinfo: Optional[dict] = None) -> dict:
|
||||
info = self.get_src_info(pkgname) if not srcinfo else srcinfo
|
||||
|
||||
provided = set()
|
||||
|
||||
@@ -209,7 +209,7 @@ class ArchManager(SoftwareManager):
|
||||
self.enabled = True
|
||||
self.arch_distro = context.distro == 'arch'
|
||||
self.categories = {}
|
||||
self.deps_analyser = DependenciesAnalyser(self.aur_client, self.i18n)
|
||||
self.deps_analyser = DependenciesAnalyser(self.aur_client, self.i18n, self.logger)
|
||||
self.http_client = context.http_client
|
||||
self._custom_actions: Optional[Dict[str, CustomSoftwareAction]] = None
|
||||
self.index_aur = None
|
||||
@@ -2333,7 +2333,7 @@ class ArchManager(SoftwareManager):
|
||||
to_install = []
|
||||
|
||||
if context.missing_deps:
|
||||
to_install.extend((d[0] for d in context.missing_deps))
|
||||
to_install.extend((d[0] for d in context.missing_deps if d[1] != 'aur'))
|
||||
|
||||
to_install.extend(pkgpaths)
|
||||
|
||||
@@ -2357,7 +2357,8 @@ class ArchManager(SoftwareManager):
|
||||
status_handler = None
|
||||
|
||||
installed_with_same_name = self.read_installed(disk_loader=context.disk_loader, internet_available=True, names=context.get_package_names()).installed
|
||||
context.watcher.change_substatus(self.i18n['arch.installing.package'].format(bold(context.name)))
|
||||
context.watcher.change_substatus(self.i18n['arch.installing.package'].format(bold(context.name))) #
|
||||
|
||||
installed = self._handle_install_call(context=context, to_install=to_install, status_handler=status_handler)
|
||||
|
||||
if status_handler:
|
||||
@@ -2600,29 +2601,9 @@ class ArchManager(SoftwareManager):
|
||||
return TransactionResult(success=pkg_installed, installed=installed, removed=removed)
|
||||
|
||||
def _install_from_repository(self, context: TransactionContext) -> bool:
|
||||
try:
|
||||
missing_deps = self._list_missing_deps(context)
|
||||
except PackageNotFoundException:
|
||||
self.logger.error("Package '{}' was not found")
|
||||
if not self._handle_missing_deps(context):
|
||||
return False
|
||||
|
||||
if missing_deps is None:
|
||||
return False # called off by the user
|
||||
|
||||
if missing_deps:
|
||||
if any((dep for dep in missing_deps if dep[1] == 'aur')):
|
||||
context.watcher.show_message(title=self.i18n['error'].capitalize(),
|
||||
body=self.i18n['arch.install.repo_pkg.error.aur_deps'],
|
||||
type_=MessageType.ERROR)
|
||||
return False
|
||||
|
||||
context.missing_deps = missing_deps
|
||||
context.watcher.change_substatus(self.i18n['arch.missing_deps_found'].format(bold(context.name)))
|
||||
|
||||
if not confirmation.request_install_missing_deps(context.name, missing_deps, context.watcher, self.i18n):
|
||||
context.watcher.print(self.i18n['action.cancelled'])
|
||||
return False
|
||||
|
||||
res = self._install(context)
|
||||
|
||||
if res and not context.skip_opt_deps:
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import re
|
||||
import traceback
|
||||
from logging import Logger
|
||||
from threading import Thread
|
||||
from typing import Set, List, Tuple, Dict, Iterable, Optional
|
||||
from typing import Set, List, Tuple, Dict, Iterable, Optional, Generator
|
||||
|
||||
from bauh.api.abstract.handler import ProcessWatcher
|
||||
from bauh.gems.arch import pacman, message, sorting, confirmation
|
||||
@@ -13,10 +14,11 @@ from bauh.view.util.translation import I18n
|
||||
|
||||
class DependenciesAnalyser:
|
||||
|
||||
def __init__(self, aur_client: AURClient, i18n: I18n):
|
||||
def __init__(self, aur_client: AURClient, i18n: I18n, logger: Logger):
|
||||
self.aur_client = aur_client
|
||||
self.i18n = i18n
|
||||
self.re_dep_operator = re.compile(r'([<>=]+)')
|
||||
self._log = logger
|
||||
|
||||
def _fill_repository(self, name: str, output: List[Tuple[str, str]]):
|
||||
|
||||
@@ -40,8 +42,8 @@ class DependenciesAnalyser:
|
||||
|
||||
output.append((name, ''))
|
||||
|
||||
def get_missing_packages(self, names: Set[str], repository: str = None, in_analysis: Set[str] = None) -> List[
|
||||
Tuple[str, str]]:
|
||||
def get_missing_packages(self, names: Set[str], repository: Optional[str] = None, in_analysis: Optional[Set[str]] = None) -> \
|
||||
List[Tuple[str, str]]:
|
||||
"""
|
||||
:param names:
|
||||
:param repository:
|
||||
@@ -157,7 +159,8 @@ class DependenciesAnalyser:
|
||||
if missing_subdeps:
|
||||
for dep in missing_subdeps:
|
||||
if not dep[1]:
|
||||
message.show_dep_not_found(dep[0], self.i18n, watcher)
|
||||
dependents = ', '.join(deps[0]) # it is not possible to know which is the exact dependent
|
||||
message.show_dep_not_found(dep[0], self.i18n, watcher, dependent=dependents)
|
||||
return
|
||||
|
||||
for dep in missing_subdeps:
|
||||
@@ -175,25 +178,28 @@ class DependenciesAnalyser:
|
||||
|
||||
return sorted_deps
|
||||
|
||||
def _fill_missing_dep(self, dep_name: str, dep_exp: str, aur_index: Iterable[str],
|
||||
missing_deps: Set[Tuple[str, str]],
|
||||
remote_provided_map: Dict[str, Set[str]], remote_repo_map: Dict[str, str],
|
||||
repo_deps: Set[str], aur_deps: Set[str], deps_data: Dict[str, dict], watcher: ProcessWatcher,
|
||||
automatch_providers: bool):
|
||||
|
||||
def _find_repo_providers(self, dep_name: str, dep_exp: str, remote_provided_map: Dict[str, Set[str]],
|
||||
deps_data: Dict[str, dict], remote_repo_map: Dict[str, str]) -> Generator[Tuple[str, str, Optional[dict]], None, None]:
|
||||
if dep_name == dep_exp:
|
||||
providers = remote_provided_map.get(dep_name)
|
||||
|
||||
if not providers: # try to find the package through the pacman's search mechanism
|
||||
if providers:
|
||||
for pkgname in providers:
|
||||
yield pkgname, remote_repo_map.get(pkgname), None
|
||||
|
||||
else: # try to find the package through the pacman's search mechanism
|
||||
match = pacman.find_one_match(dep_name)
|
||||
|
||||
if match:
|
||||
providers = {match}
|
||||
yield match, remote_repo_map.get(match), None
|
||||
|
||||
else: # handling cases when the dep has an expression ( e.g: xpto>=0.12 )
|
||||
providers = remote_provided_map.get(dep_exp)
|
||||
exact_exp_providers = remote_provided_map.get(dep_exp)
|
||||
|
||||
if providers is None:
|
||||
if exact_exp_providers:
|
||||
for p in exact_exp_providers:
|
||||
yield p, remote_repo_map.get(p), None
|
||||
else:
|
||||
providers = remote_provided_map.get(dep_name)
|
||||
|
||||
if not providers: # try to find the package through the pacman's search mechanism
|
||||
@@ -203,103 +209,177 @@ class DependenciesAnalyser:
|
||||
providers = {match}
|
||||
|
||||
if providers:
|
||||
no_mapped_data = {p for p in providers if
|
||||
p not in deps_data} # checking providers with no mapped data
|
||||
providers_no_provided_data = {p for p in providers if p not in deps_data}
|
||||
missing_providers_data = None
|
||||
|
||||
if no_mapped_data:
|
||||
providers_data = pacman.map_updates_data(no_mapped_data)
|
||||
if providers_no_provided_data:
|
||||
missing_providers_data = pacman.map_updates_data(providers_no_provided_data)
|
||||
|
||||
if not providers_data:
|
||||
raise Exception("Could not retrieve the info from providers: {}".format(no_mapped_data))
|
||||
if not missing_providers_data:
|
||||
raise Exception(f"Could not retrieve information from providers: "
|
||||
f"{', '.join(providers_no_provided_data)}")
|
||||
|
||||
deps_data.update(providers_data) # adding missing providers data
|
||||
data_not_found = {p for p in providers if p not in missing_providers_data}
|
||||
|
||||
if data_not_found:
|
||||
raise Exception(f"Could not retrieve information from providers: "
|
||||
f"{', '.join(data_not_found)}")
|
||||
|
||||
matched_providers = set()
|
||||
split_informed_dep = self.re_dep_operator.split(dep_exp)
|
||||
try:
|
||||
version_required = split_informed_dep[2]
|
||||
exp_op = split_informed_dep[1] if split_informed_dep[1] != '=' else '=='
|
||||
|
||||
for p in providers:
|
||||
provided = deps_data[p]['p']
|
||||
version_required = split_informed_dep[2]
|
||||
exp_op = split_informed_dep[1] if split_informed_dep[1] != '=' else '=='
|
||||
|
||||
for provided_exp in provided:
|
||||
split_dep = self.re_dep_operator.split(provided_exp)
|
||||
for p in providers:
|
||||
info = deps_data.get(p)
|
||||
|
||||
if len(split_dep) == 3 and split_dep[0] == dep_name:
|
||||
version_provided = split_dep[2]
|
||||
if not info and missing_providers_data:
|
||||
info = missing_providers_data[p]
|
||||
|
||||
if match_required_version(version_provided, exp_op, version_required):
|
||||
matched_providers.add(p)
|
||||
break
|
||||
for provided_exp in info['p']:
|
||||
split_dep = self.re_dep_operator.split(provided_exp)
|
||||
|
||||
providers = matched_providers
|
||||
except:
|
||||
traceback.print_exc()
|
||||
if len(split_dep) == 3 and split_dep[0] == dep_name:
|
||||
version_provided = split_dep[2]
|
||||
|
||||
if providers:
|
||||
if len(providers) > 1:
|
||||
dep_data = None
|
||||
if match_required_version(version_provided, exp_op, version_required):
|
||||
yield p, remote_repo_map.get(p), info
|
||||
break
|
||||
|
||||
if automatch_providers:
|
||||
exact_matches = [p for p in providers if p == dep_name]
|
||||
|
||||
if exact_matches:
|
||||
dep_data = (exact_matches[0], remote_repo_map.get(exact_matches[0]))
|
||||
|
||||
if not dep_data:
|
||||
dep_data = (dep_name, '__several__')
|
||||
else:
|
||||
real_name = providers.pop()
|
||||
dep_data = (real_name, remote_repo_map.get(real_name))
|
||||
|
||||
repo_deps.add(dep_data[0])
|
||||
missing_deps.add(dep_data)
|
||||
|
||||
elif aur_index and dep_name in aur_index:
|
||||
def _find_aur_providers(self, dep_name: str, dep_exp: str, aur_index: Iterable[str], exact_match: bool) -> Generator[Tuple[str, dict], None, None]:
|
||||
if exact_match and dep_name in aur_index:
|
||||
if dep_name == dep_exp:
|
||||
aur_deps.add(dep_name)
|
||||
missing_deps.add((dep_name, 'aur'))
|
||||
yield from self.aur_client.gen_updates_data((dep_name,))
|
||||
return
|
||||
else:
|
||||
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 = dep_info[0]['Version']
|
||||
except:
|
||||
traceback.print_exc()
|
||||
return self.__raise_dependency_not_found(dep_exp, watcher)
|
||||
|
||||
for _, dep_data in self.aur_client.gen_updates_data((dep_name,)):
|
||||
split_informed_dep = self.re_dep_operator.split(dep_exp)
|
||||
version_required = split_informed_dep[2]
|
||||
exp_op = split_informed_dep[1].strip()
|
||||
|
||||
if match_required_version(dep_data['v'], exp_op, version_required):
|
||||
yield dep_name, dep_data
|
||||
return
|
||||
|
||||
aur_search = self.aur_client.search(dep_name)
|
||||
|
||||
if aur_search:
|
||||
if dep_name == dep_exp:
|
||||
version_required, exp_op = None, None
|
||||
else:
|
||||
split_informed_dep = self.re_dep_operator.split(dep_exp)
|
||||
version_required = split_informed_dep[2]
|
||||
exp_op = split_informed_dep[1] if split_informed_dep[1] != '=' else '=='
|
||||
|
||||
for pkgname, pkgdata in self.aur_client.gen_updates_data(
|
||||
(aur_res['Name'] for aur_res in aur_search['results'])):
|
||||
if pkgname == dep_name or (dep_name in pkgdata['p']):
|
||||
try:
|
||||
version_required = split_informed_dep[2]
|
||||
exp_op = split_informed_dep[1].strip()
|
||||
|
||||
if match_required_version(dep_version, exp_op, version_required):
|
||||
aur_deps.add(dep_name)
|
||||
missing_deps.add((dep_name, 'aur'))
|
||||
if not version_required or match_required_version(pkgdata['v'], exp_op,
|
||||
version_required):
|
||||
yield pkgname, pkgdata
|
||||
except:
|
||||
self.__raise_dependency_not_found(dep_exp, watcher)
|
||||
else:
|
||||
self.__raise_dependency_not_found(dep_exp, watcher)
|
||||
self._log.warning(f"Could not compare AUR package '{pkgname}' version '{pkgdata['v']}' "
|
||||
f"with the dependency expression '{dep_exp}'")
|
||||
traceback.print_exc()
|
||||
|
||||
def __raise_dependency_not_found(self, dep_exp: str, watcher: Optional[ProcessWatcher]):
|
||||
def _fill_missing_dep(self, dep_name: str, dep_exp: str, aur_index: Iterable[str],
|
||||
missing_deps: Set[Tuple[str, str]],
|
||||
remote_provided_map: Dict[str, Set[str]], remote_repo_map: Dict[str, str],
|
||||
repo_deps: Set[str], aur_deps: Set[str], deps_data: Dict[str, dict], watcher: ProcessWatcher,
|
||||
automatch_providers: bool, dependent: Optional[str] = None):
|
||||
|
||||
repo_matches = None
|
||||
|
||||
for pkgname, repo, data in self._find_repo_providers(dep_name=dep_name, dep_exp=dep_exp,
|
||||
remote_repo_map=remote_repo_map,
|
||||
remote_provided_map=remote_provided_map,
|
||||
deps_data=deps_data):
|
||||
if automatch_providers and pkgname == dep_name:
|
||||
missing_deps.add((pkgname, repo))
|
||||
repo_deps.add(pkgname)
|
||||
|
||||
if data:
|
||||
deps_data[pkgname] = data
|
||||
|
||||
return
|
||||
|
||||
if repo_matches is None:
|
||||
repo_matches = []
|
||||
|
||||
repo_matches.append((pkgname, repo, data))
|
||||
|
||||
aur_matches = None
|
||||
|
||||
if aur_index:
|
||||
for pkgname, pkgdata in self._find_aur_providers(dep_name=dep_name, dep_exp=dep_exp, aur_index=aur_index,
|
||||
exact_match=automatch_providers):
|
||||
if automatch_providers and pkgname == dep_name:
|
||||
missing_deps.add((pkgname, 'aur'))
|
||||
aur_deps.add(pkgname)
|
||||
deps_data[pkgname] = pkgdata
|
||||
return
|
||||
|
||||
if aur_matches is None:
|
||||
aur_matches = []
|
||||
|
||||
aur_matches.append((pkgname, pkgdata))
|
||||
|
||||
total_matches = (len(repo_matches) if repo_matches else 0) + (len(aur_matches) if aur_matches else 0)
|
||||
|
||||
if total_matches == 0:
|
||||
self.__raise_dependency_not_found(dep_exp, watcher, dependent)
|
||||
elif total_matches == 1:
|
||||
if repo_matches:
|
||||
repo_pkg = [*repo_matches][0]
|
||||
|
||||
if repo_pkg[2]:
|
||||
deps_data[repo_pkg[0]] = repo_pkg[2] # already updating the deps data (if available)
|
||||
|
||||
match = (repo_pkg[0], repo_pkg[1])
|
||||
repo_deps.add(repo_pkg[0])
|
||||
else:
|
||||
aur_pkg = aur_matches[0]
|
||||
deps_data[aur_pkg[0]] = aur_pkg[1] # already updating the deps data (if available)
|
||||
aur_deps.add(aur_pkg[0])
|
||||
match = aur_pkg[0], 'aur'
|
||||
|
||||
missing_deps.add(match)
|
||||
|
||||
elif total_matches > 1:
|
||||
missing_deps.add((dep_name, '__several__'))
|
||||
|
||||
if repo_matches:
|
||||
repo_deps.add(dep_name)
|
||||
|
||||
if aur_matches:
|
||||
aur_deps.add(dep_name)
|
||||
|
||||
for pkgname, _ in aur_matches:
|
||||
for key in (dep_name, dep_exp):
|
||||
key_provided = remote_provided_map.get(key, set())
|
||||
remote_provided_map[key] = key_provided
|
||||
key_provided.add(pkgname)
|
||||
|
||||
if pkgname not in remote_repo_map:
|
||||
remote_repo_map[pkgname] = 'aur'
|
||||
|
||||
def __raise_dependency_not_found(self, dep_exp: str, watcher: Optional[ProcessWatcher], dependent: Optional[str] = None):
|
||||
if watcher:
|
||||
message.show_dep_not_found(dep_exp, self.i18n, watcher)
|
||||
message.show_dep_not_found(depname=dep_exp, i18n=self.i18n, watcher=watcher, dependent=dependent)
|
||||
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)
|
||||
def _fill_aur_updates_data(self, pkgnames: Iterable[str], output_data: dict):
|
||||
for pkgname, pkgdata in self.aur_client.gen_updates_data(pkgnames):
|
||||
output_data[pkgname] = pkgdata
|
||||
|
||||
def map_missing_deps(self, pkgs_data: Dict[str, dict], provided_map: Dict[str, Set[str]],
|
||||
remote_provided_map: Dict[str, Set[str]], remote_repo_map: Dict[str, str],
|
||||
aur_index: Iterable[str], deps_checked: Set[str], deps_data: Dict[str, dict],
|
||||
sort: bool, watcher: ProcessWatcher, choose_providers: bool = True,
|
||||
automatch_providers: bool = False) -> List[Tuple[str, str]]:
|
||||
automatch_providers: bool = False) -> Optional[List[Tuple[str, str]]]:
|
||||
sorted_deps = [] # it will hold the proper order to install the missing dependencies
|
||||
|
||||
missing_deps, repo_missing, aur_missing = set(), set(), set()
|
||||
@@ -325,7 +405,8 @@ class DependenciesAnalyser:
|
||||
remote_repo_map=remote_repo_map,
|
||||
repo_deps=repo_missing, aur_deps=aur_missing, watcher=watcher,
|
||||
deps_data=deps_data,
|
||||
automatch_providers=automatch_providers)
|
||||
automatch_providers=automatch_providers,
|
||||
dependent=p)
|
||||
else:
|
||||
version_pattern = '{}='.format(dep_name)
|
||||
version_found = [p for p in provided_map if p.startswith(version_pattern)]
|
||||
@@ -343,7 +424,8 @@ class DependenciesAnalyser:
|
||||
repo_deps=repo_missing, aur_deps=aur_missing,
|
||||
watcher=watcher,
|
||||
deps_data=deps_data,
|
||||
automatch_providers=automatch_providers)
|
||||
automatch_providers=automatch_providers,
|
||||
dependent=p)
|
||||
else:
|
||||
self._fill_missing_dep(dep_name=dep_name, dep_exp=dep, aur_index=aur_index,
|
||||
missing_deps=missing_deps,
|
||||
@@ -352,34 +434,11 @@ class DependenciesAnalyser:
|
||||
repo_deps=repo_missing, aur_deps=aur_missing,
|
||||
watcher=watcher,
|
||||
deps_data=deps_data,
|
||||
automatch_providers=automatch_providers)
|
||||
automatch_providers=automatch_providers,
|
||||
dependent=p)
|
||||
|
||||
if missing_deps:
|
||||
if repo_missing:
|
||||
with_single_providers = []
|
||||
|
||||
for d in missing_deps:
|
||||
if d[0] in repo_missing and d[0] not in deps_data:
|
||||
if d[1] == '__several__':
|
||||
deps_data[d[0]] = {'d': None, 'p': d[0], 'r': d[1]}
|
||||
else:
|
||||
with_single_providers.append(d[0])
|
||||
|
||||
if with_single_providers:
|
||||
data = pacman.map_updates_data(with_single_providers)
|
||||
|
||||
if data:
|
||||
deps_data.update(data)
|
||||
|
||||
if aur_missing:
|
||||
aur_threads = []
|
||||
for pkgname in aur_missing:
|
||||
t = Thread(target=self.__fill_aur_update_data, args=(pkgname, deps_data), daemon=True)
|
||||
t.start()
|
||||
aur_threads.append(t)
|
||||
|
||||
for t in aur_threads:
|
||||
t.join()
|
||||
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,
|
||||
deps_checked=deps_checked, sort=False, deps_data=deps_data,
|
||||
@@ -406,6 +465,51 @@ class DependenciesAnalyser:
|
||||
|
||||
return sorted_deps
|
||||
|
||||
def _fill_single_providers_data(self, all_missing_deps: Iterable[Tuple[str, str]], repo_missing_deps: Iterable[str], aur_missing_deps: Iterable[str], deps_data: Dict[str, dict]):
|
||||
"""
|
||||
fills the missing data of the single dependency providers since they are already considered dependencies
|
||||
(when several providers are available for given a dependency, the user must choose first)
|
||||
"""
|
||||
repo_providers_no_data, aur_providers_no_data = None, None
|
||||
|
||||
for dep_name, dep_repo in all_missing_deps:
|
||||
if dep_repo == '__several__':
|
||||
deps_data[dep_name] = {'d': None, 'p': {dep_name}, 'r': dep_repo}
|
||||
elif dep_name not in deps_data:
|
||||
if repo_missing_deps and dep_name in repo_missing_deps:
|
||||
if repo_providers_no_data is None:
|
||||
repo_providers_no_data = set()
|
||||
|
||||
repo_providers_no_data.add(dep_name)
|
||||
elif aur_missing_deps and dep_name in aur_missing_deps:
|
||||
if aur_providers_no_data is None:
|
||||
aur_providers_no_data = set()
|
||||
|
||||
aur_providers_no_data.add(dep_name)
|
||||
|
||||
aur_data_filler, aur_providers_data = None, None
|
||||
|
||||
if aur_providers_no_data:
|
||||
aur_providers_data = dict()
|
||||
aur_data_filler = Thread(target=self._fill_aur_updates_data,
|
||||
args=(aur_providers_no_data, aur_providers_data))
|
||||
aur_data_filler.start()
|
||||
|
||||
if repo_providers_no_data:
|
||||
repo_providers_data = pacman.map_updates_data(repo_providers_no_data)
|
||||
|
||||
if repo_providers_data:
|
||||
deps_data.update(repo_providers_data)
|
||||
|
||||
for pkgname, pkgdata in self.aur_client.gen_updates_data(aur_providers_no_data):
|
||||
deps_data[pkgname] = pkgdata
|
||||
|
||||
if aur_data_filler:
|
||||
aur_data_filler.join()
|
||||
|
||||
if aur_providers_data:
|
||||
deps_data.update(aur_providers_data)
|
||||
|
||||
def fill_providers_deps(self, missing_deps: List[Tuple[str, str]],
|
||||
provided_map: Dict[str, Set[str]], remote_repo_map: Dict[str, str],
|
||||
already_checked: Set[str], remote_provided_map: Dict[str, Set[str]],
|
||||
@@ -429,21 +533,45 @@ class DependenciesAnalyser:
|
||||
remote_provided_map)
|
||||
|
||||
if deps_providers:
|
||||
all_providers = set()
|
||||
providers_repos = {}
|
||||
repos_providers = set()
|
||||
|
||||
for providers in deps_providers.values():
|
||||
all_providers.update(providers)
|
||||
for provider in providers:
|
||||
if remote_repo_map.get(provider) == 'aur':
|
||||
providers_repos[provider] = 'aur'
|
||||
else:
|
||||
repos_providers.add(provider)
|
||||
|
||||
providers_repos = pacman.map_repositories(all_providers)
|
||||
providers_repos.update(pacman.map_repositories(repos_providers))
|
||||
selected_providers = confirmation.request_providers(deps_providers, providers_repos, watcher, self.i18n)
|
||||
|
||||
if not selected_providers:
|
||||
return
|
||||
else:
|
||||
providers_data = pacman.map_updates_data(
|
||||
selected_providers) # adding the chosen providers to re-check the missing deps
|
||||
provided_map.update(pacman.map_provided(remote=True,
|
||||
pkgs=selected_providers)) # adding the providers as "installed" packages
|
||||
# adding the chosen providers for re-checking the missing dependencies
|
||||
repo_selected, aur_selected = set(), set()
|
||||
|
||||
for provider in selected_providers:
|
||||
if provider in repos_providers:
|
||||
repo_selected.add(provider)
|
||||
else:
|
||||
aur_selected.add(provider)
|
||||
|
||||
providers_data = dict()
|
||||
|
||||
if repo_selected:
|
||||
providers_data.update(pacman.map_updates_data(repo_selected))
|
||||
# adding the providers as "installed" packages
|
||||
provided_map.update(pacman.map_provided(remote=True, pkgs=repo_selected))
|
||||
|
||||
if aur_selected:
|
||||
for pkgname, pkgdata in self.aur_client.gen_updates_data(aur_selected):
|
||||
providers_data[pkgname] = pkgdata
|
||||
for provider in pkgdata['p']: # adding the providers as "installed" packages
|
||||
currently_provided = provided_map.get(provider, set())
|
||||
provided_map[provider] = currently_provided
|
||||
currently_provided.add(pkgname)
|
||||
|
||||
providers_deps = self.map_missing_deps(pkgs_data=providers_data,
|
||||
provided_map=provided_map,
|
||||
@@ -457,6 +585,9 @@ class DependenciesAnalyser:
|
||||
choose_providers=True,
|
||||
automatch_providers=automatch_providers)
|
||||
|
||||
if providers_deps is None: # it means the user called off the installation process
|
||||
return
|
||||
|
||||
# cleaning the already mapped providers deps:
|
||||
to_remove = []
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from typing import Iterable
|
||||
from typing import Iterable, Optional
|
||||
|
||||
from bauh.api.abstract.handler import ProcessWatcher
|
||||
from bauh.api.abstract.view import MessageType
|
||||
@@ -13,11 +13,13 @@ def show_deps_not_installed(watcher: ProcessWatcher, pkgname: str, depnames: Ite
|
||||
type_=MessageType.ERROR)
|
||||
|
||||
|
||||
def show_dep_not_found(depname: str, i18n: I18n, watcher: ProcessWatcher):
|
||||
def show_dep_not_found(depname: str, i18n: I18n, watcher: ProcessWatcher, dependent: Optional[str] = None):
|
||||
|
||||
body = '<p>{}</p><p>{}</p><p></p><p>{}</p>'.format(i18n['arch.install.dep_not_found.body.l1'].format(bold(depname)),
|
||||
i18n['arch.install.dep_not_found.body.l2'],
|
||||
i18n['arch.install.dep_not_found.body.l3'])
|
||||
source = f" {bold('(' + dependent + ')')}" if dependent else ''
|
||||
|
||||
body = f"<p>{i18n['arch.install.dep_not_found.body.l1'].format(dep=bold(depname), source=source)}</p>" \
|
||||
f"<p><{i18n['arch.install.dep_not_found.body.l2']}</p>" \
|
||||
f"<p>{i18n['arch.install.dep_not_found.body.l3']}</p>"
|
||||
|
||||
watcher.show_message(title=i18n['arch.install.dep_not_found.title'].capitalize(),
|
||||
body=body,
|
||||
|
||||
@@ -195,7 +195,7 @@ arch.install.aur.unknown_key.title=Clau pública necessària
|
||||
arch.install.aur.unknown_key.body=Per a continuar amb la instal·lació de {} cal confiar en la clau pública següent {}
|
||||
arch.install.conflict.popup.body=Les aplicacions {} estan en conflicte. Heu de desinstal·lar una per a instal·lar l’altra. Voleu continuar?
|
||||
arch.install.conflict.popup.title=S’ha detectat un conflicte
|
||||
arch.install.dep_not_found.body.l1=No s’ha trobat la dependència requerida {} a l’AUR ni als dipòsits
|
||||
arch.install.dep_not_found.body.l1=No s’ha trobat la dependència requerida {dep}{source} a l’AUR ni als dipòsits
|
||||
arch.install.dep_not_found.body.l2=It might be a package database synchronization problem.
|
||||
arch.install.dep_not_found.body.l3=Operation cancelled.
|
||||
arch.install.dep_not_found.title=No s’ha trobat la dependència
|
||||
@@ -208,7 +208,6 @@ arch.install.optdep.error=Could not install the optional packages: {}
|
||||
arch.install.optdeps.request.body={} s’ha instal·lat correctament. Hi ha paquets opcionals associats que potser voldreu instal·lar
|
||||
arch.install.optdeps.request.help=Marqueu els que voleu
|
||||
arch.install.optdeps.request.title=Dependències opcionals
|
||||
arch.install.repo_pkg.error.aur_deps=It is not possible to install an AUR package as dependency of a repository package
|
||||
arch.installing.package=S’està instal·lant el paquet {}
|
||||
arch.checking_unnecessary_deps=Checking if there are packages no longer needed
|
||||
arch.makepkg.optimizing=Optimitzant la recopilació
|
||||
|
||||
@@ -195,7 +195,7 @@ arch.install.aur.unknown_key.body=Um mit der Installation von {} fortzufahren is
|
||||
arch.install.aur.unknown_key.title=Öffentlicher Schlüssel nötig
|
||||
arch.install.conflict.popup.body=Die Anwendungen {} können nicht gleichzeitig installiert sein. Du musst eine deinstallieren um die andere zu installieren. Fortfahren?
|
||||
arch.install.conflict.popup.title=Konflikt entdeckt
|
||||
arch.install.dep_not_found.body.l1=Nötige Abhängigkeit {} wurde weder im AUR noch in den standard Spiegelservern gefunden
|
||||
arch.install.dep_not_found.body.l1=Nötige Abhängigkeit {dep}{source} wurde weder im AUR noch in den standard Spiegelservern gefunden
|
||||
arch.install.dep_not_found.body.l2=It might be a package database synchronization problem.
|
||||
arch.install.dep_not_found.body.l3=Operation cancelled.
|
||||
arch.install.dep_not_found.title=Abhängigkeit nicht gefunden
|
||||
@@ -208,7 +208,6 @@ arch.install.optdep.error=Could not install the optional packages: {}
|
||||
arch.install.optdeps.request.body={} wurde erfolgreich installiert! Es gibt optionale zugehörige Pakete welche du vielleicht auch installieren möchtest
|
||||
arch.install.optdeps.request.help=Wähle entsprechende aus
|
||||
arch.install.optdeps.request.title=Optionale Abhängigkeiten
|
||||
arch.install.repo_pkg.error.aur_deps=It is not possible to install an AUR package as dependency of a repository package
|
||||
arch.installing.package=Paket {} installieren
|
||||
arch.checking_unnecessary_deps=Checking if there are packages no longer needed
|
||||
arch.makepkg.optimizing=Optimiert die Zusammenstellung
|
||||
|
||||
@@ -195,7 +195,7 @@ arch.install.aur.unknown_key.body=To continue {} installation is necessary to tr
|
||||
arch.install.aur.unknown_key.title=Public key required
|
||||
arch.install.conflict.popup.body=The applications {} are in conflict. You must uninstall one to install the other. Continue ?
|
||||
arch.install.conflict.popup.title=Conflict detected
|
||||
arch.install.dep_not_found.body.l1=Required dependency {} was not found in AUR nor in the repositories.
|
||||
arch.install.dep_not_found.body.l1=Required dependency {dep}{source} was not found on the repositories nor AUR.
|
||||
arch.install.dep_not_found.body.l2=It might be a package database synchronization problem.
|
||||
arch.install.dep_not_found.body.l3=Operation cancelled.
|
||||
arch.install.dep_not_found.title=Dependency not found
|
||||
@@ -208,7 +208,6 @@ arch.install.optdep.error=Could not install the optional packages: {}
|
||||
arch.install.optdeps.request.body={} was succesfully installed ! There are some optional associated packages that you might want to install
|
||||
arch.install.optdeps.request.help=Check those you want
|
||||
arch.install.optdeps.request.title=Optional dependencies
|
||||
arch.install.repo_pkg.error.aur_deps=It is not possible to install an AUR package as dependency of a repository package
|
||||
arch.installing.package=Installing {} package
|
||||
arch.checking_unnecessary_deps=Checking if there are packages no longer needed
|
||||
arch.makepkg.optimizing=Optimizing the compilation
|
||||
|
||||
@@ -195,7 +195,7 @@ arch.install.aur.unknown_key.body=Para continuar la instalación de {} es necesa
|
||||
arch.install.aur.unknown_key.title=Clave pública necesaria
|
||||
arch.install.conflict.popup.body=Los aplicativos {} estan en conflicto. Debe desinstalar uno para instalar el otro. ¿Continuar?
|
||||
arch.install.conflict.popup.title=Conflicto detectado
|
||||
arch.install.dep_not_found.body.l1=No se encontró la dependencia requerida {} en AUR ni en los repositorios.
|
||||
arch.install.dep_not_found.body.l1=No se encontró la dependencia requerida {dep}{source} en AUR ni en los repositorios.
|
||||
arch.install.dep_not_found.body.l2=Puede ser un problema de sincronización de la base de paquetes.
|
||||
arch.install.dep_not_found.body.l3=Operación cancelada.
|
||||
arch.install.dep_not_found.title=Dependencia no encontrada
|
||||
@@ -208,7 +208,6 @@ arch.install.optdep.error=No se pudo instalar los paquetes opcionales: {}
|
||||
arch.install.optdeps.request.body=¡{} se instaló correctamente! Hay algunos paquetes opcionales asociados que es posible que desee instalar
|
||||
arch.install.optdeps.request.help=Marque los que desee
|
||||
arch.install.optdeps.request.title=Dependencias opcionales
|
||||
arch.install.repo_pkg.error.aur_deps=It is not possible to install an AUR package as dependency of a repository package
|
||||
arch.installing.package=Instalando el paquete {}
|
||||
arch.checking_unnecessary_deps=Verificando se hay paquetes innecesarios
|
||||
arch.makepkg.optimizing=Optimizing the compilation
|
||||
|
||||
@@ -195,7 +195,7 @@ arch.install.aur.unknown_key.body=Pour continuer à installer {} il faut faire c
|
||||
arch.install.aur.unknown_key.title=Clé publique requise
|
||||
arch.install.conflict.popup.body=Les applications {} sont en conflit. Il faut en désinstaller une pour installer l'autre. Continuer ?
|
||||
arch.install.conflict.popup.title=Conflit détecté
|
||||
arch.install.dep_not_found.body.l1=Dépendance requise {} absente d AUR ou des dépôts.
|
||||
arch.install.dep_not_found.body.l1=Dépendance requise {dep}{source} absente d AUR ou des dépôts.
|
||||
arch.install.dep_not_found.body.l2=Sans doute un problème de synchronisation de base de données.
|
||||
arch.install.dep_not_found.body.l3=Operation annulée.
|
||||
arch.install.dep_not_found.title=Dependance non trouvée
|
||||
@@ -208,7 +208,6 @@ arch.install.optdep.error=Impossible d'installer les paquets optionnels: {}
|
||||
arch.install.optdeps.request.body={} installé avec succès ! Il y a des paquets optionnels que vous pouvez installer
|
||||
arch.install.optdeps.request.help=Cochez ceux que vous désirez
|
||||
arch.install.optdeps.request.title=Dépendances optionnelles
|
||||
arch.install.repo_pkg.error.aur_deps=Impossible d'installer un paquet AUR comme une dépendance d'un paquet venant d'un dépôt
|
||||
arch.installing.package=Installation du paquet {}
|
||||
arch.checking_unnecessary_deps=Calcul des paquets devenus inutiles
|
||||
arch.makepkg.optimizing=Optimisation de la compilation
|
||||
|
||||
@@ -195,7 +195,7 @@ arch.install.aur.unknown_key.body=Per continuare {} l'installazione è necessari
|
||||
arch.install.aur.unknown_key.title=Chiave pubblica richiesta
|
||||
arch.install.conflict.popup.body=Le applicazioni {} sono in conflitto. È necessario disinstallarne una per installare l'altra. Continua ?
|
||||
arch.install.conflict.popup.title=Conflitto rilevato
|
||||
arch.install.dep_not_found.body.l1=La dipendenza richiesta {} non è stata trovata in AUR né nei depositos.
|
||||
arch.install.dep_not_found.body.l1=La dipendenza richiesta {dep}{source} non è stata trovata in AUR né nei depositos.
|
||||
arch.install.dep_not_found.body.l2=It might be a package database synchronization problem.
|
||||
arch.install.dep_not_found.body.l3=Operation cancelled.
|
||||
arch.install.dep_not_found.title=Dipendenza non trovata
|
||||
@@ -208,7 +208,6 @@ arch.install.optdep.error=Could not install the optional packages: {}
|
||||
arch.install.optdeps.request.body={} è stato installato con successo! Ci sono alcuni pacchetti associati opzionali che potresti voler installare
|
||||
arch.install.optdeps.request.help=Controlla quelli che vuoi
|
||||
arch.install.optdeps.request.title=Dipendenze opzionali
|
||||
arch.install.repo_pkg.error.aur_deps=It is not possible to install an AUR package as dependency of a repository package
|
||||
arch.installing.package=Installazione del pacchetto {}
|
||||
arch.checking_unnecessary_deps=Checking if there are packages no longer needed
|
||||
arch.makepkg.optimizing=Ottimizzando la compilazione
|
||||
|
||||
@@ -194,7 +194,7 @@ arch.install.aur.unknown_key.body=Para continuar a instalação de {} é ncessá
|
||||
arch.install.aur.unknown_key.title=Chave pública necessária
|
||||
arch.install.conflict.popup.body=Os aplicativos {} estão em conflito. Você precisa desinstalar um para instalar o outro. Continuar ?
|
||||
arch.install.conflict.popup.title=Conflito detectado
|
||||
arch.install.dep_not_found.body.l1=A dependência {} não foi encontrado no AUR nem nos repositórios.
|
||||
arch.install.dep_not_found.body.l1=A dependência {dep}{source} não foi encontrado no AUR nem nos repositórios.
|
||||
arch.install.dep_not_found.body.l2=Pode ser um problema de sincronização das bases de pacotes.
|
||||
arch.install.dep_not_found.body.l3=Operação cancelada.
|
||||
arch.install.dep_not_found.title=Dependência não encontrada
|
||||
@@ -207,7 +207,6 @@ arch.install.optdep.error=Não foi possível instalar os pacotes opcionais: {}
|
||||
arch.install.optdeps.request.body={} foi instalado com sucesso ! Existem alguns pacotes opcionais associados que você talvez queira instalar
|
||||
arch.install.optdeps.request.help=Marque os desejados
|
||||
arch.install.optdeps.request.title=Dependências opcionais
|
||||
arch.install.repo_pkg.error.aur_deps=Não é possível instalar um pacote do AUR como dependência de um pacote de repositório
|
||||
arch.installing.package=Instalando o pacote {}
|
||||
arch.checking_unnecessary_deps=Verificando se há pacotes não mais necessários
|
||||
arch.makepkg.optimizing=Otimizando a compilação
|
||||
|
||||
@@ -195,7 +195,7 @@ arch.install.aur.unknown_key.body=Для продолжения установк
|
||||
arch.install.aur.unknown_key.title=Требуется открытый ключ
|
||||
arch.install.conflict.popup.body=Приложения {} находятся в конфликте. Вы должны удалить одно, чтобы установить другоое. Продолжить ?
|
||||
arch.install.conflict.popup.title=Обнаружен конфликт
|
||||
arch.install.dep_not_found.body.l1=Требуемая зависимость {} не была найдена ни в AUR, ни в зеркалах по умолчанию.
|
||||
arch.install.dep_not_found.body.l1=Требуемая зависимость {dep}{source} не была найдена ни в AUR, ни в зеркалах по умолчанию.
|
||||
arch.install.dep_not_found.body.l2=It might be a package database synchronization problem.
|
||||
arch.install.dep_not_found.body.l3=Operation cancelled.
|
||||
arch.install.dep_not_found.title=Зависимость не найдена
|
||||
@@ -208,7 +208,6 @@ arch.install.optdep.error=Could not install the optional packages: {}
|
||||
arch.install.optdeps.request.body={} успешно установлен ! Есть некоторые дополнительные связанные пакеты, которые вы можете установить
|
||||
arch.install.optdeps.request.help=Отметьте те, которые вы хотите установить
|
||||
arch.install.optdeps.request.title=Необязательные зависимости
|
||||
arch.install.repo_pkg.error.aur_deps=It is not possible to install an AUR package as dependency of a repository package
|
||||
arch.installing.package=Установка пакета {}
|
||||
arch.checking_unnecessary_deps=Checking if there are packages no longer needed
|
||||
arch.makepkg.optimizing=Оптимизация компиляции
|
||||
|
||||
@@ -195,7 +195,7 @@ arch.install.aur.unknown_key.body=Yüklemeye devam etmek için {} aşağıdaki o
|
||||
arch.install.aur.unknown_key.title=Ortak anahtar gerekli
|
||||
arch.install.conflict.popup.body={} Uygulamaları çakışıyor. Diğerini kurmak için birini kaldırmalısınız. Devam et ?
|
||||
arch.install.conflict.popup.title=Çakışma tespit edildi
|
||||
arch.install.dep_not_found.body.l1=Gerekli bağımlılık {} ne AUR ne de resmi depolarda bulunamadı.
|
||||
arch.install.dep_not_found.body.l1=Gerekli bağımlılık {dep}{source} ne AUR ne de resmi depolarda bulunamadı.
|
||||
arch.install.dep_not_found.body.l2=Bir paket veritabanı senkronizasyon sorunu olabilir.
|
||||
arch.install.dep_not_found.body.l3=Operation cancelled.
|
||||
arch.install.dep_not_found.title=Bağımlılık bulunamadı
|
||||
@@ -208,7 +208,6 @@ arch.install.optdep.error=Tercihe bağlı paketler yüklenemedi: {}
|
||||
arch.install.optdeps.request.body={} başarıyla yüklendi! Yüklemek isteyebileceğiniz bazı tercihe bağlı bağımlılıklar vardır
|
||||
arch.install.optdeps.request.help=İstediklerinizi kontrol edin
|
||||
arch.install.optdeps.request.title=İsteğe bağlı bağımlılıklar
|
||||
arch.install.repo_pkg.error.aur_deps=Depodaki paketin bağımlılığı olarak bir AUR paketi kurmak mümkün değildir
|
||||
arch.installing.package={} Paketi yükleniyor
|
||||
arch.checking_unnecessary_deps=Artık gerekli olmayan paketler olup olmadığını kontrol et
|
||||
arch.makepkg.optimizing=Derlemeyi optimize et
|
||||
|
||||
Reference in New Issue
Block a user