diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8bef3bb6..63b85d57 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -59,6 +59,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- allowing the user to bypass dependency breakage scenarios (a popup will be displayed)
+ - new settings property **suggest_unneeded_uninstall**: defines if the dependencies apparently no longer necessary associated with the uninstalled packages should be suggested for uninstallation. When this property is enabled it automatically disables the property **suggest_optdep_uninstall**. Default: false (to prevent new users from making mistakes)
+ - new settings property **suggest_optdep_uninstall**: defines 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)
+
+
+
- AUR
- caching the PKGBUILD file used for the package installation/upgrade/downgrade (**~/.cache/bauh/arch/installed/$pkgname/PKGBUILD**)
@@ -104,10 +109,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- some conflict resolution scenarios when upgrading several packages
- not handling conflicting files errors during the installation process
- - some environment variables are not available during the common operations (install, upgrade, downgrade, uninstall, makepkg, launch)
- - not displaying and uninstalling dependent packages during conflict resolutions
- - not retrieving all packages that would break if a given package is uninstalled
- displaying wrong progress during the upgrade process when there are packages to install and upgrade
+ - uninstall: not detecting hard requirements properly
+ - not displaying and uninstalling dependent packages during conflict resolutions
+ - some environment variables are not available during the common operations (install, upgrade, downgrade, uninstall, makepkg, launch)
- AUR
- info dialog of installed packages displays the latest PKGBUILD file instead of the one used for installation/upgrade/downgrade (the fix will only work for new installed packages)
- multi-threaded download: not retrieving correctly some source files URLs (e.g: linux-xanmod-lts)
diff --git a/README.md b/README.md
index 390fd401..6fb25aa0 100644
--- a/README.md
+++ b/README.md
@@ -203,7 +203,9 @@ edit_aur_pkgbuild: false # if the AUR PKGBUILD file should be displayed for edi
aur_build_dir: null # defines a custom build directory for AUR packages (a null value will point to /tmp/bauh/arch (non-root user) or /tmp/bauh_root/arch (root user)). Default: null.
aur_remove_build_dir: true # it defines if a package's generated build directory should be removed after the operation is finished (installation, upgrading, ...). Options: true, false (default: true).
aur_build_only_chosen : true # some AUR packages have a common file definition declaring several packages to be built. When this property is 'true' only the package the user select to install will be built (unless its name is different from those declared in the PKGBUILD base). With a 'null' value a popup asking if the user wants to build all of them will be displayed. 'false' will build and install all packages. Default: true.
-check_dependency_breakage: true # If, during the verification of the update requirements, specific versions of dependencies must also be checked. Example: package A depends on version 1.0 of B. If A and B were selected to upgrade, and B would be upgrade to 2.0, then B would be excluded from the transaction. Default: true.
+check_dependency_breakage: true # if, during the verification of the update requirements, specific versions of dependencies must also be checked. Example: package A depends on version 1.0 of B. If A and B were selected to upgrade, and B would be upgrade to 2.0, then B would be excluded from the transaction. Default: true.
+suggest_unneeded_uninstall: false # if the dependencies apparently no longer necessary associated with the uninstalled packages should be suggested for uninstallation. When this property is enabled it automatically disables the property 'suggest_optdep_uninstall'. Default: false (to prevent new users from making mistakes)
+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)
```
- Required dependencies:
- **pacman**
diff --git a/bauh/commons/system.py b/bauh/commons/system.py
index 08f4bc4a..2b130803 100644
--- a/bauh/commons/system.py
+++ b/bauh/commons/system.py
@@ -320,3 +320,8 @@ def check_enabled_services(*names: str) -> Dict[str, bool]:
else:
status = output.split('\n')
return {s: status[i].strip().lower() == 'enabled' for i, s in enumerate(names) if s}
+
+
+def execute(cmd: str, shell: bool = False) -> Tuple[int, str]:
+ p = subprocess.run(args=cmd.split(' ') if not shell else [cmd], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell)
+ return p.returncode, p.stdout.decode()
diff --git a/bauh/gems/arch/config.py b/bauh/gems/arch/config.py
index 402c0ce2..2fd89b1b 100644
--- a/bauh/gems/arch/config.py
+++ b/bauh/gems/arch/config.py
@@ -19,7 +19,9 @@ def read_config(update_file: bool = False) -> dict:
'aur_build_dir': None,
'aur_remove_build_dir': True,
'aur_build_only_chosen': True,
- 'check_dependency_breakage': True}
+ 'check_dependency_breakage': True,
+ 'suggest_unneeded_uninstall': False,
+ 'suggest_optdep_uninstall': False}
return read(CONFIG_FILE, template, update_file=update_file)
diff --git a/bauh/gems/arch/controller.py b/bauh/gems/arch/controller.py
index a13ca7fb..eac27bed 100644
--- a/bauh/gems/arch/controller.py
+++ b/bauh/gems/arch/controller.py
@@ -39,7 +39,7 @@ from bauh.gems.arch.aur import AURClient
from bauh.gems.arch.config import read_config, get_build_dir
from bauh.gems.arch.dependencies import DependenciesAnalyser
from bauh.gems.arch.download import MultithreadedDownloadService, ArchDownloadException
-from bauh.gems.arch.exceptions import PackageNotFoundException
+from bauh.gems.arch.exceptions import PackageNotFoundException, PackageInHoldException
from bauh.gems.arch.mapper import ArchDataMapper
from bauh.gems.arch.model import ArchPackage
from bauh.gems.arch.output import TransactionStatusHandler
@@ -1140,7 +1140,7 @@ class ArchManager(SoftwareManager):
return True
- def _request_unncessary_uninstall_confirmation(self, uninstalled: Iterable[str], unnecessary: Iterable[str], watcher: ProcessWatcher) -> Optional[List[str]]:
+ def _request_unncessary_uninstall_confirmation(self, unnecessary: Iterable[str], watcher: ProcessWatcher) -> Optional[Set[str]]:
reqs = [InputOption(label=p, value=p, icon_path=get_icon_path(), read_only=False) for p in unnecessary]
reqs_select = MultipleSelectComponent(options=reqs, default_options=set(reqs), label="", max_per_line=3 if len(reqs) > 9 else 1)
@@ -1150,7 +1150,7 @@ class ArchManager(SoftwareManager):
deny_label=self.i18n['arch.uninstall.unnecessary.proceed'].capitalize(),
confirmation_label=self.i18n['arch.uninstall.unnecessary.cancel'].capitalize(),
window_cancel=False):
- return reqs_select.get_selected_values()
+ return {*reqs_select.get_selected_values()}
def _request_all_unncessary_uninstall_confirmation(self, pkgs: Iterable[str], context: TransactionContext):
reqs = [InputOption(label=p, value=p, icon_path=get_icon_path(), read_only=True) for p in pkgs]
@@ -1172,47 +1172,45 @@ class ArchManager(SoftwareManager):
net_available = internet.is_available() if disk_loader else True
- required_by = self.deps_analyser.map_all_required_by(names, set())
+ hard_requirements = set()
- if required_by:
- target_provided = pacman.map_provided(pkgs={*names, *required_by}).keys()
+ for n in names:
+ try:
+ pkg_reqs = pacman.list_hard_requirements(n, self.logger)
- if target_provided:
- required_by_deps = pacman.map_all_deps(required_by, only_installed=True)
+ if pkg_reqs:
+ hard_requirements.update(pkg_reqs)
+ except PackageInHoldException:
+ context.watcher.show_message(title=self.i18n['error'].capitalize(),
+ body=self.i18n['arch.uninstall.error.hard_dep_in_hold'].format(bold(n)),
+ type_=MessageType.ERROR)
+ return False
- if required_by_deps:
- all_provided = pacman.map_provided()
-
- for pkg, deps in required_by_deps.items():
- target_required_by = 0
- for dep in deps:
- dep_split = pacman.RE_DEP_OPERATORS.split(dep)
- if dep_split[0] in target_provided or dep_split[0] in required_by:
- dep_providers = all_provided.get(dep_split[0])
-
- if dep_providers:
- target_required_by += 1 if not dep_providers.difference(target_provided) else 0
-
- if not target_required_by:
- required_by.remove(pkg)
-
- self._update_progress(context, 50)
+ self._update_progress(context, 25)
to_uninstall = set()
to_uninstall.update(names)
- if required_by:
- to_uninstall.update(required_by)
+ if hard_requirements:
+ to_uninstall.update(hard_requirements)
if not self._request_uninstall_confirmation(to_uninstall=names,
- required=required_by,
+ required=hard_requirements,
watcher=context.watcher):
return False
if remove_unneeded:
- all_deps_map = pacman.map_all_deps(names=to_uninstall, only_installed=True) # retrieving the deps to check if they are still necessary
+ unnecessary_packages = pacman.list_post_uninstall_unneeded_packages(to_uninstall)
+ self.logger.info("Checking unnecessary optdeps")
+
+ if context.config['suggest_optdep_uninstall']:
+ unnecessary_packages.update(self._list_opt_deps_with_no_hard_requirements(source_pkgs=to_uninstall))
+
+ self.logger.info("Packages no longer needed found: {}".format(len(unnecessary_packages)))
else:
- all_deps_map = None
+ unnecessary_packages = None
+
+ self._update_progress(context, 50)
if disk_loader and to_uninstall: # loading package instances in case the uninstall succeeds
instances = self.read_installed(disk_loader=disk_loader,
@@ -1234,60 +1232,50 @@ class ArchManager(SoftwareManager):
self._update_progress(context, 70)
- if all_deps_map:
- context.watcher.change_substatus(self.i18n['arch.checking_unnecessary_deps'])
- all_deps = set()
+ if unnecessary_packages:
+ unnecessary_to_uninstall = self._request_unncessary_uninstall_confirmation(unnecessary=unnecessary_packages,
+ watcher=context.watcher)
- all_provided = pacman.map_provided(remote=False)
- for deps in all_deps_map.values():
- for dep in deps:
- real_deps = all_provided.get(dep)
+ if unnecessary_to_uninstall:
+ context.watcher.change_substatus(self.i18n['arch.checking_unnecessary_deps'])
+ unnecessary_requirements = set()
- if real_deps:
- all_deps.update(real_deps)
+ for pkg in unnecessary_to_uninstall:
+ try:
+ pkg_reqs = pacman.list_hard_requirements(pkg)
- if all_deps:
- self.logger.info("Mapping dependencies required packages of uninstalled packages")
- alldeps_reqs = pacman.map_required_by(all_deps)
+ if pkg_reqs:
+ unnecessary_requirements.update(pkg_reqs)
- no_longer_needed = set()
- if alldeps_reqs:
- for dep, reqs in alldeps_reqs.items():
- if not reqs:
- no_longer_needed.add(dep)
+ except PackageInHoldException:
+ context.watcher.show_message(title=self.i18n['warning'].capitalize(),
+ body=self.i18n['arch.uninstall.error.hard_dep_in_hold'].format(bold(p)),
+ type_=MessageType.WARNING)
- if no_longer_needed:
- self.logger.info("{} packages no longer needed found".format(len(no_longer_needed)))
- unnecessary_to_uninstall = self._request_unncessary_uninstall_confirmation(uninstalled=to_uninstall,
- unnecessary=no_longer_needed,
- watcher=context.watcher)
+ all_unnecessary_to_uninstall = {*unnecessary_to_uninstall, *unnecessary_requirements}
- if unnecessary_to_uninstall:
- unnecessary_to_uninstall_deps = pacman.list_unnecessary_deps(unnecessary_to_uninstall, all_provided)
- all_unnecessary_to_uninstall = {*unnecessary_to_uninstall, *unnecessary_to_uninstall_deps}
+ if not unnecessary_requirements or self._request_all_unncessary_uninstall_confirmation(all_unnecessary_to_uninstall, context):
+ if disk_loader: # loading package instances in case the uninstall succeeds
+ unnecessary_instances = self.read_installed(disk_loader=disk_loader,
+ internet_available=net_available,
+ names=all_unnecessary_to_uninstall).installed
+ else:
+ unnecessary_instances = None
- if not unnecessary_to_uninstall_deps or self._request_all_unncessary_uninstall_confirmation(all_unnecessary_to_uninstall, context):
+ unneded_uninstalled = self._uninstall_pkgs(all_unnecessary_to_uninstall, context.root_password, context.handler)
- if disk_loader: # loading package instances in case the uninstall succeeds
- unnecessary_instances = self.read_installed(disk_loader=disk_loader,
- internet_available=net_available,
- names=all_unnecessary_to_uninstall).installed
- else:
- unnecessary_instances = None
+ if unneded_uninstalled:
+ to_uninstall.update(all_unnecessary_to_uninstall)
- unneded_uninstalled = self._uninstall_pkgs(all_unnecessary_to_uninstall, context.root_password, context.handler)
-
- if unneded_uninstalled:
- to_uninstall.update(all_unnecessary_to_uninstall)
-
- if disk_loader and unnecessary_instances: # loading package instances in case the uninstall succeeds
- for p in unnecessary_instances:
- context.removed[p.name] = p
- else:
- self.logger.error("Could not uninstall some unnecessary packages")
- context.watcher.print("Could not uninstall some unnecessary packages")
+ if disk_loader and unnecessary_instances: # loading package instances in case the uninstall succeeds
+ for p in unnecessary_instances:
+ context.removed[p.name] = p
+ else:
+ self.logger.error("Could not uninstall some unnecessary packages")
+ context.watcher.print("Could not uninstall some unnecessary packages")
self._update_progress(context, 90)
+
if bool(context.config['clean_cached']): # cleaning old versions
context.watcher.change_substatus(self.i18n['arch.uninstall.clean_cached.substatus'])
if os.path.isdir('/var/cache/pacman/pkg'):
@@ -1315,13 +1303,14 @@ class ArchManager(SoftwareManager):
return TransactionResult.fail()
removed = {}
+ arch_config = read_config()
success = self._uninstall(TransactionContext(change_progress=True,
- arch_config=read_config(),
+ arch_config=arch_config,
watcher=watcher,
root_password=root_password,
handler=handler,
removed=removed),
- remove_unneeded=True,
+ remove_unneeded=arch_config['suggest_unneeded_uninstall'],
names={pkg.name},
disk_loader=disk_loader) # to be able to return all uninstalled packages
if success:
@@ -1545,7 +1534,7 @@ class ArchManager(SoftwareManager):
if context.removed is None:
context.removed = {}
- res = self._uninstall(context=context, names={conflicting_pkg}, disk_loader=context.disk_loader)
+ res = self._uninstall(context=context, names={conflicting_pkg}, disk_loader=context.disk_loader, remove_unneeded=False)
context.restabilish_progress()
return res
@@ -2568,16 +2557,27 @@ class ArchManager(SoftwareManager):
def get_screenshots(self, pkg: SoftwarePackage) -> List[str]:
pass
- def _gen_bool_selector(self, id_: str, label_key: str, tooltip_key: str, value: bool, max_width: int, capitalize_label: bool = True) -> SingleSelectComponent:
+ def _gen_bool_selector(self, id_: str, label_key: str, tooltip_key: str, value: bool, max_width: int,
+ capitalize_label: bool = True, label_params: Optional[list] = None, tooltip_params: Optional[list] = None) -> SingleSelectComponent:
opts = [InputOption(label=self.i18n['yes'].capitalize(), value=True),
InputOption(label=self.i18n['no'].capitalize(), value=False)]
- return SingleSelectComponent(label=self.i18n[label_key],
+ lb = self.i18n[label_key]
+
+ if label_params:
+ lb = lb.format(*label_params)
+
+ tip = self.i18n[tooltip_key]
+
+ if tooltip_params:
+ tip = tip.format(*tooltip_params)
+
+ return SingleSelectComponent(label=lb,
options=opts,
default_option=[o for o in opts if o.value == value][0],
max_per_line=len(opts),
type_=SelectViewType.RADIO,
- tooltip=self.i18n[tooltip_key],
+ tooltip=tip,
max_width=max_width,
id_=id_,
capitalize_label=capitalize_label)
@@ -2638,6 +2638,17 @@ class ArchManager(SoftwareManager):
tooltip_key='arch.config.clean_cache.tip',
value=bool(local_config['clean_cached']),
max_width=max_width),
+ self._gen_bool_selector(id_='suggest_unneeded_uninstall',
+ label_key='arch.config.suggest_unneeded_uninstall',
+ tooltip_params=['"{}"'.format(self.i18n['arch.config.suggest_optdep_uninstall'])],
+ tooltip_key='arch.config.suggest_unneeded_uninstall.tip',
+ value=bool(local_config['suggest_unneeded_uninstall']),
+ max_width=max_width),
+ self._gen_bool_selector(id_='suggest_optdep_uninstall',
+ label_key='arch.config.suggest_optdep_uninstall',
+ tooltip_key='arch.config.suggest_optdep_uninstall.tip',
+ value=bool(local_config['suggest_optdep_uninstall']),
+ max_width=max_width),
self._gen_bool_selector(id_='ref_mirs',
label_key='arch.config.refresh_mirrors',
tooltip_key='arch.config.refresh_mirrors.tip',
@@ -2707,6 +2718,8 @@ class ArchManager(SoftwareManager):
config['aur_build_dir'] = form_install.get_component('aur_build_dir').file_path
config['aur_build_only_chosen'] = form_install.get_component('aur_build_only_chosen').get_selected()
config['check_dependency_breakage'] = form_install.get_component('check_dependency_breakage').get_selected()
+ config['suggest_optdep_uninstall'] = form_install.get_component('suggest_optdep_uninstall').get_selected()
+ config['suggest_unneeded_uninstall'] = form_install.get_component('suggest_unneeded_uninstall').get_selected()
if not config['aur_build_dir']:
config['aur_build_dir'] = None
@@ -3132,3 +3145,35 @@ class ArchManager(SoftwareManager):
f.write(new_srcinfo)
return custom_pkgbuild_path
+
+ def _list_opt_deps_with_no_hard_requirements(self, source_pkgs: Set[str], installed_provided: Optional[Dict[str, Set[str]]] = None) -> Set[str]:
+ optdeps = set()
+
+ for deps in pacman.map_optional_deps(names=source_pkgs, remote=False).values():
+ optdeps.update(deps.keys())
+
+ res = set()
+ if optdeps:
+ all_provided = pacman.map_provided() if not installed_provided else installed_provided
+
+ real_optdeps = set()
+ for o in optdeps:
+ dep_providers = all_provided.get(o)
+
+ if dep_providers:
+ for p in dep_providers:
+ if p not in source_pkgs:
+ real_optdeps.add(p)
+
+ if real_optdeps:
+ for p in real_optdeps:
+ try:
+ reqs = pacman.list_hard_requirements(p, self.logger)
+
+ if reqs is not None and (not reqs or reqs.issubset(source_pkgs)):
+ res.add(p)
+ except PackageInHoldException:
+ self.logger.warning("There is a requirement in hold for opt dep '{}'".format(p))
+ continue
+
+ return res
diff --git a/bauh/gems/arch/exceptions.py b/bauh/gems/arch/exceptions.py
index d868cb15..a5c29584 100644
--- a/bauh/gems/arch/exceptions.py
+++ b/bauh/gems/arch/exceptions.py
@@ -1,5 +1,13 @@
+from typing import Optional
+
class PackageNotFoundException(Exception):
def __init__(self, name: str):
self.name = name
+
+
+class PackageInHoldException(Exception):
+
+ def __init__(self, name: Optional[str] = None):
+ self.name = name
diff --git a/bauh/gems/arch/pacman.py b/bauh/gems/arch/pacman.py
index 5c042d2d..18cd8000 100644
--- a/bauh/gems/arch/pacman.py
+++ b/bauh/gems/arch/pacman.py
@@ -1,12 +1,15 @@
+import logging
import os
import re
from threading import Thread
-from typing import List, Set, Tuple, Dict, Iterable
+from typing import List, Set, Tuple, Dict, Iterable, Optional
+
+from colorama import Fore
from bauh.commons import system
from bauh.commons.system import run_cmd, new_subprocess, new_root_subprocess, SystemProcess, SimpleProcess
from bauh.commons.util import size_to_byte
-from bauh.gems.arch.exceptions import PackageNotFoundException
+from bauh.gems.arch.exceptions import PackageNotFoundException, PackageInHoldException
RE_DEPS = re.compile(r'[\w\-_]+:[\s\w_\-\.]+\s+\[\w+\]')
RE_OPTDEPS = re.compile(r'[\w\._\-]+\s*:')
@@ -1128,3 +1131,42 @@ def get_packages_to_sync_first() -> Set[str]:
def is_snapd_installed() -> bool:
return bool(run_cmd('pacman -Qq snapd', print_error=False))
+
+
+def list_hard_requirements(name: str, logger: Optional[logging.Logger] = None) -> Optional[Set[str]]:
+ code, output = system.execute('pacman -Rc {} --print-format=%n'.format(name), shell=True)
+
+ if code != 0:
+ if 'HoldPkg' in output:
+ raise PackageInHoldException()
+ elif 'target not found' in output:
+ raise PackageNotFoundException(name)
+ elif logger:
+ logger.error("Unexpected error while listing hard requirements of: {}".format(name))
+ print('{}{}{}'.format(Fore.RED, output, Fore.RESET))
+ elif output:
+ reqs = set()
+
+ for line in output.split('\n'):
+ if line:
+ line_strip = line.strip()
+
+ if line_strip and line_strip != name:
+ reqs.add(line_strip)
+
+ return reqs
+
+
+def list_post_uninstall_unneeded_packages(names: Set[str]) -> Set[str]:
+ output = run_cmd('pacman -Rss {} --print-format=%n'.format(' '.join(names)), print_error=False)
+
+ reqs = set()
+ if output:
+ for line in output.split('\n'):
+ if line:
+ line_strip = line.strip()
+
+ if line_strip and line_strip not in names:
+ reqs.add(line_strip)
+
+ return reqs
diff --git a/bauh/gems/arch/resources/locale/ca b/bauh/gems/arch/resources/locale/ca
index 5d6c2a5e..410cd4c1 100644
--- a/bauh/gems/arch/resources/locale/ca
+++ b/bauh/gems/arch/resources/locale/ca
@@ -56,6 +56,10 @@ arch.config.refresh_mirrors=Refresh mirrors on startup
arch.config.refresh_mirrors.tip=Refresh the package mirrors once a day on startup ( or after a device reboot )
arch.config.repos=Repositories packages
arch.config.repos.tip=It allows to manage packages from the repositories set
+arch.config.suggest_optdep_uninstall=Uninstall optional dependencies
+arch.config.suggest_optdep_uninstall.tip=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.
+arch.config.suggest_unneeded_uninstall=Uninstall unneeded dependencies
+arch.config.suggest_unneeded_uninstall.tip=If the dependencies apparently no longer necessary associated with the uninstalled packages should be suggested for uninstallation. When this property is enabled it automatically disables the property {}.
arch.config.sync_dbs=Synchronize packages databases
arch.config.sync_dbs.tip=Synchronizes the package databases once a day before the first package installation, upgrade or downgrade. This option helps to prevent errors during these operations.
arch.config.sync_dbs_start.tip=Synchronizes the package databases during the initialization once a day
@@ -213,6 +217,7 @@ arch.task.sync_sb.status=Actualitzen {}
arch.uncompressing.package=S’està descomprimint el paquet
arch.uninstall.clean_cached.error=No s'ha pogut eliminar {} versions antigues que es troba al disc
arch.uninstall.clean_cached.substatus=Eliminació de versions antigues del disc
+arch.uninstall.error.hard_dep_in_hold=It is not possible to uninstall {} because one of its dependencies is marked as "InHold"
arch.uninstall.required_by=The {} packages listed below depend on {} to work properly
arch.uninstall.required_by.advice=It is necessary to uninstall them as well to proceed
arch.uninstall.unnecessary.all=The following {} packages will be uninstalled
diff --git a/bauh/gems/arch/resources/locale/de b/bauh/gems/arch/resources/locale/de
index 827fcaf0..55120a11 100644
--- a/bauh/gems/arch/resources/locale/de
+++ b/bauh/gems/arch/resources/locale/de
@@ -56,6 +56,10 @@ arch.config.refresh_mirrors=Refresh mirrors on startup
arch.config.refresh_mirrors.tip=Refresh the package mirrors once a day on startup ( or after a device reboot )
arch.config.repos=Repositories packages
arch.config.repos.tip=It allows to manage packages from the repositories set
+arch.config.suggest_optdep_uninstall=Uninstall optional dependencies
+arch.config.suggest_optdep_uninstall.tip=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.
+arch.config.suggest_unneeded_uninstall=Uninstall unneeded dependencies
+arch.config.suggest_unneeded_uninstall.tip=If the dependencies apparently no longer necessary associated with the uninstalled packages should be suggested for uninstallation. When this property is enabled it automatically disables the property {}.
arch.config.sync_dbs=Synchronize packages databases
arch.config.sync_dbs.tip=Synchronizes the package databases once a day before the first package installation, upgrade or downgrade. This option helps to prevent errors during these operations.
arch.config.sync_dbs_start.tip=Synchronizes the package databases during the initialization once a day
@@ -213,6 +217,7 @@ arch.task.sync_sb.status=Updating {}
arch.uncompressing.package=Paket entpacken
arch.uninstall.clean_cached.error=It was not possible to remove old {} versions found on disk
arch.uninstall.clean_cached.substatus=Removing old versions from disk
+arch.uninstall.error.hard_dep_in_hold=It is not possible to uninstall {} because one of its dependencies is marked as "InHold"
arch.uninstall.required_by=The {} packages listed below depend on {} to work properly
arch.uninstall.required_by.advice=It is necessary to uninstall them as well to proceed
arch.uninstall.unnecessary.all=The following {} packages will be uninstalled
diff --git a/bauh/gems/arch/resources/locale/en b/bauh/gems/arch/resources/locale/en
index c85e103a..e8a940b6 100644
--- a/bauh/gems/arch/resources/locale/en
+++ b/bauh/gems/arch/resources/locale/en
@@ -57,6 +57,10 @@ arch.config.refresh_mirrors=Refresh mirrors on startup
arch.config.refresh_mirrors.tip=Refresh the package mirrors once a day on startup ( or after a device reboot )
arch.config.repos=Repositories packages
arch.config.repos.tip=It allows to manage packages from the repositories set
+arch.config.suggest_optdep_uninstall=Uninstall optional dependencies
+arch.config.suggest_optdep_uninstall.tip=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.
+arch.config.suggest_unneeded_uninstall=Uninstall unneeded dependencies
+arch.config.suggest_unneeded_uninstall.tip=If the dependencies apparently no longer necessary associated with the uninstalled packages should be suggested for uninstallation. When this property is enabled it automatically disables the property {}.
arch.config.sync_dbs=Synchronize packages databases
arch.config.sync_dbs.tip=Synchronizes the package databases once a day before the first package installation, upgrade or downgrade. This option helps to prevent errors during these operations.
arch.config.sync_dbs_start.tip=Synchronizes the package databases during the initialization once a day
@@ -214,6 +218,7 @@ arch.task.sync_sb.status=Updating {}
arch.uncompressing.package=Uncompressing the package
arch.uninstall.clean_cached.error=It was not possible to remove old {} versions found on disk
arch.uninstall.clean_cached.substatus=Removing old versions from disk
+arch.uninstall.error.hard_dep_in_hold=It is not possible to uninstall {} because one of its dependencies is marked as "InHold"
arch.uninstall.required_by=The {} packages listed below depend on {} to work properly
arch.uninstall.required_by.advice=It is necessary to uninstall them as well to proceed
arch.uninstall.unnecessary.all=The following {} packages will be uninstalled
diff --git a/bauh/gems/arch/resources/locale/es b/bauh/gems/arch/resources/locale/es
index 32127891..6eb584b1 100644
--- a/bauh/gems/arch/resources/locale/es
+++ b/bauh/gems/arch/resources/locale/es
@@ -56,6 +56,10 @@ 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 ( o después de reiniciar el dispositivo )
arch.config.repos=Paquetes de repositorios
arch.config.repos.tip=Permite gestionar paquetes de los repositorios configurados
+arch.config.suggest_optdep_uninstall=Desinstalar dependencias opcionales
+arch.config.suggest_optdep_uninstall.tip=Si las dependencias opcionales asociadas con los paquetes desinstalados deben se sugeridas para desinstalación. Solo se sugerirán las dependencias opcionales que no sean dependencias de otros paquetes.
+arch.config.suggest_unneeded_uninstall=Desinstalar las dependencias innecesarias
+arch.config.suggest_unneeded_uninstall.tip=Si las dependencias aparentemente ya no necesarias asociadas con los paquetes desinstalados deben ser sugeridas para desinstalación. Cuando esta propiedad está habilitada, automáticamente deshabilita la propiedad {}.
arch.config.sync_dbs=Sincronizar las bases de paquetes
arch.config.sync_dbs.tip=Sincroniza las bases de paquetes una vez al día antes de la primera instalación, actualización o reversión de paquete. Esta opción ayuda a prevenir errores durante estas operaciones.
arch.config.sync_dbs_start.tip=Sincroniza las bases de paquetes durante la inicialización una vez al día
@@ -213,6 +217,7 @@ arch.task.sync_sb.status=Actualizando {}
arch.uncompressing.package=Descomprimindo el paquete
arch.uninstall.clean_cached.error=No fue posible eliminar versiones antiguas de {} encontradas en disco
arch.uninstall.clean_cached.substatus=Eliminando versiones antiguas del disco
+arch.uninstall.error.hard_dep_in_hold=No es posible desinstalar {} porque una de sus dependencias está bloqueada (InHold)
arch.uninstall.required_by=Los {} paquetes enumerados abajo dependen de {} para funcionar correctamente
arch.uninstall.required_by.advice=Es necesario desinstalarlos también para continuar
arch.uninstall.unnecessary.all=Los {} seguintes paquetes serán desinstalados
diff --git a/bauh/gems/arch/resources/locale/it b/bauh/gems/arch/resources/locale/it
index d576ef8d..003d5536 100644
--- a/bauh/gems/arch/resources/locale/it
+++ b/bauh/gems/arch/resources/locale/it
@@ -56,6 +56,10 @@ arch.config.refresh_mirrors=Refresh mirrors on startup
arch.config.refresh_mirrors.tip=Refresh the package mirrors once a day on startup ( or after a device reboot )
arch.config.repos=Repositories packages
arch.config.repos.tip=It allows to manage packages from the repositories set
+arch.config.suggest_optdep_uninstall=Uninstall optional dependencies
+arch.config.suggest_optdep_uninstall.tip=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.
+arch.config.suggest_unneeded_uninstall=Uninstall unneeded dependencies
+arch.config.suggest_unneeded_uninstall.tip=If the dependencies apparently no longer necessary associated with the uninstalled packages should be suggested for uninstallation. When this property is enabled it automatically disables the property {}.
arch.config.sync_dbs=Synchronize packages databases
arch.config.sync_dbs.tip=Synchronizes the package databases once a day before the first package installation, upgrade or downgrade. This option helps to prevent errors during these operations.
arch.config.sync_dbs_start.tip=Synchronizes the package databases during the initialization once a day
@@ -213,6 +217,7 @@ arch.task.sync_sb.status=Aggiornando {}
arch.uncompressing.package=Non comprimere il pacchetto
arch.uninstall.clean_cached.error=Non è stato possibile rimuovere le vecchie {} versioni trovate sul disco
arch.uninstall.clean_cached.substatus=Rimozione di versioni precedenti dal disco
+arch.uninstall.error.hard_dep_in_hold=It is not possible to uninstall {} because one of its dependencies is marked as "InHold"
arch.uninstall.required_by=The {} packages listed below depend on {} to work properly
arch.uninstall.required_by.advice=It is necessary to uninstall them as well to proceed
arch.uninstall.unnecessary.all=The following {} packages will be uninstalled
diff --git a/bauh/gems/arch/resources/locale/pt b/bauh/gems/arch/resources/locale/pt
index d1ef855f..4b7e43fd 100644
--- a/bauh/gems/arch/resources/locale/pt
+++ b/bauh/gems/arch/resources/locale/pt
@@ -56,6 +56,10 @@ 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
arch.config.repos.tip=Permite gerenciar pacotes dos repositórisos
+arch.config.suggest_optdep_uninstall=Desinstalar dependências opcionais
+arch.config.suggest_optdep_uninstall.tip=Se as dependências opcionais associadas a pacotes desinstalados devem ser sugeridas para desinstalação. Somente as dependências opcionais que não sejam dependências de outros pacotes serão sugeridas.
+arch.config.suggest_unneeded_uninstall=Desinstalar dependências desnecessárias
+arch.config.suggest_unneeded_uninstall.tip=Se as dependências aparentemente não mais necessárias associadas aos pacotes desinstalados devem ser sugeridas para desinstalação. Quando essa proprieda está habilitada automaticamente desabilita a propriedade {}.
arch.config.sync_dbs=Sincronizar bases de pacotes
arch.config.sync_dbs.tip=Sincroniza as bases de pacotes uma vez ao dia antes da primeira instalação, atualização ou reversão de pacote. Essa opção ajuda a evitar erros durante essa operações.
arch.config.sync_dbs_start.tip=Sincroniza as bases de pacotes durante a inicialização uma vez ao dia
@@ -213,6 +217,7 @@ arch.task.sync_sb.status=Atualizando {}
arch.uncompressing.package=Descompactando o pacote
arch.uninstall.clean_cached.error=Não foi possível remover versões antigas de {} encontradas em disco
arch.uninstall.clean_cached.substatus=Removendo versões antigas do disco
+arch.uninstall.error.hard_dep_in_hold=Não é possível desinstalar {} pois uma de suas dependências está bloqueada (InHold)
arch.uninstall.required_by=Os {} pacotes listados abaixo dependem de {} para funcionar corretamente
arch.uninstall.required_by.advice=Para prosseguir será necessário desinstá-los também
arch.uninstall.unnecessary.all=Os seguintes {} pacotes serão desinstalados
diff --git a/bauh/gems/arch/resources/locale/ru b/bauh/gems/arch/resources/locale/ru
index 751f10b1..035ce7cb 100644
--- a/bauh/gems/arch/resources/locale/ru
+++ b/bauh/gems/arch/resources/locale/ru
@@ -56,6 +56,10 @@ arch.config.refresh_mirrors=Обновить зеркала при запуск
arch.config.refresh_mirrors.tip=Обновляйте зеркала пакета один раз в день при запуске (или после перезагрузки устройства)
arch.config.repos=Пакеты репозиториев
arch.config.repos.tip=Он позволяет управлять пакетами из набора репозиториев
+arch.config.suggest_optdep_uninstall=Uninstall optional dependencies
+arch.config.suggest_optdep_uninstall.tip=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.
+arch.config.suggest_unneeded_uninstall=Uninstall unneeded dependencies
+arch.config.suggest_unneeded_uninstall.tip=If the dependencies apparently no longer necessary associated with the uninstalled packages should be suggested for uninstallation. When this property is enabled it automatically disables the property {}.
arch.config.sync_dbs=Синхронизация баз данных пакетов
arch.config.sync_dbs.tip=Синхронизируйте базы данных пакетов один раз в день перед первой установкой, обновлением или понижением версии пакета. Этот параметр помогает предотвратить ошибки во время этих операций.
arch.config.sync_dbs_start.tip=Синхронизирует базы данных пакетов во время инициализации один раз в день
@@ -213,6 +217,7 @@ arch.task.sync_sb.status=Updating {}
arch.uncompressing.package=Распаковка пакета
arch.uninstall.clean_cached.error=It was not possible to remove old {} versions found on disk
arch.uninstall.clean_cached.substatus=Removing old versions from disk
+arch.uninstall.error.hard_dep_in_hold=It is not possible to uninstall {} because one of its dependencies is marked as "InHold"
arch.uninstall.required_by=The {} packages listed below depend on {} to work properly
arch.uninstall.required_by.advice=It is necessary to uninstall them as well to proceed
arch.uninstall.unnecessary.all=The following {} packages will be uninstalled
diff --git a/bauh/gems/arch/resources/locale/tr b/bauh/gems/arch/resources/locale/tr
index 023bea68..a6a12a76 100644
--- a/bauh/gems/arch/resources/locale/tr
+++ b/bauh/gems/arch/resources/locale/tr
@@ -56,6 +56,10 @@ 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 (veya cihaz yeniden başlatıldıktan sonra) yenileyin
arch.config.repos=Depo paketleri
arch.config.repos.tip=Paketleri depolardan yönetmeye izin verir
+arch.config.suggest_optdep_uninstall=Uninstall optional dependencies
+arch.config.suggest_optdep_uninstall.tip=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.
+arch.config.suggest_unneeded_uninstall=Uninstall unneeded dependencies
+arch.config.suggest_unneeded_uninstall.tip=If the dependencies apparently no longer necessary associated with the uninstalled packages should be suggested for uninstallation. When this property is enabled it automatically disables the property {}.
arch.config.sync_dbs=Paket veritabanlarını senkronize et
arch.config.sync_dbs.tip=İlk veritabanını kurmadan, yükseltmeden veya indirmeden önce paket veritabanlarını günde bir kez senkronize eder. Bu seçenek, bu işlemler sırasında hataların önlenmesine yardımcı olur.
arch.config.sync_dbs_start.tip=Başlatma sırasında paket veritabanlarını günde bir kez senkronize eder
@@ -213,6 +217,7 @@ arch.task.sync_sb.status={} güncelleniyor
arch.uncompressing.package=Paket arşivden çıkarılıyor
arch.uninstall.clean_cached.error=Diskte bulunan eski {} sürümleri kaldırılamadı
arch.uninstall.clean_cached.substatus=Eski sürümler diskten kaldırılıyor
+arch.uninstall.error.hard_dep_in_hold=It is not possible to uninstall {} because one of its dependencies is marked as "InHold"
arch.uninstall.required_by=The {} packages listed below depend on {} to work properly
arch.uninstall.required_by.advice=Devam etmek için bunları da kaldırmak gerekir
arch.uninstall.unnecessary.all=Aşağıdaki {} paketler kaldırılacak