mirror of
https://github.com/spalencsar/bearhub.git
synced 2026-07-08 10:54:15 +02:00
[arch] improvements -> upgrading firstly the keyring packages declared in 'SyncFirst' (/etc/pacman.conf) to avoid pacman downloading issues | only removing packages after downloading the required ones
This commit is contained in:
@@ -11,7 +11,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://raw.githubusercontent.com/vinifmor/bauh/staging/pictures/releases/0.9.7/arch_install_reason.png">
|
<img src="https://raw.githubusercontent.com/vinifmor/bauh/staging/pictures/releases/0.9.7/arch_install_reason.png">
|
||||||
</p>
|
</p>
|
||||||
- upgrade: only removing packages after downloading the required ones (when multi-threaded download is enabled)
|
- upgrade:
|
||||||
|
- upgrading firstly the keyring packages declared in **SyncFirst** (**/etc/pacman.conf**) to avoid pacman downloading issues
|
||||||
|
- only removing packages after downloading the required ones
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
- Arch
|
- Arch
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ class UpgradeRequirements:
|
|||||||
self.to_remove = to_remove # when an upgrading package conflicts with a not upgrading package ( check all the non-upgrading packages deps an add here [including those selected to upgrade as well]
|
self.to_remove = to_remove # when an upgrading package conflicts with a not upgrading package ( check all the non-upgrading packages deps an add here [including those selected to upgrade as well]
|
||||||
self.to_upgrade = to_upgrade
|
self.to_upgrade = to_upgrade
|
||||||
self.cannot_upgrade = cannot_upgrade
|
self.cannot_upgrade = cannot_upgrade
|
||||||
|
self.context = {} # caches relevant data to actually perform the upgrade
|
||||||
|
|
||||||
|
|
||||||
class TransactionResult:
|
class TransactionResult:
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from datetime import datetime
|
|||||||
from math import floor
|
from math import floor
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from typing import List, Set, Type, Tuple, Dict, Iterable
|
from typing import List, Set, Type, Tuple, Dict, Iterable, Optional
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
@@ -768,25 +768,93 @@ class ArchManager(SoftwareManager):
|
|||||||
|
|
||||||
return files
|
return files
|
||||||
|
|
||||||
def _upgrade_repo_pkgs(self, pkgs: List[str], handler: ProcessHandler, root_password: str, arch_config: dict, overwrite_files: bool = False,
|
def list_related(self, pkgs: Iterable[str], all_pkgs: Iterable[str], data: Dict[str, dict], related: Set[str], provided_map: Dict[str, Set[str]]) -> Set[str]:
|
||||||
status_handler: TransactionStatusHandler = None, skip_download: bool = False, sizes: Dict[str, int] = None, already_downloaded: int = 0) -> bool:
|
related.update(pkgs)
|
||||||
|
|
||||||
if not skip_download and self._should_download_packages(arch_config):
|
deps = set()
|
||||||
|
|
||||||
|
for pkg in pkgs:
|
||||||
|
pkg_deps = data[pkg]['d']
|
||||||
|
|
||||||
|
if pkg_deps:
|
||||||
|
deps.update({d for d in pkg_deps if d not in related})
|
||||||
|
|
||||||
|
if deps:
|
||||||
|
if not provided_map:
|
||||||
|
for p in all_pkgs:
|
||||||
|
for provided in data[p].get('p', {p}):
|
||||||
|
sources = provided_map.get(provided, set())
|
||||||
|
provided_map[provided] = sources
|
||||||
|
sources.add(p)
|
||||||
|
|
||||||
|
added_sources = set()
|
||||||
|
for dep in deps:
|
||||||
|
sources = provided_map.get(dep)
|
||||||
|
|
||||||
|
if sources:
|
||||||
|
for source in sources:
|
||||||
|
if source not in related:
|
||||||
|
related.add(source)
|
||||||
|
added_sources.add(source)
|
||||||
|
|
||||||
|
if added_sources:
|
||||||
|
self.list_related(added_sources, all_pkgs, data, related, provided_map)
|
||||||
|
|
||||||
|
return related
|
||||||
|
|
||||||
|
def _upgrade_repo_pkgs(self, to_upgrade: List[str], to_remove: Optional[Set[str]], handler: ProcessHandler, root_password: str,
|
||||||
|
multithread_download: bool, pkgs_data: Dict[str, dict], overwrite_files: bool = False,
|
||||||
|
status_handler: TransactionStatusHandler = None, sizes: Dict[str, int] = None, download: bool = True,
|
||||||
|
check_syncfirst: bool = True) -> bool:
|
||||||
|
|
||||||
|
to_sync_first = None
|
||||||
|
if check_syncfirst:
|
||||||
|
to_sync_first = [p for p in pacman.get_packages_to_sync_first() if p.endswith('-keyring') and p in to_upgrade]
|
||||||
|
|
||||||
|
if to_sync_first:
|
||||||
|
self.logger.info("Upgrading keyrings marked as 'SyncFirst'")
|
||||||
|
if not self._upgrade_repo_pkgs(to_upgrade=to_sync_first,
|
||||||
|
to_remove=None,
|
||||||
|
handler=handler,
|
||||||
|
root_password=root_password,
|
||||||
|
sizes=sizes,
|
||||||
|
download=True,
|
||||||
|
multithread_download=multithread_download,
|
||||||
|
pkgs_data=pkgs_data,
|
||||||
|
check_syncfirst=False):
|
||||||
|
return False
|
||||||
|
|
||||||
|
to_upgrade_remaining = [p for p in to_upgrade if p not in to_sync_first] if to_sync_first else to_upgrade
|
||||||
|
|
||||||
|
# pre-downloading all packages before removing any
|
||||||
|
if download:
|
||||||
try:
|
try:
|
||||||
downloaded = self._download_packages(pkgs, handler, root_password, sizes)
|
downloaded = self._download_packages(pkgnames=to_upgrade_remaining,
|
||||||
|
handler=handler,
|
||||||
|
root_password=root_password,
|
||||||
|
sizes=sizes,
|
||||||
|
multithreaded=multithread_download)
|
||||||
|
|
||||||
|
if downloaded < len(to_upgrade_remaining):
|
||||||
|
self._show_upgrade_download_failed(handler.watcher)
|
||||||
|
return False
|
||||||
|
|
||||||
except ArchDownloadException:
|
except ArchDownloadException:
|
||||||
|
self._show_upgrade_download_failed(handler.watcher)
|
||||||
return False
|
return False
|
||||||
else:
|
|
||||||
downloaded = already_downloaded
|
if to_remove and not self._remove_transaction_packages(to_remove, handler, root_password):
|
||||||
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if status_handler:
|
if status_handler:
|
||||||
output_handler = status_handler
|
output_handler = status_handler
|
||||||
else:
|
else:
|
||||||
output_handler = TransactionStatusHandler(handler.watcher, self.i18n, len(pkgs), self.logger, downloading=downloaded)
|
output_handler = TransactionStatusHandler(handler.watcher, self.i18n, len(to_upgrade), self.logger, downloading=len(to_upgrade_remaining))
|
||||||
output_handler.start()
|
output_handler.start()
|
||||||
|
|
||||||
success, upgrade_output = handler.handle_simple(pacman.upgrade_several(pkgnames=pkgs,
|
self.logger.info("Upgrading {} repository packages: {}".format(len(to_upgrade), ', '.join(to_upgrade)))
|
||||||
|
success, upgrade_output = handler.handle_simple(pacman.upgrade_several(pkgnames=to_upgrade_remaining,
|
||||||
root_password=root_password,
|
root_password=root_password,
|
||||||
overwrite_conflicting_files=overwrite_files),
|
overwrite_conflicting_files=overwrite_files),
|
||||||
output_handler=output_handler.handle,)
|
output_handler=output_handler.handle,)
|
||||||
@@ -797,10 +865,10 @@ class ArchManager(SoftwareManager):
|
|||||||
output_handler.join()
|
output_handler.join()
|
||||||
handler.watcher.print("Repository packages successfully upgraded")
|
handler.watcher.print("Repository packages successfully upgraded")
|
||||||
handler.watcher.change_substatus(self.i18n['arch.upgrade.caching_pkgs_data'])
|
handler.watcher.change_substatus(self.i18n['arch.upgrade.caching_pkgs_data'])
|
||||||
repo_map = pacman.map_repositories(pkgs)
|
repo_map = pacman.map_repositories(to_upgrade_remaining)
|
||||||
|
|
||||||
pkg_map = {}
|
pkg_map = {}
|
||||||
for name in pkgs:
|
for name in to_upgrade_remaining:
|
||||||
repo = repo_map.get(name)
|
repo = repo_map.get(name)
|
||||||
pkg_map[name] = ArchPackage(name=name,
|
pkg_map[name] = ArchPackage(name=name,
|
||||||
repository=repo,
|
repository=repo,
|
||||||
@@ -817,13 +885,16 @@ class ArchManager(SoftwareManager):
|
|||||||
confirmation_label=self.i18n['arch.upgrade.conflicting_files.stop'],
|
confirmation_label=self.i18n['arch.upgrade.conflicting_files.stop'],
|
||||||
components=files):
|
components=files):
|
||||||
|
|
||||||
return self._upgrade_repo_pkgs(pkgs=pkgs,
|
return self._upgrade_repo_pkgs(to_upgrade=to_upgrade_remaining,
|
||||||
handler=handler,
|
handler=handler,
|
||||||
root_password=root_password,
|
root_password=root_password,
|
||||||
overwrite_files=True,
|
overwrite_files=True,
|
||||||
status_handler=output_handler,
|
status_handler=output_handler,
|
||||||
skip_download=True,
|
multithread_download=multithread_download,
|
||||||
arch_config=arch_config,
|
download=False,
|
||||||
|
check_syncfirst=False,
|
||||||
|
pkgs_data=pkgs_data,
|
||||||
|
to_remove=None,
|
||||||
sizes=sizes)
|
sizes=sizes)
|
||||||
else:
|
else:
|
||||||
output_handler.stop_working()
|
output_handler.stop_working()
|
||||||
@@ -842,27 +913,26 @@ class ArchManager(SoftwareManager):
|
|||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _remove_transaction_packages(self, requirements: UpgradeRequirements, handler: ProcessHandler, root_password: str) -> bool:
|
def _remove_transaction_packages(self, to_remove: Set[str], handler: ProcessHandler, root_password: str) -> bool:
|
||||||
to_remove_names = {r.pkg.name for r in requirements.to_remove}
|
|
||||||
output_handler = TransactionStatusHandler(watcher=handler.watcher,
|
output_handler = TransactionStatusHandler(watcher=handler.watcher,
|
||||||
i18n=self.i18n,
|
i18n=self.i18n,
|
||||||
pkgs_to_sync=0,
|
pkgs_to_sync=0,
|
||||||
logger=self.logger,
|
logger=self.logger,
|
||||||
pkgs_to_remove=len(to_remove_names))
|
pkgs_to_remove=len(to_remove))
|
||||||
output_handler.start()
|
output_handler.start()
|
||||||
try:
|
try:
|
||||||
success = handler.handle(pacman.remove_several(pkgnames=to_remove_names, root_password=root_password, skip_checks=True),
|
success = handler.handle(pacman.remove_several(pkgnames=to_remove, root_password=root_password, skip_checks=True),
|
||||||
output_handler=output_handler.handle)
|
output_handler=output_handler.handle)
|
||||||
|
|
||||||
if not success:
|
if not success:
|
||||||
self.logger.error("Could not remove packages: {}".format(', '.join(to_remove_names)))
|
self.logger.error("Could not remove packages: {}".format(', '.join(to_remove)))
|
||||||
output_handler.stop_working()
|
output_handler.stop_working()
|
||||||
output_handler.join()
|
output_handler.join()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
except:
|
except:
|
||||||
self.logger.error("An error occured while removing packages: {}".format(', '.join(to_remove_names)))
|
self.logger.error("An error occured while removing packages: {}".format(', '.join(to_remove)))
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
output_handler.stop_working()
|
output_handler.stop_working()
|
||||||
output_handler.join()
|
output_handler.join()
|
||||||
@@ -899,45 +969,19 @@ class ArchManager(SoftwareManager):
|
|||||||
arch_config = read_config()
|
arch_config = read_config()
|
||||||
self._sync_databases(arch_config=arch_config, root_password=root_password, handler=handler)
|
self._sync_databases(arch_config=arch_config, root_password=root_password, handler=handler)
|
||||||
|
|
||||||
# for now if the multithreaded-download is disabled packages will be removed before the download:
|
|
||||||
multithreaded_download = self._should_download_packages(arch_config)
|
|
||||||
|
|
||||||
if requirements.to_remove and (not repo_pkgs or not multithreaded_download):
|
|
||||||
if not self._remove_transaction_packages(requirements, handler, root_password):
|
|
||||||
return False
|
|
||||||
|
|
||||||
if repo_pkgs:
|
if repo_pkgs:
|
||||||
repo_pkgs_names = [p.name for p in repo_pkgs]
|
if not self._upgrade_repo_pkgs(to_upgrade=[p.name for p in repo_pkgs],
|
||||||
|
to_remove={r.pkg.name for r in requirements.to_remove} if requirements.to_remove else None,
|
||||||
downloaded = -1
|
|
||||||
if requirements.to_remove and multithreaded_download: # pre-downloading all packages before removing any
|
|
||||||
try:
|
|
||||||
downloaded = self._download_packages(repo_pkgs_names, handler, root_password, pkg_sizes)
|
|
||||||
|
|
||||||
if downloaded < len(repo_pkgs_names):
|
|
||||||
self._show_upgrade_download_failed(handler.watcher)
|
|
||||||
return False
|
|
||||||
|
|
||||||
except ArchDownloadException:
|
|
||||||
self._show_upgrade_download_failed(handler.watcher)
|
|
||||||
return False
|
|
||||||
|
|
||||||
if not self._remove_transaction_packages(requirements, handler, root_password):
|
|
||||||
return False
|
|
||||||
|
|
||||||
watcher.change_status('{}...'.format(self.i18n['arch.upgrade.upgrade_repo_pkgs']))
|
|
||||||
self.logger.info("Upgrading {} repository packages: {}".format(len(repo_pkgs_names),
|
|
||||||
', '.join(repo_pkgs_names)))
|
|
||||||
|
|
||||||
if not self._upgrade_repo_pkgs(pkgs=repo_pkgs_names,
|
|
||||||
handler=handler,
|
handler=handler,
|
||||||
root_password=root_password,
|
root_password=root_password,
|
||||||
arch_config=arch_config,
|
multithread_download=self._multithreaded_download_enabled(arch_config),
|
||||||
skip_download=downloaded >= 0,
|
pkgs_data=requirements.context['data'],
|
||||||
already_downloaded=0 if downloaded < 0 else downloaded,
|
|
||||||
sizes=pkg_sizes):
|
sizes=pkg_sizes):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
elif requirements.to_remove and not self._remove_transaction_packages({r.pkg.name for r in requirements.to_remove}, handler, root_password):
|
||||||
|
return False
|
||||||
|
|
||||||
if aur_pkgs:
|
if aur_pkgs:
|
||||||
watcher.change_status('{}...'.format(self.i18n['arch.upgrade.upgrade_aur_pkgs']))
|
watcher.change_status('{}...'.format(self.i18n['arch.upgrade.upgrade_aur_pkgs']))
|
||||||
for pkg in aur_pkgs:
|
for pkg in aur_pkgs:
|
||||||
@@ -1450,10 +1494,10 @@ class ArchManager(SoftwareManager):
|
|||||||
return {dep}
|
return {dep}
|
||||||
|
|
||||||
downloaded = 0
|
downloaded = 0
|
||||||
if self._should_download_packages(context.config):
|
if self._multithreaded_download_enabled(context.config):
|
||||||
try:
|
try:
|
||||||
pkg_sizes = pacman.map_download_sizes(repo_dep_names)
|
pkg_sizes = pacman.map_download_sizes(repo_dep_names)
|
||||||
downloaded = self._download_packages(repo_dep_names, context.handler, context.root_password, pkg_sizes)
|
downloaded = self._download_packages(repo_dep_names, context.handler, context.root_password, pkg_sizes, multithreaded=True)
|
||||||
except ArchDownloadException:
|
except ArchDownloadException:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -1756,21 +1800,36 @@ class ArchManager(SoftwareManager):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _should_download_packages(self, arch_config: dict) -> bool:
|
def _multithreaded_download_enabled(self, arch_config: dict) -> bool:
|
||||||
return bool(arch_config['repositories_mthread_download']) \
|
return bool(arch_config['repositories_mthread_download']) \
|
||||||
and self.context.file_downloader.is_multithreaded() \
|
and self.context.file_downloader.is_multithreaded() \
|
||||||
and pacman.is_mirrors_available()
|
and pacman.is_mirrors_available()
|
||||||
|
|
||||||
def _download_packages(self, pkgnames: List[str], handler: ProcessHandler, root_password: str, sizes: Dict[str, int] = None) -> int:
|
def _download_packages(self, pkgnames: List[str], handler: ProcessHandler, root_password: str, sizes: Dict[str, int] = None, multithreaded: bool = True) -> int:
|
||||||
download_service = MultithreadedDownloadService(file_downloader=self.context.file_downloader,
|
if multithreaded:
|
||||||
http_client=self.http_client,
|
download_service = MultithreadedDownloadService(file_downloader=self.context.file_downloader,
|
||||||
logger=self.context.logger,
|
http_client=self.http_client,
|
||||||
i18n=self.i18n)
|
logger=self.context.logger,
|
||||||
self.logger.info("Initializing multi-threaded download for {} package(s)".format(len(pkgnames)))
|
i18n=self.i18n)
|
||||||
return download_service.download_packages(pkgs=pkgnames,
|
self.logger.info("Initializing multi-threaded download for {} repository package(s)".format(len(pkgnames)))
|
||||||
handler=handler,
|
return download_service.download_packages(pkgs=pkgnames,
|
||||||
sizes=sizes,
|
handler=handler,
|
||||||
root_password=root_password)
|
sizes=sizes,
|
||||||
|
root_password=root_password)
|
||||||
|
else:
|
||||||
|
self.logger.info("Downloading {} repository package(s)".format(len(pkgnames)))
|
||||||
|
output_handler = TransactionStatusHandler(handler.watcher, self.i18n, len(pkgnames), self.logger)
|
||||||
|
output_handler.start()
|
||||||
|
try:
|
||||||
|
success, _ = handler.handle_simple(pacman.download(root_password, *pkgnames), output_handler=output_handler.handle)
|
||||||
|
|
||||||
|
if success:
|
||||||
|
return len(pkgnames)
|
||||||
|
else:
|
||||||
|
raise ArchDownloadException()
|
||||||
|
except:
|
||||||
|
traceback.print_exc()
|
||||||
|
raise ArchDownloadException()
|
||||||
|
|
||||||
def _install(self, context: TransactionContext) -> bool:
|
def _install(self, context: TransactionContext) -> bool:
|
||||||
check_install_output = []
|
check_install_output = []
|
||||||
@@ -1830,13 +1889,13 @@ class ArchManager(SoftwareManager):
|
|||||||
to_install.append(pkgpath)
|
to_install.append(pkgpath)
|
||||||
|
|
||||||
downloaded = 0
|
downloaded = 0
|
||||||
if self._should_download_packages(context.config):
|
if self._multithreaded_download_enabled(context.config):
|
||||||
to_download = [p for p in to_install if not p.startswith('/')]
|
to_download = [p for p in to_install if not p.startswith('/')]
|
||||||
|
|
||||||
if to_download:
|
if to_download:
|
||||||
try:
|
try:
|
||||||
pkg_sizes = pacman.map_download_sizes(to_download)
|
pkg_sizes = pacman.map_download_sizes(to_download)
|
||||||
downloaded = self._download_packages(to_download, context.handler, context.root_password, pkg_sizes)
|
downloaded = self._download_packages(to_download, context.handler, context.root_password, pkg_sizes, multithreaded=True)
|
||||||
except ArchDownloadException:
|
except ArchDownloadException:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ RE_DOWNLOAD_SIZE = re.compile(r'Download Size\s*:\s*([0-9,\.]+)\s(\w+)\n?', re.I
|
|||||||
RE_UPDATE_REQUIRED_FIELDS = re.compile(r'(\bProvides\b|\bInstalled Size\b|\bConflicts With\b)\s*:\s(.+)\n')
|
RE_UPDATE_REQUIRED_FIELDS = re.compile(r'(\bProvides\b|\bInstalled Size\b|\bConflicts With\b)\s*:\s(.+)\n')
|
||||||
RE_REMOVE_TRANSITIVE_DEPS = re.compile(r'removing\s([\w\-_]+)\s.+required\sby\s([\w\-_]+)\n?')
|
RE_REMOVE_TRANSITIVE_DEPS = re.compile(r'removing\s([\w\-_]+)\s.+required\sby\s([\w\-_]+)\n?')
|
||||||
RE_AVAILABLE_MIRRORS = re.compile(r'.+\s+OK\s+.+\s+(\d+:\d+)\s+.+(http.+)')
|
RE_AVAILABLE_MIRRORS = re.compile(r'.+\s+OK\s+.+\s+(\d+:\d+)\s+.+(http.+)')
|
||||||
|
RE_PACMAN_SYNC_FIRST = re.compile(r'SyncFirst\s*=\s*(.+)')
|
||||||
|
|
||||||
|
|
||||||
def is_available() -> bool:
|
def is_available() -> bool:
|
||||||
@@ -733,6 +734,12 @@ def upgrade_several(pkgnames: Iterable[str], root_password: str, overwrite_confl
|
|||||||
error_phrases={'error: failed to prepare transaction', 'error: failed to commit transaction', 'error: target not found'})
|
error_phrases={'error: failed to prepare transaction', 'error: failed to commit transaction', 'error: target not found'})
|
||||||
|
|
||||||
|
|
||||||
|
def download(root_password: str, *pkgnames: str) -> SimpleProcess:
|
||||||
|
return SimpleProcess(cmd=['pacman', '-Swdd', *pkgnames, '--noconfirm'],
|
||||||
|
root_password=root_password,
|
||||||
|
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, skip_checks: bool = False) -> SystemProcess:
|
def remove_several(pkgnames: Iterable[str], root_password: str, skip_checks: bool = False) -> SystemProcess:
|
||||||
cmd = ['pacman', '-R', *pkgnames, '--noconfirm']
|
cmd = ['pacman', '-R', *pkgnames, '--noconfirm']
|
||||||
|
|
||||||
@@ -1119,3 +1126,13 @@ def get_mirrors_branch() -> str:
|
|||||||
_, output = system.run(['pacman-mirrors', '-G'])
|
_, output = system.run(['pacman-mirrors', '-G'])
|
||||||
return output.strip()
|
return output.strip()
|
||||||
|
|
||||||
|
|
||||||
|
def get_packages_to_sync_first() -> Set[str]:
|
||||||
|
if os.path.exists('/etc/pacman.conf'):
|
||||||
|
with open('/etc/pacman.conf') as f:
|
||||||
|
to_sync_first = RE_PACMAN_SYNC_FIRST.findall(f.read())
|
||||||
|
|
||||||
|
if to_sync_first:
|
||||||
|
return {s.strip() for s in to_sync_first[0].split(' ') if s and s.strip()}
|
||||||
|
|
||||||
|
return set()
|
||||||
|
|||||||
@@ -424,6 +424,7 @@ class UpdatesSummarizer:
|
|||||||
to_sync.update(context.to_install.keys())
|
to_sync.update(context.to_install.keys())
|
||||||
res.to_install = [self._map_requirement(p, context, to_install=True, to_sync=to_sync) for p in context.to_install.values()]
|
res.to_install = [self._map_requirement(p, context, to_install=True, to_sync=to_sync) for p in context.to_install.values()]
|
||||||
|
|
||||||
|
res.context['data'] = context.pkgs_data
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def __update_context_based_on_to_remove(self, context: UpdateRequirementsContext):
|
def __update_context_based_on_to_remove(self, context: UpdateRequirementsContext):
|
||||||
|
|||||||
Reference in New Issue
Block a user