[improvement][arch] able to handle upgrade scenarios when a package wants to overwrite files of another installed package

This commit is contained in:
Vinicius Moreira
2020-05-03 17:44:23 -03:00
parent 08ddea55fd
commit 76e6194c52
11 changed files with 98 additions and 28 deletions

View File

@@ -21,7 +21,7 @@ from bauh.api.abstract.handler import ProcessWatcher, TaskManager
from bauh.api.abstract.model import PackageUpdate, PackageHistory, SoftwarePackage, PackageSuggestion, PackageStatus, \
SuggestionPriority, CustomSoftwareAction
from bauh.api.abstract.view import MessageType, FormComponent, InputOption, SingleSelectComponent, SelectViewType, \
ViewComponent, PanelComponent, MultipleSelectComponent, TextInputComponent
ViewComponent, PanelComponent, MultipleSelectComponent, TextInputComponent, TextComponent
from bauh.api.constants import TEMP_DIR
from bauh.commons import user
from bauh.commons.category import CategoriesDownloader
@@ -189,6 +189,7 @@ class ArchManager(SoftwareManager):
manager=self)
}
self.index_aur = None
self.re_file_conflict = re.compile(r'[\w\d\-_.]+:')
@staticmethod
def get_semantic_search_map() -> Dict[str, str]:
@@ -690,6 +691,66 @@ class ArchManager(SoftwareManager):
return False
def _map_conflicting_file(self, output: str) -> List[TextComponent]:
error_idx = None
lines = output.split('\n')
for idx, l in enumerate(lines):
if l and l.strip().lower().startswith('error: failed to commit transaction (conflicting files)'):
error_idx = idx
break
files = []
if error_idx and error_idx + 1 < len(lines):
for idx in range(error_idx + 1, len(lines)):
line = lines[idx].strip()
if line and self.re_file_conflict.match(line):
files.append(TextComponent(' - {}'.format(line)))
return files
def _upgrade_repo_pkgs(self, pkgs: List[str], handler: ProcessHandler, root_password: str, overwrite_files: bool = False) -> bool:
try:
output_handler = TransactionStatusHandler(handler.watcher, self.i18n, len(pkgs), self.logger)
output_handler.start()
success, upgrade_output = handler.handle_simple(pacman.upgrade_several(pkgnames=pkgs,
root_password=root_password,
overwrite_conflicting_files=overwrite_files),
output_handler=output_handler.handle,)
output_handler.stop_working()
output_handler.join()
handler.watcher.change_substatus('')
if success:
handler.watcher.print("Repository packages successfully upgraded")
handler.watcher.change_substatus(self.i18n['arch.upgrade.caching_pkgs_data'])
repo_map = pacman.map_repositories(pkgs)
disk.save_several(pkgs, repo_map=repo_map, overwrite=True, maintainer=None)
return True
elif 'conflicting files' in upgrade_output:
files = self._map_conflicting_file(upgrade_output)
if not handler.watcher.request_confirmation(title=self.i18n['warning'].capitalize(),
body=self.i18n['arch.upgrade.error.conflicting_files'] + ':',
deny_label=self.i18n['arch.upgrade.conflicting_files.proceed'],
confirmation_label=self.i18n['arch.upgrade.conflicting_files.stop'],
components=files):
return self._upgrade_repo_pkgs(pkgs=pkgs, handler=handler, root_password=root_password, overwrite_files=True)
else:
handler.watcher.print("Aborted by the user")
return False
else:
self.logger.error("'pacman' returned an unexpected response or error phrase after upgrading the repository packages")
return False
except:
handler.watcher.change_substatus('')
handler.watcher.print("An error occurred while upgrading repository packages")
self.logger.error("An error occurred while upgrading repository packages")
traceback.print_exc()
return False
def upgrade(self, requirements: UpgradeRequirements, root_password: str, watcher: ProcessWatcher) -> bool:
self.aur_client.clean_caches()
watcher.change_status("{}...".format(self.i18n['manage_window.status.upgrading']))
@@ -733,29 +794,7 @@ class ArchManager(SoftwareManager):
self.logger.info("Upgrading {} repository packages: {}".format(len(repo_pkgs_names),
', '.join(repo_pkgs_names)))
try:
output_handler = TransactionStatusHandler(watcher, self.i18n, len(repo_pkgs_names), self.logger)
output_handler.start()
success, _ = handler.handle_simple(pacman.upgrade_several(repo_pkgs_names, root_password), output_handler=output_handler.handle)
output_handler.stop_working()
output_handler.join()
watcher.change_substatus('')
if success:
watcher.print("Repository packages successfully upgraded")
watcher.change_substatus(self.i18n['arch.upgrade.caching_pkgs_data'])
repo_map = pacman.map_repositories(repo_pkgs_names)
disk.save_several(repo_pkgs_names, repo_map=repo_map, overwrite=True, maintainer=None)
else:
self.logger.error("'pacman' returned an unexpected response or error phrase after upgrading the repository packages")
return False
except:
watcher.change_substatus('')
watcher.print("An error occurred while upgrading repository packages")
self.logger.error("An error occurred while upgrading repository packages")
traceback.print_exc()
if not self._upgrade_repo_pkgs(pkgs=repo_pkgs_names, handler=handler, root_password=root_password):
return False
watcher.change_status('{}...'.format(self.i18n['arch.upgrade.upgrade_aur_pkgs']))

