[arch] improvement -> upgrade: checking specific version requirements and marking packages as 'cannot upgrade' when these requirements are not met

This commit is contained in:
Vinicius Moreira
2020-09-01 19:36:05 -03:00
parent d7225dab3b
commit feb061efa4
18 changed files with 286 additions and 43 deletions

View File

@@ -30,18 +30,24 @@ class SearchResult:
class UpgradeRequirement:
def __init__(self, pkg: SoftwarePackage, reason: str = None, required_size: int = None, extra_size: int = None):
def __init__(self, pkg: SoftwarePackage, reason: str = None, required_size: int = None, extra_size: int = None, sorting_priority: int = 0):
"""
:param pkg:
:param reason:
:param required_size: size in BYTES required to upgrade the package
:param extra_size: the extra size IN BYTES the upgrade will allocate in relation to the already allocated
:param sorting_priority: an int representing the sorting priority (higher numbers = higher priority)
"""
self.pkg = pkg
self.reason = reason
self.required_size = required_size
self.extra_size = extra_size
self.sorting_priority = sorting_priority
@staticmethod
def sort_by_priority(req: "UpgradeRequirement") -> Tuple[int, str]:
return -req.sorting_priority, req.pkg.name
class UpgradeRequirements:

View File

@@ -18,7 +18,8 @@ def read_config(update_file: bool = False) -> dict:
'edit_aur_pkgbuild': False,
'aur_build_dir': None,
'aur_remove_build_dir': True,
'aur_build_only_chosen': True}
'aur_build_only_chosen': True,
'check_dependency_breakage': True}
return read(CONFIG_FILE, template, update_file=update_file)

View File

