diff --git a/CHANGELOG.md b/CHANGELOG.md index 617af3b3..1a9b88c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,36 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## [0.9.26] 2022-01-31 + +### Improvements +- Arch + - not rechecking sub-dependencies of an AUR dependency to be installed + - allowing AUR packages to be installed as dependencies of a repository package + - always listing repository packages as primary options when multiple providers for a given dependency are available + - installation: explicitly marking installed dependent packages as "dependencies" (`--asdeps`) + - settings: + - "Auto-define dependency providers" property renamed to "Auto-match dependency by name" + - new property 'prefer_repository_provider': automatically picks the single package from the repositories among several external (AUR) available as the provider for a given dependency + +### Fixes +- General + - not handling unicode decode errors when reading a subprocess output + +- Arch + - not upgrading a package when a dependent package relies on a specific version with epoch (e.g: alsa-plugins 1:1.2.6-1 would not be upgraded to 1:1.2.6-2 because lib32-alsa-plugins relies on 1:1.2.6) + - not informing all the provided packages on the transaction context to the dependency sorting algorithm (could lead to a wrong installation order) + - not displaying all possible AUR providers for a given dependency + - not displaying any substatus when retrieving packages (pacman) + +- UI: + - settings panel: confirmation dialog icon when launched alone + +### UI + - new logo by [DN-debug](https://github.com/DN-debug) + - new dark theme (**knight**) based on Kimi-dark gtk by [DN-debug](https://github.com/DN-debug) + + ## [0.9.25] 2021-12-24 ### Improvements - General diff --git a/README.md b/README.md index b3d4e5bd..da06f925 100644 --- a/README.md +++ b/README.md @@ -281,6 +281,7 @@ suggest_unneeded_uninstall: false # if the dependencies apparently no longer ne suggest_optdep_uninstall: false # if the optional dependencies associated with uninstalled packages should be suggested for uninstallation. Only the optional dependencies that are not dependencies of other packages will be suggested. Default: false (to prevent new users from making mistakes) categories_exp: 24 # It defines the expiration time (in HOURS) of the packages categories mapping file stored in disc. Use 0 so that it is always updated during initialization. aur_rebuild_detector: true # it checks if packages built with old library versions require to be rebuilt. If a package needs to be rebuilt, it will be marked for update ('rebuild-detector' must be installed). Default: true. +prefer_repository_provider: true # when there is just one repository provider for a given a dependency and several from AUR, it will be automatically picked. ``` diff --git a/bauh/__init__.py b/bauh/__init__.py index 1030f2e3..14008bec 100644 --- a/bauh/__init__.py +++ b/bauh/__init__.py @@ -1,4 +1,4 @@ -__version__ = '0.9.25' +__version__ = '0.9.26' __app_name__ = 'bauh' import os diff --git a/bauh/commons/system.py b/bauh/commons/system.py index 9aa3e4f4..996d4d98 100644 --- a/bauh/commons/system.py +++ b/bauh/commons/system.py @@ -130,7 +130,12 @@ def handle(self, process: SystemProcess, error_output: StringIO = None, output_h if not process.skip_stdout: for output in process.subproc.stdout: - line = output.decode().strip() + + try: + line = output.decode().strip() + except UnicodeDecodeError: + line = None + if line: self._notify_watcher(line) @@ -148,7 +153,11 @@ def handle(self, process: SystemProcess, error_output: StringIO = None, output_h for output in process.subproc.stderr: if output: - line = output.decode().strip() + try: + line = output.decode().strip() + except UnicodeDecodeError: + line = None + if line: self._notify_watcher(line) @@ -181,7 +190,10 @@ def handle_simple(self, proc: SimpleProcess, output_handler=None, notify_watcher output = StringIO() for o in proc.instance.stdout: if o: - line = o.decode() + try: + line = o.decode() + except UnicodeDecodeError: + continue output.write(line) @@ -223,7 +235,7 @@ def handle_simple(self, proc: SimpleProcess, output_handler=None, notify_watcher def run_cmd(cmd: str, expected_code: int = 0, ignore_return_code: bool = False, print_error: bool = True, cwd: str = '.', global_interpreter: bool = USE_GLOBAL_INTERPRETER, extra_paths: Set[str] = None, - custom_user: Optional[str] = None) -> str: + custom_user: Optional[str] = None) -> Optional[str]: """ runs a given command and returns its default output :return: @@ -240,7 +252,12 @@ def run_cmd(cmd: str, expected_code: int = 0, ignore_return_code: bool = False, final_cmd = f"runuser -u {custom_user} -- {cmd}" if custom_user else cmd res = subprocess.run(final_cmd, **args) - return res.stdout.decode() if ignore_return_code or res.returncode == expected_code else None + + if ignore_return_code or res.returncode == expected_code: + try: + return res.stdout.decode() + except UnicodeDecodeError: + pass def new_subprocess(cmd: List[str], cwd: str = '.', shell: bool = False, stdin = None, @@ -306,7 +323,13 @@ def get_human_size_str(size) -> str: def run(cmd: List[str], success_code: int = 0, custom_user: Optional[str] = None) -> Tuple[bool, str]: final_cmd = ['runuser', '-u', custom_user, '--', *cmd] if custom_user else cmd p = subprocess.run(final_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.DEVNULL) - return p.returncode == success_code, p.stdout.decode() + + try: + output = p.stdout.decode() + except UnicodeDecodeError: + output = '' + + return p.returncode == success_code, output def check_active_services(*names: str) -> Dict[str, bool]: @@ -351,4 +374,12 @@ def execute(cmd: str, shell: bool = False, cwd: Optional[str] = None, output: bo params['env'] = custom_env p = subprocess.run(**params) - return p.returncode, p.stdout.decode() if p.stdout else None + + output = None + if p.stdout: + try: + output = p.stdout.decode() + except UnicodeDecodeError: + output = None + + return p.returncode, output diff --git a/bauh/gems/arch/aur.py b/bauh/gems/arch/aur.py index 5716f346..e5054e45 100644 --- a/bauh/gems/arch/aur.py +++ b/bauh/gems/arch/aur.py @@ -2,7 +2,7 @@ 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 @@ def get_info(self, names: Iterable[str]) -> List[dict]: 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 @@ def read_index(self) -> Iterable[str]: 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() diff --git a/bauh/gems/arch/config.py b/bauh/gems/arch/config.py index 5a88fd14..b17800e3 100644 --- a/bauh/gems/arch/config.py +++ b/bauh/gems/arch/config.py @@ -39,4 +39,5 @@ def get_default_config(self) -> dict: 'aur_idx_exp': 1, 'categories_exp': 24, 'aur_rebuild_detector': False, - "aur_rebuild_detector_no_bin": True} + "aur_rebuild_detector_no_bin": True, + "prefer_repository_provider": True} diff --git a/bauh/gems/arch/confirmation.py b/bauh/gems/arch/confirmation.py index 544e0438..a8d03f08 100644 --- a/bauh/gems/arch/confirmation.py +++ b/bauh/gems/arch/confirmation.py @@ -79,15 +79,22 @@ def request_providers(providers_map: Dict[str, Set[str]], repo_map: Dict[str, st for dep, providers in providers_map.items(): opts = [] - providers_list = [*providers] - providers_list.sort() + repo_providers, aur_providers = {}, {} - for p in providers_list: + for p in providers: repo = repo_map.get(p, 'aur') - opts.append(InputOption(label=p, - value=p, - icon_path=aur_icon_path if repo == 'aur' else repo_icon_path, - tooltip='{}: {}'.format(i18n['repository'].capitalize(), repo))) + + if repo == 'aur': + aur_providers[p] = repo + else: + repo_providers[p] = repo + + for current_providers in (repo_providers, aur_providers): + for pname, repo in sorted(current_providers.items()): + opts.append(InputOption(label=pname, + value=pname, + icon_path=aur_icon_path if repo == 'aur' else repo_icon_path, + tooltip='{}: {}'.format(i18n['repository'].capitalize(), repo))) form.components.append(SingleSelectComponent(label=bold(dep.lower()), options=opts, diff --git a/bauh/gems/arch/controller.py b/bauh/gems/arch/controller.py index 5c67fdd9..a93d9442 100644 --- a/bauh/gems/arch/controller.py +++ b/bauh/gems/arch/controller.py @@ -209,7 +209,7 @@ def __init__(self, context: ApplicationContext, disk_cache_updater: Optional[Arc 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 @@ -1760,7 +1760,8 @@ def _install_deps(self, context: TransactionContext, deps: List[Tuple[str, str]] status_handler.start() installed, _ = context.handler.handle_simple(pacman.install_as_process(pkgpaths=repo_dep_names, root_password=context.root_password, - file=False), + file=False, + as_deps=True), output_handler=status_handler.handle) if installed: @@ -2082,6 +2083,7 @@ def _list_missing_deps(self, context: TransactionContext) -> List[Tuple[str, str remote_provided_map=context.get_remote_provided_map(), remote_repo_map=context.get_remote_repo_map(), automatch_providers=context.config['automatch_providers'], + prefer_repository_provider=context.config['prefer_repository_provider'], watcher=context.watcher) tf = time.time() @@ -2108,9 +2110,10 @@ def _handle_missing_deps(self, context: TransactionContext) -> bool: return True def _handle_aur_package_deps_and_keys(self, context: TransactionContext) -> bool: - handled_deps = self._handle_missing_deps(context) - if not handled_deps: - return False + if not context.dependency: + handled_deps = self._handle_missing_deps(context) + if not handled_deps: + return False check_res = makepkg.check(project_dir=context.project_dir, optimize=bool(context.config['optimize']), @@ -2196,6 +2199,7 @@ def _install_optdeps(self, context: TransactionContext) -> bool: remote_provided_map=remote_provided_map, remote_repo_map=remote_repo_map, automatch_providers=context.config['automatch_providers'], + prefer_repository_provider=context.config['prefer_repository_provider'], sort=False) if missing_deps is None: @@ -2332,7 +2336,7 @@ def _install(self, context: TransactionContext) -> bool: 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) @@ -2356,7 +2360,8 @@ def _install(self, context: TransactionContext) -> bool: 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: @@ -2423,7 +2428,8 @@ def _call_pacman_install(self, context: TransactionContext, to_install: List[str root_password=context.root_password, file=context.has_install_files(), pkgdir=context.project_dir, - overwrite_conflicting_files=overwrite_files), + overwrite_conflicting_files=overwrite_files, + as_deps=context.dependency), output_handler=status_handler.handle if status_handler else None) def _handle_install_call(self, context: TransactionContext, to_install: List[str], status_handler) -> bool: @@ -2599,29 +2605,9 @@ def install(self, pkg: ArchPackage, root_password: str, disk_loader: Optional[Di 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: @@ -2841,6 +2827,12 @@ def get_settings(self, screen_width: int, screen_height: int) -> Optional[ViewCo tooltip_key='arch.config.automatch_providers.tip', value=bool(arch_config['automatch_providers']), max_width=max_width), + self._gen_bool_selector(id_='prefer_repo_provider', + label_key='arch.config.prefer_repository_provider', + tooltip_key='arch.config.prefer_repository_provider.tip', + value=bool(arch_config['prefer_repository_provider']), + max_width=max_width, + tooltip_params=['AUR']), self._gen_bool_selector(id_='check_dependency_breakage', label_key='arch.config.check_dependency_breakage', tooltip_key='arch.config.check_dependency_breakage.tip', @@ -2953,6 +2945,7 @@ def save_settings(self, component: PanelComponent) -> Tuple[bool, Optional[List[ arch_config['mirrors_sort_limit'] = form.get_component('mirrors_sort_limit').get_int_value() arch_config['repositories_mthread_download'] = form.get_component('mthread_download').get_selected() arch_config['automatch_providers'] = form.get_single_select_component('autoprovs').get_selected() + arch_config['prefer_repository_provider'] = form.get_single_select_component('prefer_repo_provider').get_selected() arch_config['edit_aur_pkgbuild'] = form.get_single_select_component('edit_aur_pkgbuild').get_selected() arch_config['aur_remove_build_dir'] = form.get_single_select_component('aur_remove_build_dir').get_selected() arch_config['aur_build_dir'] = form.get_component('aur_build_dir').file_path diff --git a/bauh/gems/arch/dependencies.py b/bauh/gems/arch/dependencies.py index a8af0530..34b94f4d 100644 --- a/bauh/gems/arch/dependencies.py +++ b/bauh/gems/arch/dependencies.py @@ -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 @@ 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 @@ def _fill_repository(self, name: str, output: List[Tuple[str, str]]): 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 @@ def map_known_missing_deps(self, known_deps: Dict[str, str], watcher: ProcessWat 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 @@ def map_known_missing_deps(self, known_deps: Dict[str, str], watcher: ProcessWat 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,187 @@ def _fill_missing_dep(self, dep_name: str, dep_exp: str, aur_index: Iterable[str providers = {match} if providers: - no_mapped_data = {p for p in providers if - p not in deps_data} # checking providers with no mapped data - - if no_mapped_data: - providers_data = pacman.map_updates_data(no_mapped_data) + providers_no_provided_data = {p for p in providers if p not in deps_data} + missing_providers_data = None - if not providers_data: - raise Exception("Could not retrieve the info from providers: {}".format(no_mapped_data)) + if providers_no_provided_data: + missing_providers_data = pacman.map_updates_data(providers_no_provided_data) - deps_data.update(providers_data) # adding missing providers data + if not missing_providers_data: + raise Exception(f"Could not retrieve information from providers: " + f"{', '.join(providers_no_provided_data)}") - 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 '==' + data_not_found = {p for p in providers if p not in missing_providers_data} - for p in providers: - provided = deps_data[p]['p'] + if data_not_found: + raise Exception(f"Could not retrieve information from providers: " + f"{', '.join(data_not_found)}") - for provided_exp in provided: - split_dep = self.re_dep_operator.split(provided_exp) + split_informed_dep = self.re_dep_operator.split(dep_exp) - if len(split_dep) == 3 and split_dep[0] == dep_name: - version_provided = split_dep[2] + version_required = split_informed_dep[2] + exp_op = split_informed_dep[1] if split_informed_dep[1] != '=' else '==' - if match_required_version(version_provided, exp_op, version_required): - matched_providers.add(p) - break + for p in providers: + info = deps_data.get(p) - providers = matched_providers - except: - traceback.print_exc() + if not info and missing_providers_data: + info = missing_providers_data[p] - if providers: - if len(providers) > 1: - dep_data = None + for provided_exp in info['p']: + split_dep = self.re_dep_operator.split(provided_exp) - if automatch_providers: - exact_matches = [p for p in providers if p == dep_name] + if len(split_dep) == 3 and split_dep[0] == dep_name: + version_provided = split_dep[2] - if exact_matches: - dep_data = (exact_matches[0], remote_repo_map.get(exact_matches[0])) + if match_required_version(version_provided, exp_op, version_required): + yield p, remote_repo_map.get(p), info + break - if not dep_data: - dep_data = (dep_name, '__several__') + 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: + yield from self.aur_client.gen_updates_data((dep_name,)) + return else: - real_name = providers.pop() - dep_data = (real_name, remote_repo_map.get(real_name)) + 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 - repo_deps.add(dep_data[0]) - missing_deps.add(dep_data) + aur_search = self.aur_client.search(dep_name) - elif aur_index and dep_name in aur_index: + if aur_search: if dep_name == dep_exp: - aur_deps.add(dep_name) - missing_deps.add((dep_name, 'aur')) + version_required, exp_op = None, None else: - dep_info = self.aur_client.get_info({dep_name}) + 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 '==' - if not dep_info: - self.__raise_dependency_not_found(dep_exp, watcher) - 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: - dep_version = dep_info[0]['Version'] + if not version_required or match_required_version(pkgdata['v'], exp_op, + version_required): + yield pkgname, pkgdata except: + self._log.warning(f"Could not compare AUR package '{pkgname}' version '{pkgdata['v']}' " + f"with the dependency expression '{dep_exp}'") traceback.print_exc() - return self.__raise_dependency_not_found(dep_exp, watcher) - split_informed_dep = self.re_dep_operator.split(dep_exp) - try: - version_required = split_informed_dep[2] - exp_op = split_informed_dep[1].strip() + 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, prefer_repository_provider: bool, dependent: Optional[str] = None): - if match_required_version(dep_version, exp_op, version_required): - 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) + 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)) + + if prefer_repository_provider and repo_matches and len(repo_matches) == 1: + pkg_name, pkg_repo, pkg_data = repo_matches[0] + missing_deps.add((pkg_name, pkg_repo)) + repo_deps.add(pkg_name) + + if pkg_data: + deps_data[pkg_name] = pkg_data + + return + + 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 - def __raise_dependency_not_found(self, dep_exp: str, watcher: Optional[ProcessWatcher]): + 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, prefer_repository_provider: 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 +415,9 @@ def map_missing_deps(self, pkgs_data: Dict[str, dict], provided_map: Dict[str, S 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, + prefer_repository_provider=prefer_repository_provider, + dependent=p) else: version_pattern = '{}='.format(dep_name) version_found = [p for p in provided_map if p.startswith(version_pattern)] @@ -343,7 +435,9 @@ def map_missing_deps(self, pkgs_data: Dict[str, dict], provided_map: Dict[str, S repo_deps=repo_missing, aur_deps=aur_missing, watcher=watcher, deps_data=deps_data, - automatch_providers=automatch_providers) + automatch_providers=automatch_providers, + prefer_repository_provider=prefer_repository_provider, + dependent=p) else: self._fill_missing_dep(dep_name=dep_name, dep_exp=dep, aur_index=aur_index, missing_deps=missing_deps, @@ -352,34 +446,12 @@ def map_missing_deps(self, pkgs_data: Dict[str, dict], provided_map: Dict[str, S repo_deps=repo_missing, aur_deps=aur_missing, watcher=watcher, deps_data=deps_data, - automatch_providers=automatch_providers) + automatch_providers=automatch_providers, + prefer_repository_provider=prefer_repository_provider, + 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, @@ -387,7 +459,8 @@ def map_missing_deps(self, pkgs_data: Dict[str, dict], provided_map: Dict[str, S remote_provided_map=remote_provided_map, remote_repo_map=remote_repo_map, automatch_providers=automatch_providers, - choose_providers=False) + choose_providers=False, + prefer_repository_provider=prefer_repository_provider) if missing_subdeps: missing_deps.update(missing_subdeps) @@ -402,15 +475,62 @@ def map_missing_deps(self, pkgs_data: Dict[str, dict], provided_map: Dict[str, S remote_provided_map=remote_provided_map, remote_repo_map=remote_repo_map, watcher=watcher, sort=sort, already_checked=deps_checked, aur_idx=aur_index, deps_data=deps_data, - automatch_providers=automatch_providers) + automatch_providers=automatch_providers, + prefer_repository_provider=prefer_repository_provider) 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]], deps_data: Dict[str, dict], aur_idx: Iterable[str], sort: bool, - watcher: ProcessWatcher, automatch_providers: bool) -> Optional[List[Tuple[str, str]]]: + watcher: ProcessWatcher, automatch_providers: bool, + prefer_repository_provider: bool) -> Optional[List[Tuple[str, str]]]: """ :param missing_deps: :param provided_map: @@ -422,6 +542,7 @@ def fill_providers_deps(self, missing_deps: List[Tuple[str, str]], :param sort: :param watcher: :param automatch_providers + :param prefer_repository_provider :return: all deps sorted or None if the user declined the providers options """ @@ -429,21 +550,45 @@ def fill_providers_deps(self, missing_deps: List[Tuple[str, str]], 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, @@ -455,7 +600,11 @@ def fill_providers_deps(self, missing_deps: List[Tuple[str, str]], remote_repo_map=remote_repo_map, watcher=watcher, choose_providers=True, - automatch_providers=automatch_providers) + automatch_providers=automatch_providers, + prefer_repository_provider=prefer_repository_provider) + + if providers_deps is None: # it means the user called off the installation process + return # cleaning the already mapped providers deps: to_remove = [] @@ -479,7 +628,8 @@ def fill_providers_deps(self, missing_deps: List[Tuple[str, str]], remote_repo_map=remote_repo_map, already_checked=already_checked, aur_idx=aur_idx, remote_provided_map=remote_provided_map, deps_data=deps_data, sort=False, watcher=watcher, - automatch_providers=automatch_providers): + automatch_providers=automatch_providers, + prefer_repository_provider=prefer_repository_provider): return if sort: diff --git a/bauh/gems/arch/message.py b/bauh/gems/arch/message.py index d3127b40..1a43fbac 100644 --- a/bauh/gems/arch/message.py +++ b/bauh/gems/arch/message.py @@ -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 = '
{}
{}
{}
'.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"{i18n['arch.install.dep_not_found.body.l1'].format(dep=bold(depname), source=source)}
" \ + f"<{i18n['arch.install.dep_not_found.body.l2']}
" \ + f"{i18n['arch.install.dep_not_found.body.l3']}
" watcher.show_message(title=i18n['arch.install.dep_not_found.title'].capitalize(), body=body, diff --git a/bauh/gems/arch/output.py b/bauh/gems/arch/output.py index f5881cb3..b6e211f7 100644 --- a/bauh/gems/arch/output.py +++ b/bauh/gems/arch/output.py @@ -1,7 +1,7 @@ import logging import time from threading import Thread -from typing import Set +from typing import Optional, Collection from bauh.api.abstract.handler import ProcessWatcher from bauh.commons.html import bold @@ -10,13 +10,13 @@ class TransactionStatusHandler(Thread): - def __init__(self, watcher: ProcessWatcher, i18n: I18n, names: Set[str], logger: logging.Logger, + def __init__(self, watcher: ProcessWatcher, i18n: I18n, names: Optional[Collection[str]], logger: logging.Logger, percentage: bool = True, downloading: int = 0, pkgs_to_remove: int = 0): super(TransactionStatusHandler, self).__init__(daemon=True) self.watcher = watcher self.i18n = i18n - self.pkgs_to_sync = len(names) self.names = names + self.pkgs_to_sync = len(names) if names else 0 self.pkgs_to_remove = pkgs_to_remove self.downloading = downloading self.upgrading = 0 @@ -31,7 +31,8 @@ def __init__(self, watcher: ProcessWatcher, i18n: I18n, names: Set[str], logger: 'loading package files': 'loading_files', 'checking for file conflicts': 'conflicts', 'checking available disk space': 'disk_space', - ':: Running pre-transaction hooks': 'pre_hooks'} + ':: running pre-transaction hooks': 'pre_hooks', + ':: retrieving packages': 'retrieve_pkgs'} def gen_percentage(self) -> str: if self.percentage: @@ -56,13 +57,13 @@ def _handle(self, output: str) -> bool: else: self.watcher.change_substatus('{} {}'.format(self.i18n['uninstalling'].capitalize(), output_split[1].strip())) - elif output_split[0].lower() == 'downloading' and (not self.names or (n for n in self.names if n in output_split[1])): + elif output_split[1].lower().startswith('downloading') and (not self.names or (n for n in self.names if output_split[0].startswith(n))): if self.downloading < self.pkgs_to_sync: perc = self.gen_percentage() self.downloading += 1 self.watcher.change_substatus('{}[{}/{}] {} {} {}'.format(perc, self.downloading, self.pkgs_to_sync, bold('[pacman]'), - self.i18n['downloading'].capitalize(), output_split[1].strip())) + self.i18n['downloading'].capitalize(), output_split[0].strip())) elif output_split[0].lower() == 'upgrading' and (not self.names or output_split[1].split('.')[0] in self.names): if self.get_performed() < self.pkgs_to_sync: perc = self.gen_percentage() @@ -86,7 +87,7 @@ def _handle(self, output: str) -> bool: output_split[1].strip())) else: substatus_found = False - lower_output = output.lower() + lower_output = output.lower().strip() for msg, key in self.accepted.items(): if lower_output.startswith(msg): self.watcher.change_substatus(self.i18n['arch.substatus.{}'.format(key)].capitalize()) diff --git a/bauh/gems/arch/pacman.py b/bauh/gems/arch/pacman.py index c7f26168..7835a602 100644 --- a/bauh/gems/arch/pacman.py +++ b/bauh/gems/arch/pacman.py @@ -147,7 +147,7 @@ def map_installed(names: Iterable[str] = None) -> dict: # returns a dict with w def install_as_process(pkgpaths: Iterable[str], root_password: str, file: bool, pkgdir: str = '.', - overwrite_conflicting_files: bool = False, simulate: bool = False) -> SimpleProcess: + overwrite_conflicting_files: bool = False, simulate: bool = False, as_deps: bool = False) -> SimpleProcess: cmd = ['pacman', '-U'] if file else ['pacman', '-S'] cmd.extend(pkgpaths) @@ -158,6 +158,9 @@ def install_as_process(pkgpaths: Iterable[str], root_password: str, file: bool, if overwrite_conflicting_files: cmd.append('--overwrite=*') + if as_deps: + cmd.append('--asdeps') + return SimpleProcess(cmd=cmd, root_password=root_password, cwd=pkgdir, @@ -730,7 +733,7 @@ def upgrade_several(pkgnames: Iterable[str], root_password: str, overwrite_confl def download(root_password: str, *pkgnames: str) -> SimpleProcess: - return SimpleProcess(cmd=['pacman', '-Swdd', *pkgnames, '--noconfirm'], + return SimpleProcess(cmd=['pacman', '-Swdd', *pkgnames, '--noconfirm', '--noprogressbar'], root_password=root_password, error_phrases={'error: failed to prepare transaction', 'error: failed to commit transaction', 'error: target not found'}, shell=True) @@ -882,22 +885,14 @@ def map_required_dependencies(*names: str) -> Dict[str, Set[str]]: deps = set() if val != 'None': - if ':' in val: - dep_info = val.split(':') - deps.add(dep_info[0].strip()) - else: - deps.update({dep.strip() for dep in val.split(' ') if dep}) + deps.update((dep for dep in val.split(' ') if dep)) elif latest_name and deps is not None: res[latest_name] = deps latest_name, deps, latest_field = None, None, None elif latest_name and deps is not None: - if ':' in l: - dep_info = l.split(':') - deps.add(dep_info[0].strip()) - else: - deps.update({dep.strip() for dep in l.split(' ') if dep}) + deps.update((dep for dep in l.split(' ') if dep)) return res diff --git a/bauh/gems/arch/resources/locale/ca b/bauh/gems/arch/resources/locale/ca index ec8381d5..13bfe101 100644 --- a/bauh/gems/arch/resources/locale/ca +++ b/bauh/gems/arch/resources/locale/ca @@ -49,8 +49,8 @@ arch.config.aur_rebuild_detector=Check reinstallation need {} arch.config.aur_rebuild_detector.tip=It checks if packages built with old library versions require to be rebuilt. If a package needs to be rebuilt, it will be marked for update ({} must be installed) arch.config.aur_rebuild_detector_no_bin=Ignore binaries ({}) arch.config.aur_rebuild_detector_no_bin.tip=If binary packages named as "package-bin" should be ignored by {} ({}) -arch.config.automatch_providers=Auto-define dependency providers -arch.config.automatch_providers.tip=It automatically chooses which provider will be used for a package dependency when both names are equal. +arch.config.automatch_providers=Auto-match dependency by name +arch.config.automatch_providers.tip=It associates automatically a package to a dependency if both names match. Otherwise all providers for a given dependency will be displayed. arch.config.aur_build_dir=Build directory (AUR) arch.config.aur_build_dir.tip=It define a custom directory where the AUR packages will be built. Default: {}. arch.config.aur_build_only_chosen=Build only chosen (AUR) @@ -73,6 +73,8 @@ arch.config.optimize=Optimize {} arch.config.optimize.tip=La configuració optimitzada s'utilitzarà per fer més ràpida la instal·lació, actualització i reversió dels paquets, en cas contrari s'utilitzarà la configuració del sistema. arch.config.pacman_mthread_download=Multithreaded download (repositories) arch.config.pacman_mthread_download.tip=Whether the repository packages should be downloaded with a tool that works with threads (it may be faster). pacman-mirrors must be installed. +arch.config.prefer_repository_provider=Prefer repository dependencies +arch.config.prefer_repository_provider.tip=Automatically picks the single package from the repositories among several external ({}) available as the provider for a given dependency arch.config.refresh_mirrors=Refresh mirrors on startup arch.config.refresh_mirrors.tip=Refresh the package mirrors once a day on startup arch.config.repos=Repositories packages @@ -195,7 +197,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 +210,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ó @@ -226,6 +227,7 @@ arch.substatus.integrity=Checking packages integrity arch.substatus.keyring=Checking keyring arch.substatus.loading_files=Loading package files arch.substatus.pre_hooks=Running pre-transaction hooks +arch.substatus.retrieve_pkgs=Retrieving packages arch.sync.dep_breakage.reason={} requires {} arch.sync_databases.substatus=Synchronizing package databases arch.sync_databases.substatus.error=It was not possible to synchronize the package database diff --git a/bauh/gems/arch/resources/locale/de b/bauh/gems/arch/resources/locale/de index f46459cc..4fadbb25 100644 --- a/bauh/gems/arch/resources/locale/de +++ b/bauh/gems/arch/resources/locale/de @@ -49,8 +49,8 @@ arch.config.aur_rebuild_detector=Check reinstallation need {} arch.config.aur_rebuild_detector.tip=It checks if packages built with old library versions require to be rebuilt. If a package needs to be rebuilt, it will be marked for update ({} must be installed) arch.config.aur_rebuild_detector_no_bin=Ignore binaries ({}) arch.config.aur_rebuild_detector_no_bin.tip=If binary packages named as "package-bin" should be ignored by {} ({}) -arch.config.automatch_providers=Auto-define dependency providers -arch.config.automatch_providers.tip=It automatically chooses which provider will be used for a package dependency when both names are equal. +arch.config.automatch_providers=Auto-match dependency by name +arch.config.automatch_providers.tip=It associates automatically a package to a dependency if both names match. Otherwise all providers for a given dependency will be displayed. arch.config.aur_build_dir=Build directory (AUR) arch.config.aur_build_dir.tip=It define a custom directory where the AUR packages will be built. Default: {}. arch.config.aur_build_only_chosen=Build only chosen (AUR) @@ -73,6 +73,8 @@ arch.config.optimize=Optimize {} arch.config.optimize.tip=Optimized settings will be used in order to make the packages installation, upgrading and downgrading faster, otherwise the system settings will be used arch.config.pacman_mthread_download=Multithreaded download (repositories) arch.config.pacman_mthread_download.tip=Whether the repository packages should be downloaded with a tool that works with threads (it may be faster). pacman-mirrors must be installed. +arch.config.prefer_repository_provider=Prefer repository dependencies +arch.config.prefer_repository_provider.tip=Automatically picks the single package from the repositories among several external ({}) available as the provider for a given dependency arch.config.refresh_mirrors=Refresh mirrors on startup arch.config.refresh_mirrors.tip=Refresh the package mirrors once a day on startup arch.config.repos=Repositories packages @@ -195,7 +197,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 +210,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 @@ -226,6 +227,7 @@ arch.substatus.integrity=Checking packages integrity arch.substatus.keyring=Checking keyring arch.substatus.loading_files=Loading package files arch.substatus.pre_hooks=Running pre-transaction hooks +arch.substatus.retrieve_pkgs=Retrieving packages arch.sync.dep_breakage.reason={} requires {} arch.sync_databases.substatus=Synchronizing package databases arch.sync_databases.substatus.error=It was not possible to synchronize the package database diff --git a/bauh/gems/arch/resources/locale/en b/bauh/gems/arch/resources/locale/en index a3137e06..2c90095b 100644 --- a/bauh/gems/arch/resources/locale/en +++ b/bauh/gems/arch/resources/locale/en @@ -49,8 +49,8 @@ arch.config.aur_rebuild_detector=Check reinstallation need {} arch.config.aur_rebuild_detector.tip=It checks if packages built with old library versions require to be rebuilt. If a package needs to be rebuilt, it will be marked for update ({} must be installed) arch.config.aur_rebuild_detector_no_bin=Ignore binaries ({}) arch.config.aur_rebuild_detector_no_bin.tip=If binary packages named as "package-bin" should be ignored by {} ({}) -arch.config.automatch_providers=Auto-define dependency providers -arch.config.automatch_providers.tip=It automatically chooses which provider will be used for a package dependency when both names are equal. +arch.config.automatch_providers=Auto-match dependency by name +arch.config.automatch_providers.tip=It associates automatically a package to a dependency if both names match. Otherwise all providers for a given dependency will be displayed. arch.config.aur_build_dir=Build directory (AUR) arch.config.aur_build_dir.tip=It define a custom directory where the AUR packages will be built. Default: {}. arch.config.aur_build_only_chosen=Build only chosen (AUR) @@ -73,6 +73,8 @@ arch.config.optimize=Optimize {} arch.config.optimize.tip=Optimized settings will be used in order to make the packages installation, upgrading and downgrading faster, otherwise the system settings will be used arch.config.pacman_mthread_download=Multi-threaded download (repositories) arch.config.pacman_mthread_download.tip=Whether the repository packages should be downloaded with a tool that works with threads (it may be faster). pacman-mirrors must be installed. +arch.config.prefer_repository_provider=Prefer repository dependencies +arch.config.prefer_repository_provider.tip=Automatically picks the single package from the repositories among several external ({}) available as the provider for a given dependency arch.config.refresh_mirrors=Refresh mirrors on startup arch.config.refresh_mirrors.tip=Refresh the package mirrors once a day on startup arch.config.repos=Repositories packages @@ -195,7 +197,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 +210,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 @@ -226,6 +227,7 @@ arch.substatus.integrity=Checking packages integrity arch.substatus.keyring=Checking keyring arch.substatus.loading_files=Loading package files arch.substatus.pre_hooks=Running pre-transaction hooks +arch.substatus.retrieve_pkgs=Retrieving packages arch.sync.dep_breakage.reason={} requires {} arch.sync_databases.substatus=Synchronizing package databases arch.sync_databases.substatus.error=It was not possible to synchronize the package database diff --git a/bauh/gems/arch/resources/locale/es b/bauh/gems/arch/resources/locale/es index 951cf926..ab82a38b 100644 --- a/bauh/gems/arch/resources/locale/es +++ b/bauh/gems/arch/resources/locale/es @@ -49,8 +49,8 @@ arch.config.aur_rebuild_detector=Verificar necesidad de reinstalación {} arch.config.aur_rebuild_detector.tip=Verifica si los paquetes creados con versiones antiguas de bibliotecas necesitan ser reconstruidos. Si es necesario reconstruir un paquete, el será marcado para actualización ({} debe estar instalado) arch.config.aur_rebuild_detector_no_bin=Ignorar binarios ({}) arch.config.aur_rebuild_detector_no_bin.tip=Si los paquetes binarios nombrados como "paquete-bin" deben ser ignorados por {} ({}) -arch.config.automatch_providers=Autodefinir proveedores de dependencia -arch.config.automatch_providers.tip=Elige automáticamente qué proveedor se usará para una dependencia de paquete cuando ambos nombres son iguales. +arch.config.automatch_providers=Auto-corresponder dependencia por nombre +arch.config.automatch_providers.tip=Asocia automáticamente un paquete a una dependencia si ambos nombres coinciden. De lo contrario, se mostrarán todos los proveedores para la dependencia. arch.config.aur_build_dir=Directorio de compilación (AUR) arch.config.aur_build_dir.tip=Define un directorio personalizado donde se construirán los paquetes AUR. Defecto: {}. arch.config.aur_build_only_chosen=Compilar solo elegido (AUR) @@ -73,6 +73,8 @@ arch.config.optimize=Optimizar {} arch.config.optimize.tip=Se usará la configuración optimizada para que la instalación, actualización y reversión de los paquetes sean más rápidas, de lo contrario se usará la configuración del sistema arch.config.pacman_mthread_download=Descarga segmentada (repositorios) arch.config.pacman_mthread_download.tip=Si los paquetes de los repositorios deben descargarse con una herramienta que usa segmentación/threads (puede ser más rápido). pacman-mirrors necesita estar instalado. +arch.config.prefer_repository_provider=Preferir dependencias de repositorio +arch.config.prefer_repository_provider.tip=Elige automáticamente el paquete unico de los repositorios entre varios externos ({}) disponibles como el proveedor para una dependencia arch.config.refresh_mirrors=Actualizar espejos al iniciar arch.config.refresh_mirrors.tip=Actualiza los espejos de paquetes una vez al día al iniciar arch.config.repos=Paquetes de repositorios @@ -195,7 +197,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 +210,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 @@ -226,6 +227,7 @@ arch.substatus.integrity=Verificando la integridad de los paquetes arch.substatus.keyring=Verificando keyring arch.substatus.loading_files=Cargando archivos de los paquetes arch.substatus.pre_hooks=Ejecutando ganchos pre-transacción +arch.substatus.retrieve_pkgs=Obteniendo paquetes arch.sync.dep_breakage.reason={} necesita de {} arch.sync_databases.substatus=Sincronizando bases de paquetes arch.sync_databases.substatus.error=No fue posible sincronizar la base de paquetes diff --git a/bauh/gems/arch/resources/locale/fr b/bauh/gems/arch/resources/locale/fr index b7fe4b39..7531d29a 100644 --- a/bauh/gems/arch/resources/locale/fr +++ b/bauh/gems/arch/resources/locale/fr @@ -49,8 +49,8 @@ arch.config.aur_rebuild_detector=Check reinstallation need {} arch.config.aur_rebuild_detector.tip=It checks if packages built with old library versions require to be rebuilt. If a package needs to be rebuilt, it will be marked for update ({} must be installed) arch.config.aur_rebuild_detector_no_bin=Ignore binaries ({}) arch.config.aur_rebuild_detector_no_bin.tip=If binary packages named as "package-bin" should be ignored by {} ({}) -arch.config.automatch_providers=Définition automatique des fournisseurs de dépendances -arch.config.automatch_providers.tip=Choisit automatiquement le fournisseur de dépendances d'un paquet en cas de noms identiques +arch.config.automatch_providers=Auto-match dependency by name +arch.config.automatch_providers.tip=It associates automatically a package to a dependency if both names match. Otherwise all providers for a given dependency will be displayed. arch.config.aur_build_dir=Répertoire de compilation (AUR) arch.config.aur_build_dir.tip=Définit un répertoire ou les paquets AUR seront compilés. Par défaut: {}. arch.config.aur_build_only_chosen=Compiler uniquement la sélection (AUR) @@ -73,6 +73,8 @@ arch.config.optimize=Optimizer {} arch.config.optimize.tip=Utiliser des paramètres optimisés pour rendre l'installation, mise à jour et downgrade des paquets plus rapide. À défaut, les paramètres systèmes seront utilisés. arch.config.pacman_mthread_download=Téléchargement parallèle (repos) arch.config.pacman_mthread_download.tip=Si il faut utiliser un outil qui télécharge les paquets du répos en parallèle (plus rapide). pacman-mirrors doit être installé. +arch.config.prefer_repository_provider=Prefer repository dependencies +arch.config.prefer_repository_provider.tip=Automatically picks the single package from the repositories among several external ({}) available as the provider for a given dependency arch.config.refresh_mirrors=Actualiser les miroirs au démarrage arch.config.refresh_mirrors.tip=Actualiser les miroirs du paquet une fois par jour au démarrage arch.config.repos=Repos des paquets @@ -195,7 +197,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 +210,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 @@ -226,6 +227,7 @@ arch.substatus.integrity=Recherche de paquets corrompus arch.substatus.keyring=Verification du trousseau de clés arch.substatus.loading_files=Chargement des fichers du paquet arch.substatus.pre_hooks=Éxécution des pre-transaction hooks +arch.substatus.retrieve_pkgs=Retrieving packages arch.sync.dep_breakage.reason={} requiert {} arch.sync_databases.substatus=Synchronisation des bases de données du paquet arch.sync_databases.substatus.error=Impossible de synchroniser les bases de données du paquet diff --git a/bauh/gems/arch/resources/locale/it b/bauh/gems/arch/resources/locale/it index eb106094..d42a8b47 100644 --- a/bauh/gems/arch/resources/locale/it +++ b/bauh/gems/arch/resources/locale/it @@ -49,8 +49,8 @@ arch.config.aur_rebuild_detector=Check reinstallation need {} arch.config.aur_rebuild_detector.tip=It checks if packages built with old library versions require to be rebuilt. If a package needs to be rebuilt, it will be marked for update ({} must be installed) arch.config.aur_rebuild_detector_no_bin=Ignore binaries ({}) arch.config.aur_rebuild_detector_no_bin.tip=If binary packages named as "package-bin" should be ignored by {} ({}) -arch.config.automatch_providers=Auto-define dependency providers -arch.config.automatch_providers.tip=It automatically chooses which provider will be used for a package dependency when both names are equal. +arch.config.automatch_providers=Auto-match dependency by name +arch.config.automatch_providers.tip=It associates automatically a package to a dependency if both names match. Otherwise all providers for a given dependency will be displayed. arch.config.aur_build_dir=Build directory (AUR) arch.config.aur_build_dir.tip=It define a custom directory where the AUR packages will be built. Default: {}. arch.config.aur_build_only_chosen=Build only chosen (AUR) @@ -73,6 +73,8 @@ arch.config.optimize=Optimize {} arch.config.optimize.tip=Verranno utilizzate le impostazioni ottimizzate per velocizzare l'installazione, l'aggiornamento e l'inversione dei pacchetti, altrimenti verranno utilizzate le impostazioni di sistema arch.config.pacman_mthread_download=Multithreaded download (repositories) arch.config.pacman_mthread_download.tip=Whether the repository packages should be downloaded with a tool that works with threads (it may be faster). pacman-mirrors must be installed. +arch.config.prefer_repository_provider=Prefer repository dependencies +arch.config.prefer_repository_provider.tip=Automatically picks the single package from the repositories among several external ({}) available as the provider for a given dependency arch.config.refresh_mirrors=Refresh mirrors on startup arch.config.refresh_mirrors.tip=Refresh the package mirrors once a day on startup arch.config.repos=Repositories packages @@ -195,7 +197,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 +210,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 @@ -226,6 +227,7 @@ arch.substatus.integrity=Checking packages integrity arch.substatus.keyring=Checking keyring arch.substatus.loading_files=Loading package files arch.substatus.pre_hooks=Running pre-transaction hooks +arch.substatus.retrieve_pkgs=Retrieving packages arch.sync.dep_breakage.reason={} requires {} arch.sync_databases.substatus=Synchronizing package databases arch.sync_databases.substatus.error=It was not possible to synchronize the package database diff --git a/bauh/gems/arch/resources/locale/pt b/bauh/gems/arch/resources/locale/pt index da9a8c5d..084bb184 100644 --- a/bauh/gems/arch/resources/locale/pt +++ b/bauh/gems/arch/resources/locale/pt @@ -49,8 +49,8 @@ arch.config.aur_rebuild_detector=Verificar necessidade de reinstalação {} arch.config.aur_rebuild_detector.tip=Verifica se pacotes construídos com versões antigas de bibliotecas precisam ser reconstruídas. Se um pacote precisa ser reconstruído, ele será marcado para atualizar ({} precisa estar instalado). arch.config.aur_rebuild_detector_no_bin=Ignorar binários ({}) arch.config.aur_rebuild_detector_no_bin.tip=Se pacotes binários nomeados como "pacote-bin" devem ser ignorados pelo {} ({}) -arch.config.automatch_providers=Auto-definir provedores de dependências -arch.config.automatch_providers.tip=Escolhe automaticamente qual provedor será utilizado para determinada dependência de um pacote caso os nomes de ambos sejam iguais. +arch.config.automatch_providers=Auto-corresponder dependência por nome +arch.config.automatch_providers.tip=Associa automaticamente um pacote a uma dependência caso os nomes sejam os mesmos. Caso contrário todos os provedores para a dependência serão exibidos. arch.config.aur_build_dir=Diretório de construção (AUR) arch.config.aur_build_dir.tip=Define um diretório personalizado onde pacotes do AUR serão construídos. Padrão: {}. arch.config.aur_build_only_chosen=Construir somente escolhido (AUR) @@ -72,6 +72,8 @@ arch.config.mirrors_sort_limit.tip=Define o número máximo de espelhos que ser arch.config.optimize=Otimizar {} arch.config.pacman_mthread_download=Download segmentado (repositórios) arch.config.pacman_mthread_download.tip=Se os pacotes dos repositórios devem baixados através de uma ferramenta que trabalha com segmentação/threads (pode ser mais rápido). pacman-mirrors precisa estar instalado. +arch.config.prefer_repository_provider=Preferir dependências de repositórios +arch.config.prefer_repository_provider.tip=Define automaticamente o pacote único proveniente dos repositórios entre diversos externos ({}) disponíveis como provedor de uma dependência arch.config.refresh_mirrors=Atualizar espelhos ao iniciar arch.config.refresh_mirrors.tip=Atualiza os espelhos de pacotes uma vez ao dia na inicialização arch.config.repos=Pacotes de repositórios @@ -194,7 +196,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 +209,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 @@ -225,6 +226,7 @@ arch.substatus.integrity=Verificando a integridade dos pacotes arch.substatus.keyring=Verificando o keyring arch.substatus.loading_files=Carregando os arquivos dos pacotes arch.substatus.pre_hooks=Executando ganchos pré-transação +arch.substatus.retrieve_pkgs=Obtendo pacotes arch.sync.dep_breakage.reason={} precisa de {} arch.sync_databases.substatus=Sincronizando bases de pacotes arch.sync_databases.substatus.error=Não foi possível sincronizar as bases de pacotes diff --git a/bauh/gems/arch/resources/locale/ru b/bauh/gems/arch/resources/locale/ru index 107fb6bc..7d6ae938 100644 --- a/bauh/gems/arch/resources/locale/ru +++ b/bauh/gems/arch/resources/locale/ru @@ -49,8 +49,8 @@ arch.config.aur_rebuild_detector=Check reinstallation need {} arch.config.aur_rebuild_detector.tip=It checks if packages built with old library versions require to be rebuilt. If a package needs to be rebuilt, it will be marked for update ({} must be installed) arch.config.aur_rebuild_detector_no_bin=Ignore binaries ({}) arch.config.aur_rebuild_detector_no_bin.tip=If binary packages named as "package-bin" should be ignored by {} ({}) -arch.config.automatch_providers=Auto-define dependency providers -arch.config.automatch_providers.tip=It automatically chooses which provider will be used for a package dependency when both names are equal. +arch.config.automatch_providers=Auto-match dependency by name +arch.config.automatch_providers.tip=It associates automatically a package to a dependency if both names match. Otherwise all providers for a given dependency will be displayed. arch.config.aur_build_dir=Build directory (AUR) arch.config.aur_build_dir.tip=It define a custom directory where the AUR packages will be built. Default: {}. arch.config.aur_build_only_chosen=Build only chosen (AUR) @@ -73,6 +73,8 @@ arch.config.optimize=Оптимизация {} arch.config.optimize.tip=Оптимизированные настройки будут использоваться для ускорения установки пакетов, в противном случае будут использоваться системные настройки arch.config.pacman_mthread_download=Multithreaded download (repositories) arch.config.pacman_mthread_download.tip=Whether the repository packages should be downloaded with a tool that works with threads (it may be faster). pacman-mirrors must be installed. +arch.config.prefer_repository_provider=Prefer repository dependencies +arch.config.prefer_repository_provider.tip=Automatically picks the single package from the repositories among several external ({}) available as the provider for a given dependency arch.config.refresh_mirrors=Обновить зеркала при запуске arch.config.refresh_mirrors.tip=Обновляйте зеркала пакета один раз в день при запуске arch.config.repos=Пакеты репозиториев @@ -195,7 +197,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 +210,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=Оптимизация компиляции @@ -226,6 +227,7 @@ arch.substatus.integrity=Checking packages integrity arch.substatus.keyring=Checking keyring arch.substatus.loading_files=Loading package files arch.substatus.pre_hooks=Running pre-transaction hooks +arch.substatus.retrieve_pkgs=Retrieving packages arch.sync.dep_breakage.reason={} requires {} arch.sync_databases.substatus=Синхронизация баз данных пакетов arch.sync_databases.substatus.error=Синхронизировать базу данных пакета не удалось diff --git a/bauh/gems/arch/resources/locale/tr b/bauh/gems/arch/resources/locale/tr index a6520a28..f337f0bc 100644 --- a/bauh/gems/arch/resources/locale/tr +++ b/bauh/gems/arch/resources/locale/tr @@ -49,8 +49,8 @@ arch.config.aur_rebuild_detector=Check reinstallation need {} arch.config.aur_rebuild_detector.tip=It checks if packages built with old library versions require to be rebuilt. If a package needs to be rebuilt, it will be marked for update ({} must be installed) arch.config.aur_rebuild_detector_no_bin=Ignore binaries ({}) arch.config.aur_rebuild_detector_no_bin.tip=If binary packages named as "package-bin" should be ignored by {} ({}) -arch.config.automatch_providers=Auto-define dependency providers -arch.config.automatch_providers.tip=It automatically chooses which provider will be used for a package dependency when both names are equal. +arch.config.automatch_providers=Auto-match dependency by name +arch.config.automatch_providers.tip=It associates automatically a package to a dependency if both names match. Otherwise all providers for a given dependency will be displayed. arch.config.aur_build_dir=Build directory (AUR) arch.config.aur_build_dir.tip=It define a custom directory where the AUR packages will be built. Default: {}. arch.config.aur_build_only_chosen=Build only chosen (AUR) @@ -73,6 +73,8 @@ arch.config.optimize=Optimize {} arch.config.optimize.tip=Paketlerin kurulumunu, yükseltilmesini ve indirilmesini hızlandırmak için optimize edilmiş ayarlar kullanılacak, aksi takdirde sistem ayarları kullanılacak arch.config.pacman_mthread_download=Multithreaded download (repositories) arch.config.pacman_mthread_download.tip=Whether the repository packages should be downloaded with a tool that works with threads (it may be faster). pacman-mirrors must be installed. +arch.config.prefer_repository_provider=Prefer repository dependencies +arch.config.prefer_repository_provider.tip=Automatically picks the single package from the repositories among several external ({}) available as the provider for a given dependency arch.config.refresh_mirrors=Başlangıçta yansıları yenile arch.config.refresh_mirrors.tip=Paket yansılarını başlangıçta günde bir kez yenileyin arch.config.repos=Depo paketleri @@ -195,7 +197,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 +210,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 @@ -226,6 +227,7 @@ arch.substatus.integrity=Checking packages integrity arch.substatus.keyring=Checking keyring arch.substatus.loading_files=Loading package files arch.substatus.pre_hooks=Running pre-transaction hooks +arch.substatus.retrieve_pkgs=Retrieving packages arch.sync.dep_breakage.reason={} requires {} arch.sync_databases.substatus=Paket veritabanı eşitleniyor arch.sync_databases.substatus.error=Paket veritabanı eşitlenemedi diff --git a/bauh/gems/arch/sorting.py b/bauh/gems/arch/sorting.py index ee099734..7d6b63b5 100644 --- a/bauh/gems/arch/sorting.py +++ b/bauh/gems/arch/sorting.py @@ -1,4 +1,4 @@ -from typing import Dict, Set, Tuple, List, Collection +from typing import Dict, Set, Tuple, List, Collection, Optional def __add_dep_to_sort(pkgname: str, pkgs_data: Dict[str, dict], sorted_names: dict, not_sorted: Set[str], @@ -35,16 +35,18 @@ def __add_dep_to_sort(pkgname: str, pkgs_data: Dict[str, dict], sorted_names: di return idx -def sort(pkgs: Collection[str], pkgs_data: Dict[str, dict], provided_map: Dict[str, Set[str]] = None) -> List[Tuple[str, str]]: +def sort(pkgs: Collection[str], pkgs_data: Dict[str, dict], provided_map: Optional[Dict[str, Set[str]]] = None) -> List[Tuple[str, str]]: sorted_list, sorted_names, not_sorted = [], set(), set() - provided = provided_map if provided_map else {} + all_provided = {**provided_map} if provided_map else {} - # add all packages with no dependencies first + # adding all packages with no dependencies first for pkgname in pkgs: data = pkgs_data[pkgname] - if not provided_map and data['p']: # mapping provided if reeded + + if data['p']: # adding providers not mapped to the sorting context for p in data['p']: - provided[p] = {pkgname} + if p not in all_provided: + all_provided[p] = {pkgname} if not data['d']: sorted_list.append(pkgname) @@ -57,7 +59,7 @@ def sort(pkgs: Collection[str], pkgs_data: Dict[str, dict], provided_map: Dict[s pkgsdeps = set() data = pkgs_data[pkg] for dep in data['d']: - providers = provided.get(dep) + providers = all_provided.get(dep) if providers: for p in providers: diff --git a/bauh/gems/arch/updates.py b/bauh/gems/arch/updates.py index 032af4f5..2f5113ce 100644 --- a/bauh/gems/arch/updates.py +++ b/bauh/gems/arch/updates.py @@ -227,7 +227,8 @@ def _fill_to_install(self, context: UpdateRequirementsContext) -> bool: remote_provided_map=context.remote_provided_map, remote_repo_map=context.remote_repo_map, watcher=self.watcher, - automatch_providers=context.arch_config['automatch_providers']) + automatch_providers=context.arch_config['automatch_providers'], + prefer_repository_provider=context.arch_config['prefer_repository_provider']) if deps is None: tf = time.time() diff --git a/bauh/view/qt/dialog.py b/bauh/view/qt/dialog.py index 2de9973c..e69d05e9 100644 --- a/bauh/view/qt/dialog.py +++ b/bauh/view/qt/dialog.py @@ -33,7 +33,8 @@ class ConfirmationDialog(QDialog): def __init__(self, title: str, body: Optional[str], i18n: I18n, icon: QIcon = QIcon(resource.get_path('img/logo.svg')), widgets: Optional[List[QWidget]] = None, confirmation_button: bool = True, deny_button: bool = True, - window_cancel: bool = False, confirmation_label: Optional[str] = None, deny_label: Optional[str] = None): + window_cancel: bool = False, confirmation_label: Optional[str] = None, deny_label: Optional[str] = None, + confirmation_icon: bool = True): super(ConfirmationDialog, self).__init__() if not window_cancel: @@ -64,9 +65,10 @@ def __init__(self, title: str, body: Optional[str], i18n: I18n, icon: QIcon = QI container_body.setLayout(QHBoxLayout()) self.layout().addWidget(container_body) - lb_icon = QLabel() - lb_icon.setObjectName("confirm_dialog_icon") - container_body.layout().addWidget(lb_icon) + if confirmation_icon: + lb_icon = QLabel() + lb_icon.setObjectName("confirm_dialog_icon") + container_body.layout().addWidget(lb_icon) if body: lb_msg = QLabel(body) diff --git a/bauh/view/qt/settings.py b/bauh/view/qt/settings.py index 150431c2..f3d89ce6 100644 --- a/bauh/view/qt/settings.py +++ b/bauh/view/qt/settings.py @@ -110,9 +110,12 @@ def _save_settings(self): if success: if not self.window: - dialog.show_message(title=self.i18n['success'].capitalize(), - body=self.i18n['settings.changed.success.warning'], - type_=MessageType.INFO) + ConfirmationDialog(title=self.i18n['success'].capitalize(), + body=f"{self.i18n['settings.changed.success.warning']}
", + i18n=self.i18n, + confirmation_label=self.i18n['ok'], + confirmation_icon=False, + deny_button=False).ask() QCoreApplication.exit() elif ConfirmationDialog(title=self.i18n['warning'].capitalize(), body=f"{self.i18n['settings.changed.success.warning']}
" diff --git a/bauh/view/resources/style/knight/knight.qss b/bauh/view/resources/style/knight/knight.qss index a82fc5b6..cf42fe6b 100644 --- a/bauh/view/resources/style/knight/knight.qss +++ b/bauh/view/resources/style/knight/knight.qss @@ -413,6 +413,10 @@ QLabel[tip_icon = "true"] { qproperty-pixmap: url("@style_dir/img/help.svg"); } +QLabel#confirm_dialog_icon { + qproperty-pixmap: url("@style_dir/img/help.svg"); +} + FormQt IconButton#clean_field { qproperty-icon: url("@style_dir/img/clean.svg"); }