View File

@@ -144,7 +144,7 @@ def install_as_process(pkgpaths: Iterable[str], root_password: str, file: bool,
return SimpleProcess(cmd=cmd,
root_password=root_password,
cwd=pkgdir,
error_phrases={"error: failed to prepare transaction", 'error: failed to commit transaction'})
error_phrases={"error: failed to prepare transaction", 'error: failed to commit transaction', 'error: target not found'})
def list_desktop_entries(pkgnames: Set[str]) -> List[str]:
@@ -693,10 +693,15 @@ def list_installed_names() -> Set[str]:
return {p for p in run_cmd('pacman -Qq').split('\n') if p}
def upgrade_several(pkgnames: Iterable[str], root_password: str) -> SimpleProcess:
return SimpleProcess(cmd=['pacman', '-S', *pkgnames, '--noconfirm'],
def upgrade_several(pkgnames: Iterable[str], root_password: str, overwrite_conflicting_files: bool = False) -> SimpleProcess:
cmd = ['pacman', '-S', *pkgnames, '--noconfirm']
if overwrite_conflicting_files:
cmd.append('--overwrite=*')
return SimpleProcess(cmd=cmd,
root_password=root_password,
error_phrases={'error: failed to prepare transaction', 'error: failed to commit transaction'})
error_phrases={'error: failed to prepare transaction', 'error: failed to commit transaction', 'error: target not found'})
def remove_several(pkgnames: Iterable[str], root_password: str) -> SystemProcess:

View File

@@ -188,6 +188,9 @@ arch.update_summary.to_install.dep_conflict=Conflict between the dependencies {}
arch.update_summary.to_update.conflicts_dep=Conflicts with the dependency {} of {}
arch.update_summary.to_update.dep_conflicts=Dependency {} conflicts with {}
arch.upgrade.caching_pkgs_data=Caching upgrades data
arch.upgrade.error.conflicting_files=Some of the packages being upgraded want to overwrite files of another installed packages
arch.upgrade.conflicting_files.proceed=Allow and continue
arch.upgrade.conflicting_files.stop=Cancel upgrading
arch.upgrade.fail=Package {} upgrade failed
arch.upgrade.success=Package {} successfully upgraded
arch.upgrade.upgrade_aur_pkgs=Upgrading AUR packages

View File

@@ -188,6 +188,9 @@ arch.update_summary.to_install.dep_conflict=Conflict between the dependencies {}
arch.update_summary.to_update.conflicts_dep=Conflicts with the dependency {} of {}
arch.update_summary.to_update.dep_conflicts=Dependency {} conflicts with {}
arch.upgrade.caching_pkgs_data=Caching upgrades data
arch.upgrade.error.conflicting_files=Some of the packages being upgraded want to overwrite files of another installed packages
arch.upgrade.conflicting_files.proceed=Allow and continue
arch.upgrade.conflicting_files.stop=Cancel upgrading
arch.upgrade.fail=Package {} upgrade failed
arch.upgrade.success=Package {} successfully upgraded
arch.upgrade.upgrade_aur_pkgs=Upgrading AUR packages

View File

@@ -188,6 +188,9 @@ arch.update_summary.to_install.dep_conflict=Conflict between the dependencies {}
arch.update_summary.to_update.conflicts_dep=Conflicts with the dependency {} of {}
arch.update_summary.to_update.dep_conflicts=Dependency {} conflicts with {}
arch.upgrade.caching_pkgs_data=Caching upgrades data
arch.upgrade.error.conflicting_files=Some of the packages being upgraded want to overwrite files of another installed packages
arch.upgrade.conflicting_files.proceed=Allow and continue
arch.upgrade.conflicting_files.stop=Cancel upgrading
arch.upgrade.fail=Package {} upgrade failed
arch.upgrade.success=Package {} successfully upgraded
arch.upgrade.upgrade_aur_pkgs=Upgrading AUR packages

