mirror of
https://github.com/spalencsar/bearhub.git
synced 2026-07-08 19:04:15 +02:00
[fix][arch][uninstall] not displaying removing all unnecessary dependencies
This commit is contained in:
@@ -17,7 +17,8 @@ class ProcessWatcher:
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def request_confirmation(self, title: str, body: str, components: List[ViewComponent] = None, confirmation_label: str = None, deny_label: str = None, deny_button: bool = True)-> bool:
|
def request_confirmation(self, title: str, body: str, components: List[ViewComponent] = None, confirmation_label: str = None,
|
||||||
|
deny_label: str = None, deny_button: bool = True, window_cancel: bool = True) -> bool:
|
||||||
"""
|
"""
|
||||||
request a user confirmation. In the current GUI implementation, it shows a popup to the user.
|
request a user confirmation. In the current GUI implementation, it shows a popup to the user.
|
||||||
:param title: popup title
|
:param title: popup title
|
||||||
@@ -26,6 +27,7 @@ class ProcessWatcher:
|
|||||||
:param confirmation_label: optional confirmation button label (default to 'yes')
|
:param confirmation_label: optional confirmation button label (default to 'yes')
|
||||||
:param deny_label: optional deny button label (default to 'no')
|
:param deny_label: optional deny button label (default to 'no')
|
||||||
:param deny_button: if the deny button should be displayed
|
:param deny_button: if the deny button should be displayed
|
||||||
|
:param window_cancel: if the window cancel button should be visible
|
||||||
:return: if the request was confirmed by the user
|
:return: if the request was confirmed by the user
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -819,14 +819,15 @@ class ArchManager(SoftwareManager):
|
|||||||
reqs = [InputOption(label=p, value=p, icon_path=get_icon_path(), read_only=False) for p in pkgs]
|
reqs = [InputOption(label=p, value=p, icon_path=get_icon_path(), read_only=False) for p in pkgs]
|
||||||
reqs_select = MultipleSelectComponent(options=reqs, default_options=set(reqs), label="", max_per_line=3)
|
reqs_select = MultipleSelectComponent(options=reqs, default_options=set(reqs), label="", max_per_line=3)
|
||||||
|
|
||||||
msg = '{}. {}:'.format(self.i18n['arch.uninstall.unnecessary.l1'].format(bold(str(len(reqs)))),
|
msg = '<p>{}</p><p>{}:</p>'.format(self.i18n['arch.uninstall.unnecessary.l1'].format(bold(context.name)),
|
||||||
self.i18n['arch.uninstall.unnecessary.l2'])
|
self.i18n['arch.uninstall.unnecessary.l2'])
|
||||||
|
|
||||||
if not context.watcher.request_confirmation(title=self.i18n['confirmation'].capitalize(),
|
if not context.watcher.request_confirmation(title=self.i18n['confirmation'].capitalize(),
|
||||||
body=msg,
|
body=msg,
|
||||||
components=[reqs_select],
|
components=[reqs_select],
|
||||||
confirmation_label=self.i18n['arch.uninstall.unnecessary.proceed'].capitalize(),
|
confirmation_label=self.i18n['arch.uninstall.unnecessary.proceed'].capitalize(),
|
||||||
deny_label=self.i18n['arch.uninstall.unnecessary.cancel'].capitalize()):
|
deny_label=self.i18n['arch.uninstall.unnecessary.cancel'].capitalize(),
|
||||||
|
window_cancel=False):
|
||||||
return
|
return
|
||||||
|
|
||||||
return reqs_select.get_selected_values()
|
return reqs_select.get_selected_values()
|
||||||
@@ -862,30 +863,30 @@ class ArchManager(SoftwareManager):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
if remove_unneeded:
|
if remove_unneeded:
|
||||||
optdeps = pacman.map_optional_deps(names=to_uninstall, remote=False) # retrieving the optdeps to check if they are still necessary
|
all_deps_map = pacman.map_all_deps(names=to_uninstall, only_installed=True) # retrieving the deps to check if they are still necessary
|
||||||
else:
|
else:
|
||||||
optdeps = None
|
all_deps_map = None
|
||||||
|
|
||||||
uninstalled = self._uninstall_pkgs(to_uninstall, context.root_password, context.handler)
|
uninstalled = self._uninstall_pkgs(to_uninstall, context.root_password, context.handler)
|
||||||
|
|
||||||
if uninstalled:
|
if uninstalled:
|
||||||
self._update_progress(context, 70)
|
self._update_progress(context, 70)
|
||||||
|
|
||||||
if optdeps:
|
if all_deps_map:
|
||||||
context.watcher.change_substatus(self.i18n['arch.checking_unnecessary_deps'])
|
context.watcher.change_substatus(self.i18n['arch.checking_unnecessary_deps'])
|
||||||
all_opt_deps = set()
|
all_deps = set()
|
||||||
|
|
||||||
all_provided = pacman.map_provided(remote=False)
|
all_provided = pacman.map_provided(remote=False)
|
||||||
for deps in optdeps.values():
|
for deps in all_deps_map.values():
|
||||||
for dep in deps.keys():
|
for dep in deps:
|
||||||
real_deps = all_provided.get(dep)
|
real_deps = all_provided.get(dep)
|
||||||
|
|
||||||
if real_deps:
|
if real_deps:
|
||||||
all_opt_deps.update(real_deps)
|
all_deps.update(real_deps)
|
||||||
|
|
||||||
if all_opt_deps:
|
if all_deps:
|
||||||
self.logger.info("Mapping optdeps required packages")
|
self.logger.info("Mapping dependencies required packages of uninstalled packages")
|
||||||
optdeps_reqs = pacman.map_required_by(all_opt_deps)
|
optdeps_reqs = pacman.map_required_by(all_deps)
|
||||||
|
|
||||||
no_longer_needed = set()
|
no_longer_needed = set()
|
||||||
if optdeps_reqs:
|
if optdeps_reqs:
|
||||||
|
|||||||
@@ -760,6 +760,67 @@ def map_optional_deps(names: Iterable[str], remote: bool, not_installed: bool =
|
|||||||
return res
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def map_all_deps(names: Iterable[str], only_installed: bool = False) -> Dict[str, Set[str]]:
|
||||||
|
output = run_cmd('pacman -Qi {}'.format(' '.join(names)))
|
||||||
|
|
||||||
|
if output:
|
||||||
|
res = {}
|
||||||
|
deps_fields = {'Depends On', 'Optional Deps'}
|
||||||
|
latest_name, deps, latest_field = None, None, None
|
||||||
|
|
||||||
|
for l in output.split('\n'):
|
||||||
|
if l:
|
||||||
|
if l[0] != ' ':
|
||||||
|
line = l.strip()
|
||||||
|
field_sep_idx = line.index(':')
|
||||||
|
field = line[0:field_sep_idx].strip()
|
||||||
|
|
||||||
|
if field == 'Name':
|
||||||
|
latest_field = field
|
||||||
|
val = line[field_sep_idx + 1:].strip()
|
||||||
|
latest_name = val
|
||||||
|
deps = None
|
||||||
|
elif field in deps_fields:
|
||||||
|
latest_field = field
|
||||||
|
val = line[field_sep_idx + 1:].strip()
|
||||||
|
opt_deps = latest_field == 'Optional Deps'
|
||||||
|
|
||||||
|
if deps is None:
|
||||||
|
deps = set()
|
||||||
|
|
||||||
|
if val != 'None':
|
||||||
|
if ':' in val:
|
||||||
|
dep_info = val.split(':')
|
||||||
|
desc = dep_info[1].strip()
|
||||||
|
|
||||||
|
if desc and opt_deps and only_installed and '[installed]' not in desc:
|
||||||
|
continue
|
||||||
|
|
||||||
|
deps.add(dep_info[0].strip())
|
||||||
|
else:
|
||||||
|
deps.update({dep.strip() 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:
|
||||||
|
opt_deps = latest_field == 'Optional Deps'
|
||||||
|
|
||||||
|
if ':' in l:
|
||||||
|
dep_info = l.split(':')
|
||||||
|
desc = dep_info[1].strip()
|
||||||
|
|
||||||
|
if desc and opt_deps and only_installed and '[installed]' not in desc:
|
||||||
|
continue
|
||||||
|
|
||||||
|
deps.add(dep_info[0].strip())
|
||||||
|
else:
|
||||||
|
deps.update({dep.strip() for dep in l.split(' ') if dep})
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
def get_cache_dir() -> str:
|
def get_cache_dir() -> str:
|
||||||
dir_pattern = re.compile(r'.*CacheDir\s*=\s*.+')
|
dir_pattern = re.compile(r'.*CacheDir\s*=\s*.+')
|
||||||
|
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ arch.uninstall.required_by=No es pot desinstal·lar {} perquè és necessari per
|
|||||||
arch.uninstall.required_by.advice=It is necessary to uninstall them as well to proceed.
|
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
|
arch.uninstall.unnecessary.all=The following {} packages will be uninstalled
|
||||||
arch.uninstall.unnecessary.cancel=Keep
|
arch.uninstall.unnecessary.cancel=Keep
|
||||||
arch.uninstall.unnecessary.l1=The {} packages below are no longer needed
|
arch.uninstall.unnecessary.l1={} was successfully uninstalled. The packages below that he depended on are no longer needed.
|
||||||
arch.uninstall.unnecessary.l2=Check those you want to uninstall
|
arch.uninstall.unnecessary.l2=Check those you want to uninstall
|
||||||
arch.uninstall.unnecessary.proceed=Uninstall
|
arch.uninstall.unnecessary.proceed=Uninstall
|
||||||
arch.uninstalling.conflict=S’està suprimint el paquet conflictiu {}
|
arch.uninstalling.conflict=S’està suprimint el paquet conflictiu {}
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ arch.uninstall.required_by={} konnte nicht deinstalliert werden, da es für die
|
|||||||
arch.uninstall.required_by.advice=It is necessary to uninstall them as well to proceed.
|
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
|
arch.uninstall.unnecessary.all=The following {} packages will be uninstalled
|
||||||
arch.uninstall.unnecessary.cancel=Keep
|
arch.uninstall.unnecessary.cancel=Keep
|
||||||
arch.uninstall.unnecessary.l1=The {} packages below are no longer needed
|
arch.uninstall.unnecessary.l1={} was successfully uninstalled. The packages below that he depended on are no longer needed.
|
||||||
arch.uninstall.unnecessary.l2=Check those you want to uninstall
|
arch.uninstall.unnecessary.l2=Check those you want to uninstall
|
||||||
arch.uninstall.unnecessary.proceed=Uninstall
|
arch.uninstall.unnecessary.proceed=Uninstall
|
||||||
arch.uninstalling.conflict={} deinstallieren
|
arch.uninstalling.conflict={} deinstallieren
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ arch.uninstall.required_by={} cannot be uninstalled because it is required for t
|
|||||||
arch.uninstall.required_by.advice=It is necessary to uninstall them as well to proceed.
|
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
|
arch.uninstall.unnecessary.all=The following {} packages will be uninstalled
|
||||||
arch.uninstall.unnecessary.cancel=Keep
|
arch.uninstall.unnecessary.cancel=Keep
|
||||||
arch.uninstall.unnecessary.l1=The {} packages below are no longer needed
|
arch.uninstall.unnecessary.l1={} was successfully uninstalled. The packages below that he depended on are no longer needed.
|
||||||
arch.uninstall.unnecessary.l2=Check those you want to uninstall
|
arch.uninstall.unnecessary.l2=Check those you want to uninstall
|
||||||
arch.uninstall.unnecessary.proceed=Uninstall
|
arch.uninstall.unnecessary.proceed=Uninstall
|
||||||
arch.uninstalling.conflict=Uninstalling conflicting package {}
|
arch.uninstalling.conflict=Uninstalling conflicting package {}
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ arch.uninstall.required_by=No se puede desinstalar {} porque es necesario para q
|
|||||||
arch.uninstall.required_by.advice=Es necesario desinstalarlos también para continuar.
|
arch.uninstall.required_by.advice=Es necesario desinstalarlos también para continuar.
|
||||||
arch.uninstall.unnecessary.all=Los {} seguintes paquetes serán desinstalados
|
arch.uninstall.unnecessary.all=Los {} seguintes paquetes serán desinstalados
|
||||||
arch.uninstall.unnecessary.cancel=Mantener
|
arch.uninstall.unnecessary.cancel=Mantener
|
||||||
arch.uninstall.unnecessary.l1=Los {} paquetes abajo ya no son necesarios
|
arch.uninstall.unnecessary.l1={} se desinstaló correctamente. Los paquetes abajo de los que dependía ya no son necesarios
|
||||||
arch.uninstall.unnecessary.l2=Seleccione aquellos que desea desinstalar
|
arch.uninstall.unnecessary.l2=Seleccione aquellos que desea desinstalar
|
||||||
arch.uninstall.unnecessary.proceed=Desinstalar
|
arch.uninstall.unnecessary.proceed=Desinstalar
|
||||||
arch.uninstalling.conflict=Eliminando el paquete conflictivo {}
|
arch.uninstalling.conflict=Eliminando el paquete conflictivo {}
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ arch.uninstall.required_by={} non può essere disinstallato perché è necessari
|
|||||||
arch.uninstall.required_by.advice=It is necessary to uninstall them as well to proceed.
|
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
|
arch.uninstall.unnecessary.all=The following {} packages will be uninstalled
|
||||||
arch.uninstall.unnecessary.cancel=Keep
|
arch.uninstall.unnecessary.cancel=Keep
|
||||||
arch.uninstall.unnecessary.l1=The {} packages below are no longer needed
|
arch.uninstall.unnecessary.l1={} was successfully uninstalled. The packages below that he depended on are no longer needed.
|
||||||
arch.uninstall.unnecessary.l2=Check those you want to uninstall:
|
arch.uninstall.unnecessary.l2=Check those you want to uninstall:
|
||||||
arch.uninstall.unnecessary.proceed=Uninstall
|
arch.uninstall.unnecessary.proceed=Uninstall
|
||||||
arch.uninstalling.conflict=Disinstallazione del pacchetto in conflitto {}
|
arch.uninstalling.conflict=Disinstallazione del pacchetto in conflitto {}
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ arch.uninstall.required_by={} não pode ser desinstalado porque ele é necessár
|
|||||||
arch.uninstall.required_by.advice=Para prosseguir será necessário desinstá-los também.
|
arch.uninstall.required_by.advice=Para prosseguir será necessário desinstá-los também.
|
||||||
arch.uninstall.unnecessary.all=Os seguintes {} pacotes serão desinstalados
|
arch.uninstall.unnecessary.all=Os seguintes {} pacotes serão desinstalados
|
||||||
arch.uninstall.unnecessary.cancel=Manter
|
arch.uninstall.unnecessary.cancel=Manter
|
||||||
arch.uninstall.unnecessary.l1=Os {} pacotes abaixo não são mais necessários.
|
arch.uninstall.unnecessary.l1={} foi desinstalado com sucesso ! Os pacotes abaixo que ele dependia já não são mais necessários.
|
||||||
arch.uninstall.unnecessary.l2=Selecione os desejados para desinstalação
|
arch.uninstall.unnecessary.l2=Selecione os desejados para desinstalação
|
||||||
arch.uninstall.unnecessary.proceed=Desinstalar
|
arch.uninstall.unnecessary.proceed=Desinstalar
|
||||||
arch.uninstalling.conflict=Desinstalando o pacote conflitante {}
|
arch.uninstalling.conflict=Desinstalando o pacote conflitante {}
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ arch.uninstall.required_by={} не может быть удален, так ка
|
|||||||
arch.uninstall.required_by.advice=It is necessary to uninstall them as well to proceed.
|
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
|
arch.uninstall.unnecessary.all=The following {} packages will be uninstalled
|
||||||
arch.uninstall.unnecessary.cancel=Keep
|
arch.uninstall.unnecessary.cancel=Keep
|
||||||
arch.uninstall.unnecessary.l1=The {} packages below are no longer needed
|
arch.uninstall.unnecessary.l1={} was successfully uninstalled. The packages below that he depended on are no longer needed.
|
||||||
arch.uninstall.unnecessary.l2=Check those you want to uninstall
|
arch.uninstall.unnecessary.l2=Check those you want to uninstall
|
||||||
arch.uninstall.unnecessary.proceed=Uninstall
|
arch.uninstall.unnecessary.proceed=Uninstall
|
||||||
arch.uninstalling.conflict=Удаление конфликтующего пакета {}
|
arch.uninstalling.conflict=Удаление конфликтующего пакета {}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from PyQt5.QtCore import QSize
|
from PyQt5.QtCore import QSize, Qt
|
||||||
from PyQt5.QtWidgets import QMessageBox, QVBoxLayout, QLabel, QWidget, QScrollArea, QFrame
|
from PyQt5.QtWidgets import QMessageBox, QVBoxLayout, QLabel, QWidget, QScrollArea, QFrame
|
||||||
|
|
||||||
from bauh.api.abstract.view import ViewComponent
|
from bauh.api.abstract.view import ViewComponent
|
||||||
@@ -12,8 +12,12 @@ from bauh.view.util.translation import I18n
|
|||||||
class ConfirmationDialog(QMessageBox):
|
class ConfirmationDialog(QMessageBox):
|
||||||
|
|
||||||
def __init__(self, title: str, body: str, i18n: I18n, screen_size: QSize, components: List[ViewComponent] = None,
|
def __init__(self, title: str, body: str, i18n: I18n, screen_size: QSize, components: List[ViewComponent] = None,
|
||||||
confirmation_label: str = None, deny_label: str = None, deny_button: bool = True):
|
confirmation_label: str = None, deny_label: str = None, deny_button: bool = True, window_cancel: bool = True):
|
||||||
super(ConfirmationDialog, self).__init__()
|
super(ConfirmationDialog, self).__init__()
|
||||||
|
|
||||||
|
if not window_cancel:
|
||||||
|
self.setWindowFlags(Qt.CustomizeWindowHint | Qt.WindowTitleHint)
|
||||||
|
|
||||||
self.setWindowTitle(title)
|
self.setWindowTitle(title)
|
||||||
self.setStyleSheet('QLabel { margin-right: 25px; }')
|
self.setStyleSheet('QLabel { margin-right: 25px; }')
|
||||||
self.bt_yes = self.addButton(i18n['popup.button.yes'] if not confirmation_label else confirmation_label.capitalize(), QMessageBox.YesRole)
|
self.bt_yes = self.addButton(i18n['popup.button.yes'] if not confirmation_label else confirmation_label.capitalize(), QMessageBox.YesRole)
|
||||||
|
|||||||
@@ -49,9 +49,10 @@ class AsyncAction(QThread, ProcessWatcher):
|
|||||||
self.root_password = None
|
self.root_password = None
|
||||||
self.stop = False
|
self.stop = False
|
||||||
|
|
||||||
def request_confirmation(self, title: str, body: str, components: List[ViewComponent] = None, confirmation_label: str = None, deny_label: str = None, deny_button: bool = True) -> bool:
|
def request_confirmation(self, title: str, body: str, components: List[ViewComponent] = None,
|
||||||
|
confirmation_label: str = None, deny_label: str = None, deny_button: bool = True, window_cancel: bool = True) -> bool:
|
||||||
self.wait_confirmation = True
|
self.wait_confirmation = True
|
||||||
self.signal_confirmation.emit({'title': title, 'body': body, 'components': components, 'confirmation_label': confirmation_label, 'deny_label': deny_label, 'deny_button': deny_button})
|
self.signal_confirmation.emit({'title': title, 'body': body, 'components': components, 'confirmation_label': confirmation_label, 'deny_label': deny_label, 'deny_button': deny_button, 'window_cancel': window_cancel})
|
||||||
self.wait_user()
|
self.wait_user()
|
||||||
return self.confirmation_res
|
return self.confirmation_res
|
||||||
|
|
||||||
|
|||||||
@@ -445,6 +445,7 @@ class ManageWindow(QWidget):
|
|||||||
confirmation_label=msg['confirmation_label'],
|
confirmation_label=msg['confirmation_label'],
|
||||||
deny_label=msg['deny_label'],
|
deny_label=msg['deny_label'],
|
||||||
deny_button=msg['deny_button'],
|
deny_button=msg['deny_button'],
|
||||||
|
window_cancel=msg['window_cancel'],
|
||||||
screen_size=self.screen_size)
|
screen_size=self.screen_size)
|
||||||
res = diag.is_confirmed()
|
res = diag.is_confirmed()
|
||||||
self.thread_animate_progress.animate()
|
self.thread_animate_progress.animate()
|
||||||
|
|||||||
Reference in New Issue
Block a user