mirror of
https://github.com/spalencsar/bearhub.git
synced 2026-07-07 04:44:15 +02:00
[arch] improvement -> upgrade: checking specific version requirements and marking packages as 'cannot upgrade' when these requirements are not met
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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 = {}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user