View File

@@ -188,6 +188,9 @@ arch.update_summary.to_install.dep_conflict=Conflicto entre las dependencias {}
arch.update_summary.to_update.conflicts_dep=Conflicta con la dependencia {} de {}
arch.update_summary.to_update.dep_conflicts=La dependencia {} conflicta con {}
arch.upgrade.caching_pkgs_data=Caching upgrades data
arch.upgrade.error.conflicting_files=Algunos de los paquetes que se están actualizando desean sobrescribir archivos de otros paquetes instalados
arch.upgrade.conflicting_files.proceed=Permitir y continuar
arch.upgrade.conflicting_files.stop=Cancelar la actualización
arch.upgrade.fail=Falló la actualización del paquete {}
arch.upgrade.success=Paquete {} actualizado con éxito
arch.upgrade.upgrade_aur_pkgs=Actualizando paquetes de AUR

View File

@@ -188,6 +188,9 @@ arch.update_summary.to_install.dep_conflict=Conflict between the dependencies {}
arch.update_summary.to_update.conflicts_dep=Conflicts with the dependency {} of {}
arch.update_summary.to_update.dep_conflicts=Dependency {} conflicts with {}
arch.upgrade.caching_pkgs_data=Caching upgrades data
arch.upgrade.error.conflicting_files=Some of the packages being upgraded want to overwrite files of another installed packages
arch.upgrade.conflicting_files.proceed=Allow and continue
arch.upgrade.conflicting_files.stop=Cancel upgrading
arch.upgrade.fail=Package {} upgrade failed
arch.upgrade.success=Package {} successfully upgraded
arch.upgrade.upgrade_aur_pkgs=Upgrading AUR packages

View File

@@ -188,6 +188,9 @@ arch.update_summary.to_install.dep_conflict=Conflito entre as dependências {} e
arch.update_summary.to_update.conflicts_dep=Conflita com a dependência {} de {}
arch.update_summary.to_update.dep_conflicts=A dependência {} conflita com {}
arch.upgrade.caching_pkgs_data=Armazenando dados das atualizações
arch.upgrade.error.conflicting_files=Alguns dos pacotes que estão sendo atualizados querem sobrepor arquivos de outros pacotes instalados
arch.upgrade.conflicting_files.proceed=Permitir e continuar
arch.upgrade.conflicting_files.stop=Cancelar atualização
arch.upgrade.fail=Atualização do pacote {} falhou
arch.upgrade.success=Pacote {} atualizado com sucesso
arch.upgrade.upgrade_aur_pkgs=Atualizando pacotes do AUR

View File

@@ -188,6 +188,9 @@ arch.update_summary.to_install.dep_conflict=Конфликт между зави
arch.update_summary.to_update.conflicts_dep=Конфликты с зависимостью {} от {}
arch.update_summary.to_update.dep_conflicts=Зависимость {} конфликтует с {}
arch.upgrade.caching_pkgs_data=Caching upgrades data
arch.upgrade.error.conflicting_files=Some of the packages being upgraded want to overwrite files of another installed packages
arch.upgrade.conflicting_files.proceed=Allow and continue
arch.upgrade.conflicting_files.stop=Cancel upgrading
arch.upgrade.fail=Package {} upgrade failed
arch.upgrade.success=Package {} successfully upgraded
arch.upgrade.upgrade_aur_pkgs=Upgrading AUR packages

View File

@@ -188,6 +188,9 @@ arch.update_summary.to_install.dep_conflict={} ve {} bağımlılıkları arasın
arch.update_summary.to_update.conflicts_dep={} / {} bağımlılığıyla ilgili çakışmalar
arch.update_summary.to_update.dep_conflicts=Bağımlılık {} ile {} çakışıyor
arch.upgrade.caching_pkgs_data=Yükseltme verileri önbelleğe alınıyor
arch.upgrade.error.conflicting_files=Some of the packages being upgraded want to overwrite files of another installed packages
arch.upgrade.conflicting_files.proceed=Allow and continue
arch.upgrade.conflicting_files.stop=Cancel upgrading
arch.upgrade.fail={} paketi yükseltilemedi
arch.upgrade.success={} paketi başarıyla yükseltildi
arch.upgrade.upgrade_aur_pkgs=AUR paketleri yükseltiliyor