@@ -2554,6 +2554,11 @@ class ArchManager(SoftwareManager):
tooltip_key='arch.config.automatch_providers.tip',
value=bool(local_config['automatch_providers']),
max_width=max_width),
self._gen_bool_selector(id_='check_dependency_breakage',
label_key='arch.config.check_dependency_breakage',
tooltip_key='arch.config.check_dependency_breakage.tip',
value=bool(local_config['check_dependency_breakage']),
max_width=max_width),
self._gen_bool_selector(id_='mthread_download',
label_key='arch.config.pacman_mthread_download',
tooltip_key='arch.config.pacman_mthread_download.tip',
@@ -2639,6 +2644,7 @@ class ArchManager(SoftwareManager):
config['aur_remove_build_dir'] = form_install.get_component('aur_remove_build_dir').get_selected()
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()
if not config['aur_build_dir']:
config['aur_build_dir'] = None

View File

@@ -180,3 +180,8 @@ class ArchPackage(SoftwarePackage):
else:
return ACTIONS_AUR_ENABLE_PKGBUILD_EDITION
def __hash__(self):
if self.view_name is not None:
return hash((self.view_name, self.repository))
else:
return hash((self.name, self.repository))

View File

@@ -914,8 +914,8 @@ def get_cache_dir() -> str:
return '/var/cache/pacman/pkg'
def map_required_by(names: Iterable[str] = None) -> Dict[str, Set[str]]:
output = run_cmd('pacman -Qi {}'.format(' '.join(names) if names else ''))
def map_required_by(names: Iterable[str] = None, remote: bool = False) -> Dict[str, Set[str]]:
output = run_cmd('pacman -{} {}'.format('Sii' if remote else 'Qi', ' '.join(names) if names else ''), print_error=False)
if output:
res = {}

View File

@@ -42,6 +42,8 @@ arch.config.aur_remove_build_dir=Remove build directory (AUR)
arch.config.aur_remove_build_dir.tip=If a package's generated build directory should be removed after the operations is finished.
arch.config.clean_cache=Elimina les versions antigues
arch.config.clean_cache.tip=Si cal eliminar les versions antigues d'un paquet emmagatzemat al disc durant la desinstal·lació
arch.config.check_dependency_breakage=Check dependency version breakage
arch.config.check_dependency_breakage.tip=If, during the verification of upgrade requirements, specific versions of dependencies must also be checked. Example: package A depends on version 1.0 of B.
arch.config.edit_aur_pkgbuild=Edit PKGBUILD (AUR)
arch.config.edit_aur_pkgbuild.tip=If the PKGBUILD file of an AUR package should be displayed for editing before its installation/upgrade/downgrade
arch.config.mirrors_sort_limit=Mirrors sort limit
@@ -196,6 +198,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.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
arch.task.disk_cache=Indexing packages data

View File

@@ -42,6 +42,8 @@ arch.config.aur_remove_build_dir=Remove build directory (AUR)
arch.config.aur_remove_build_dir.tip=If a package's generated build directory should be removed after the operations is finished.
arch.config.clean_cache=Remove old versions
arch.config.clean_cache.tip=Whether old versions of a package stored on disk should be removed during uninstall
arch.config.check_dependency_breakage=Check dependency version breakage
arch.config.check_dependency_breakage.tip=If, during the verification of upgrade requirements, specific versions of dependencies must also be checked. Example: package A depends on version 1.0 of B.
arch.config.edit_aur_pkgbuild=Edit PKGBUILD (AUR)
arch.config.edit_aur_pkgbuild.tip=If the PKGBUILD file of an AUR package should be displayed for editing before its installation/upgrade/downgrade
arch.config.mirrors_sort_limit=Mirrors sort limit
@@ -196,6 +198,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.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
arch.task.disk_cache=Indexing packages data

View File

@@ -43,6 +43,8 @@ arch.config.aur_remove_build_dir=Remove build directory (AUR)
arch.config.aur_remove_build_dir.tip=If a package's generated build directory should be removed after the operations is finished.
arch.config.clean_cache=Remove old versions
arch.config.clean_cache.tip=Whether old versions of a package stored on disk should be removed during uninstall
arch.config.check_dependency_breakage=Check dependency version breakage
arch.config.check_dependency_breakage.tip=If, during the verification of upgrade requirements, specific versions of dependencies must also be checked. Example: package A depends on version 1.0 of B.
arch.config.edit_aur_pkgbuild=Edit PKGBUILD (AUR)
arch.config.edit_aur_pkgbuild.tip=If the PKGBUILD file of an AUR package should be displayed for editing before its installation/upgrade/downgrade
arch.config.mirrors_sort_limit=Mirrors sort limit
@@ -197,6 +199,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.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
arch.task.disk_cache=Indexing packages data

View File

@@ -42,6 +42,8 @@ arch.config.aur_remove_build_dir=Eliminar directorio de compilación (AUR)
arch.config.aur_remove_build_dir.tip=Si el directorio de compilación generado para un paquete debe ser eliminado una vez finalizada la operación.
arch.config.clean_cache=Eliminar versiones antiguas
arch.config.clean_cache.tip=Si las versiones antiguas de un paquete almacenado en el disco deben ser eliminadas durante la desinstalación
arch.config.check_dependency_breakage=Verificar rotura de versión de dependencia
arch.config.check_dependency_breakage.tip=Si, durante la verificación de los requisitos de actualización, también se deben verificar versiones específicas de las dependencias. Ejemplo: el paquete A depende de la versión 1.0 de B.
arch.config.edit_aur_pkgbuild=Editar PKGBUILD (AUR)
arch.config.edit_aur_pkgbuild.tip=Si el archivo PKGBUILD de un paquete AUR debe ser exhibido para edición antes de su instalación/actualización/degradación
arch.config.mirrors_sort_limit=Límite de ordenación de espejos
@@ -196,6 +198,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.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
arch.task.disk_cache=Indexando datos de paquetes

View File

@@ -42,6 +42,8 @@ arch.config.aur_remove_build_dir=Remove build directory (AUR)
arch.config.aur_remove_build_dir.tip=If a package's generated build directory should be removed after the operations is finished.
arch.config.clean_cache=Rimuovi le vecchie versioni
arch.config.clean_cache.tip=Se le vecchie versioni di un pacchetto memorizzate sul disco devono essere rimosse durante la disinstallazione
arch.config.check_dependency_breakage=Check dependency version breakage
arch.config.check_dependency_breakage.tip=If, during the verification of upgrade requirements, specific versions of dependencies must also be checked. Example: package A depends on version 1.0 of B.
arch.config.edit_aur_pkgbuild=Edit PKGBUILD (AUR)
arch.config.edit_aur_pkgbuild.tip=If the PKGBUILD file of an AUR package should be displayed for editing before its installation/upgrade/downgrade
arch.config.mirrors_sort_limit=Mirrors sort limit
@@ -196,6 +198,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.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
arch.task.disk_cache=Indexing packages data

View File

@@ -43,6 +43,8 @@ arch.config.aur_remove_build_dir=Remover diretório de construção (AUR)
arch.config.aur_remove_build_dir.tip=Se o diretório gerado para a construção de um pacote do AUR deve ser removido após a operação ser finalizada.
arch.config.clean_cache=Remover versões antigas
arch.config.clean_cache.tip=Se versões antigas de um pacote armazenadas em disco devem ser removidas durante a desinstalação
arch.config.check_dependency_breakage=Verificar quebra de dependência de versão
arch.config.check_dependency_breakage.tip=Se durante a verificação dos requisitos de atualização deve-se verificar também versões específicas de dependências. Exemplo: pacote A depende da versão 1.0 de B.
arch.config.edit_aur_pkgbuild=Editar PKGBUILD (AUR)
arch.config.edit_aur_pkgbuild.tip=Se o arquivo PKGBUILD de um pacote do AUR deve ser exibido para edição antes da instalação/atualização/reversão
arch.config.mirrors_sort_limit=Limite de ordenação de espelhos
@@ -196,6 +198,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.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
arch.task.disk_cache=Indexando dados de pacotes

View File

@@ -42,6 +42,8 @@ arch.config.aur_remove_build_dir=Remove build directory (AUR)
arch.config.aur_remove_build_dir.tip=If a package's generated build directory should be removed after the operations is finished.
arch.config.clean_cache=Remove old versions
arch.config.clean_cache.tip=Whether old versions of a package stored on disk should be removed during uninstall
arch.config.check_dependency_breakage=Check dependency version breakage
arch.config.check_dependency_breakage.tip=If, during the verification of upgrade requirements, specific versions of dependencies must also be checked. Example: package A depends on version 1.0 of B.
arch.config.edit_aur_pkgbuild=Edit PKGBUILD (AUR)
arch.config.edit_aur_pkgbuild.tip=If the PKGBUILD file of an AUR package should be displayed for editing before its installation/upgrade/downgrade
arch.config.mirrors_sort_limit=Ограничение сортировки зеркал
@@ -196,6 +198,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.sync.dep_breakage.reason={} requires {}
arch.sync_databases.substatus=Синхронизация баз данных пакетов
arch.sync_databases.substatus.error=Синхронизировать базу данных пакета не удалось
arch.task.disk_cache=Indexing packages data

View File

@@ -42,6 +42,8 @@ arch.config.aur_remove_build_dir=Remove build directory (AUR)
arch.config.aur_remove_build_dir.tip=If a package's generated build directory should be removed after the operations is finished.
arch.config.clean_cache=Önbelleği temizle
arch.config.clean_cache.tip=Disk üzerinde kurulu bir paketin eski sürümlerinin kaldırma sırasında kaldırılıp kaldırılmayacağı
arch.config.check_dependency_breakage=Check dependency version breakage
arch.config.check_dependency_breakage.tip=If, during the verification of upgrade requirements, specific versions of dependencies must also be checked. Example: package A depends on version 1.0 of B.
arch.config.edit_aur_pkgbuild=Edit PKGBUILD (AUR)
arch.config.edit_aur_pkgbuild.tip=If the PKGBUILD file of an AUR package should be displayed for editing before its installation/upgrade/downgrade
arch.config.mirrors_sort_limit=Yansı sıralama sınırı
@@ -196,6 +198,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.sync.dep_breakage.reason={} requires {}
arch.sync_databases.substatus=Paket veritabanı eşitleniyor
arch.sync_databases.substatus.error=Paket veritabanı eşitlenemedi
arch.task.disk_cache=Indexing packages data

View File

@@ -1,7 +1,8 @@
import logging
import time
from distutils.version import LooseVersion
from threading import Thread
from typing import Dict, Set, List, Tuple, Iterable
from typing import Dict, Set, List, Tuple, Iterable, Optional
from bauh.api.abstract.controller import UpgradeRequirements, UpgradeRequirement
from bauh.api.abstract.handler import ProcessWatcher
@@ -261,38 +262,53 @@ class UpdatesSummarizer:
context.pkgs_data.update(all_to_install_data)
self._fill_conflicts(context, context.to_remove.keys())
if context.to_install:
self.__fill_provided_map(context=context, pkgs=context.to_install, fill_installed=False)
tf = time.time()
self.logger.info("It took {0:.2f} seconds to retrieve required upgrade packages".format(tf - ti))
return True
def __fill_provided_map(self, context: UpdateRequirementsContext):
ti = time.time()
self.logger.info("Filling provided names")
context.installed_names = pacman.list_installed_names()
installed_to_ignore = set()
def __fill_provided_map(self, context: UpdateRequirementsContext, pkgs: Dict[str, ArchPackage], fill_installed: bool = True):
if pkgs:
ti = time.time()
self.logger.info("Filling provided names")
for pkgname in context.to_update:
pacman.fill_provided_map(pkgname, pkgname, context.provided_map)
installed_to_ignore.add(pkgname)
if not context.installed_names:
context.installed_names = pacman.list_installed_names()
pdata = context.pkgs_data.get(pkgname)
if pdata and pdata['p']:
pacman.fill_provided_map('{}={}'.format(pkgname, pdata['v']), pkgname, context.provided_map)
for p in pdata['p']:
pacman.fill_provided_map(p, pkgname, context.provided_map)
split_provided = p.split('=')
installed_to_ignore = set()
if len(split_provided) > 1 and split_provided[0] != p:
pacman.fill_provided_map(split_provided[0], pkgname, context.provided_map)
for pkgname in pkgs:
pacman.fill_provided_map(pkgname, pkgname, context.provided_map)
if installed_to_ignore: # filling the provided names of the installed
installed_to_query = context.installed_names.difference(installed_to_ignore)
if fill_installed:
installed_to_ignore.add(pkgname)
if installed_to_query:
context.provided_map.update(pacman.map_provided(remote=False, pkgs=installed_to_query))
pdata = context.pkgs_data.get(pkgname)
if pdata and pdata['p']:
pacman.fill_provided_map('{}={}'.format(pkgname, pdata['v']), pkgname, context.provided_map)
tf = time.time()
self.logger.info("Filling provided names took {0:.2f} seconds".format(tf - ti))
ver_split = pdata['v'].split('-')
if len(ver_split) > 1:
pacman.fill_provided_map('{}={}'.format(pkgname, '-'.join(ver_split[0:-1])), pkgname, context.provided_map)
for p in pdata['p']:
pacman.fill_provided_map(p, pkgname, context.provided_map)
split_provided = p.split('=')
if len(split_provided) > 1 and split_provided[0] != p:
pacman.fill_provided_map(split_provided[0], pkgname, context.provided_map)
if installed_to_ignore: # filling the provided names of the installed
installed_to_query = context.installed_names.difference(installed_to_ignore)
if installed_to_query:
context.provided_map.update(pacman.map_provided(remote=False, pkgs=installed_to_query))
tf = time.time()
self.logger.info("Filling provided names took {0:.2f} seconds".format(tf - ti))
def __fill_aur_index(self, context: UpdateRequirementsContext):
if context.arch_config['aur']:
@@ -381,7 +397,7 @@ class UpdatesSummarizer:
if aur_data:
context.pkgs_data.update(aur_data)
self.__fill_provided_map(context)
self.__fill_provided_map(context=context, pkgs=context.to_update)
if context.pkgs_data:
self._fill_conflicts(context)
@@ -394,6 +410,9 @@ class UpdatesSummarizer:
self.logger.error("Package '{}' not found".format(e.name))
return
if context.pkgs_data:
self._fill_dependency_breakage(context)
self.__update_context_based_on_to_remove(context)
if context.to_update:
@@ -558,3 +577,166 @@ class UpdatesSummarizer:
self._add_to_remove(pkgs_to_sync, {dep: {n} for dep in all_deps}, context, blacklist)
else:
self.logger.warning("Package '{}' could not be removed from the transaction context because its data was not loaded")
def _fill_dependency_breakage(self, context: UpdateRequirementsContext):
if bool(context.arch_config['check_dependency_breakage']) and (context.to_update or context.to_install):
ti = time.time()
self.logger.info("Begin: checking dependency breakage")
required_by = pacman.map_required_by(context.to_update.keys()) if context.to_update else {}
if context.to_install:
required_by.update(pacman.map_required_by(context.to_install.keys(), remote=True))
reqs_not_in_transaction = set()
reqs_in_transaction = set()
transaction_pkgs = {*context.to_update.keys(), *context.to_install.keys()}
for reqs in required_by.values():
for r in reqs:
if r in transaction_pkgs:
reqs_in_transaction.add(r)
elif r in context.installed_names:
reqs_not_in_transaction.add(r)
if not reqs_not_in_transaction and not reqs_in_transaction:
return
provided_versions = {}
for p in context.provided_map:
pkg_split = p.split('=')
if len(pkg_split) > 1:
versions = provided_versions.get(pkg_split[0])
if versions is None:
versions = set()
provided_versions[pkg_split[0]] = versions
versions.add(pkg_split[1])
if not provided_versions:
return
cannot_upgrade = set()
for pkg, deps in pacman.map_required_dependencies(*reqs_not_in_transaction).items():
self._add_dependency_breakage(pkgname=pkg,
pkgdeps=deps,
provided_versions=provided_versions,
cannot_upgrade=cannot_upgrade,
context=context)
for pkg in reqs_in_transaction:
data = context.pkgs_data[pkg]
if data and data['d']:
self._add_dependency_breakage(pkgname=pkg,
pkgdeps=data['d'],
provided_versions=provided_versions,
cannot_upgrade=cannot_upgrade,
context=context)
if cannot_upgrade:
cannot_upgrade.update(self._add_dependents_as_cannot_upgrade(context=context,
names=cannot_upgrade,
pkgs_available={*context.to_update.values(), *context.to_install.values()}))
for p in cannot_upgrade:
if p in context.to_update:
del context.to_update[p]
if p in context.repo_to_update:
del context.repo_to_update[p]
if p in context.aur_to_update:
del context.aur_to_update[p]
if p in context.pkgs_data:
del context.pkgs_data[p]
if p in context.to_install:
del context.to_install[p]
if p in context.repo_to_install:
del context.repo_to_install[p]
if p in context.aur_to_install:
del context.aur_to_install[p]
tf = time.time()
self.logger.info("End: checking dependency breakage. Time: {0:.2f} seconds".format(tf - ti))
def _add_dependents_as_cannot_upgrade(self, context: UpdateRequirementsContext, names: Iterable[str], pkgs_available: Set[ArchPackage], already_removed: Optional[Set[str]] = None, iteration_level: int = 0) -> Set[str]:
removed = set() if already_removed is None else already_removed
removed.update(names)
available = {p for p in pkgs_available if p.name not in removed}
to_remove = set()
if available:
for pkg in available:
if pkg.name not in removed:
data = context.pkgs_data.get(pkg.name)
if data and data['d']:
for dep in data['d']:
dep_providers = context.provided_map.get(dep)
if dep_providers:
for p in dep_providers:
if p in names:
to_remove.add(pkg.name)
if pkg.name not in context.cannot_upgrade:
reason = "{} {}".format(self.i18n['arch.info.depends on'].capitalize(), p)
context.cannot_upgrade[pkg.name] = UpgradeRequirement(pkg=pkg,
reason=reason,
sorting_priority=iteration_level - 1)
break
if to_remove:
removed.update(to_remove)
self._add_dependents_as_cannot_upgrade(context=context, names=to_remove, pkgs_available=available,
already_removed=to_remove, iteration_level=iteration_level-1)
return to_remove
def _add_dependency_breakage(self, pkgname: str, pkgdeps: Optional[Set[str]], provided_versions: Dict[str, Set[str]], cannot_upgrade: Set[str], context: UpdateRequirementsContext):
if pkgdeps:
for dep in pkgdeps:
dep_split = RE_DEP_OPERATORS.split(dep)
if len(dep_split) > 1 and dep_split[1]:
real_providers = context.provided_map.get(dep_split[0])
if real_providers:
versions = provided_versions.get(dep_split[0])
if versions:
op = ''.join(RE_DEP_OPERATORS.findall(dep))
if op == '=':
op = '=='
version_match = False
for v in versions:
provided_version, required_version = LooseVersion(v), LooseVersion(dep_split[1])
if eval('provided_version {} required_version'.format(op)):
version_match = True
break
if not version_match:
for pname in real_providers:
if pname not in cannot_upgrade:
provider = context.to_update.get(pname)
if provider:
cannot_upgrade.add(pname)
reason = self.i18n['arch.sync.dep_breakage.reason'].format(pkgname, dep)
context.cannot_upgrade[pname] = UpgradeRequirement(pkg=provider,
reason=reason)

View File

@@ -619,6 +619,7 @@ class FormMultipleSelectQt(QWidget):
help_icon = QLabel()
help_icon.setPixmap(pixmap_help)
help_icon.setToolTip(op.tooltip)
help_icon.setCursor(QCursor(Qt.PointingHandCursor))
widget.layout().addWidget(help_icon)
self._layout.addWidget(widget, line, col)

View File

@@ -193,7 +193,7 @@ class UpgradeSelected(AsyncAction):
self.manager = manager
self.i18n = i18n
def _req_as_option(self, req: UpgradeRequirement, tooltip: bool = True, custom_tooltip: str = None, required_size: bool = True) -> InputOption:
def _req_as_option(self, req: UpgradeRequirement, tooltip: bool = True, custom_tooltip: str = None, required_size: bool = True, display_sizes: bool = True) -> InputOption:
if req.pkg.installed:
icon_path = req.pkg.get_disk_icon_path()
@@ -205,15 +205,19 @@ class UpgradeSelected(AsyncAction):
else:
icon_path = req.pkg.get_type_icon_path()
size_str = '{}: {}'.format(self.i18n['size'].capitalize(),
'?' if req.extra_size is None else get_human_size_str(req.extra_size))
if required_size and req.extra_size != req.required_size:
size_str += ' ( {}: {} )'.format(self.i18n['action.update.pkg.required_size'].capitalize(),
'?' if req.required_size is None else get_human_size_str(req.required_size))
size_str = None
if display_sizes:
size_str = '{}: {}'.format(self.i18n['size'].capitalize(),
'?' if req.extra_size is None else get_human_size_str(req.extra_size))
if required_size and req.extra_size != req.required_size:
size_str += ' ( {}: {} )'.format(self.i18n['action.update.pkg.required_size'].capitalize(),
'?' if req.required_size is None else get_human_size_str(req.required_size))
label = '{}{} - {}'.format(req.pkg.name,
' ( {} )'.format(req.pkg.latest_version) if req.pkg.latest_version else '',
size_str)
label = '{}{}'.format(req.pkg.name,
' ( {} )'.format(req.pkg.latest_version) if req.pkg.latest_version else '')
if size_str:
label += ' - {}'.format(size_str)
return InputOption(label=label,
value=None,
@@ -232,11 +236,14 @@ class UpgradeSelected(AsyncAction):
return required, extra
def _gen_cannot_update_form(self, reqs: List[UpgradeRequirement]) -> FormComponent:
opts = [self._req_as_option(r, False, r.reason) for r in reqs]
def _gen_cannot_upgrade_form(self, reqs: List[UpgradeRequirement]) -> FormComponent:
reqs.sort(key=UpgradeRequirement.sort_by_priority)
opts = [self._req_as_option(req=r, tooltip=False, custom_tooltip=r.reason, display_sizes=False) for r in reqs]
comps = [MultipleSelectComponent(label='', options=opts, default_options=set(opts))]
return FormComponent(label=self.i18n['action.update.cannot_update_label'], components=comps)
return FormComponent(label='{} ( {}: {} )'.format(self.i18n['action.update.cannot_update_label'],
self.i18n['amount'].capitalize(), len(opts)),
components=comps)
def _gen_to_install_form(self, reqs: List[UpgradeRequirement]) -> Tuple[FormComponent, Tuple[int, int]]:
opts = [self._req_as_option(r, custom_tooltip=r.reason) for r in reqs]
@@ -396,7 +403,7 @@ class UpgradeSelected(AsyncAction):
comps, required_size, extra_size = [], 0, 0
if requirements.cannot_upgrade:
comps.append(self._gen_cannot_update_form(requirements.cannot_upgrade))
comps.append(self._gen_cannot_upgrade_form(requirements.cannot_upgrade))
if requirements.to_install:
req_form, reqs_size = self._gen_to_install_form(requirements.to_install)