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 __update_context_based_on_to_remove( self, context: UpdateRequirementsContext): if context.to_remove: to_remove_provided = {} # filtering all package to synchronization from the transaction context to_sync = { *(context.to_update.keys() if context.to_update else set()), *(context.to_install.keys() if context.to_install else set()) } if to_sync: # checking if any packages to sync on the context rely on the 'to remove' ones to_remove_provided.update( pacman.map_provided(remote=False, pkgs=context.to_remove.keys())) to_remove_from_sync = { } # will store all packages that should be removed for pname in to_sync: if pname in context.pkgs_data: deps = context.pkgs_data[pname].get('d') if deps: required = set() for pkg in context.to_remove: for provided in to_remove_provided[pkg]: if provided in deps: required.add(pkg) break if required: to_remove_from_sync[pname] = required else: self.logger.warning( "Conflict resolution: package '{}' marked to synchronization has no data loaded" ) if to_remove_from_sync: # removing all these packages and their dependents from the context self._add_to_remove(to_sync, to_remove_from_sync, context) # checking if the installed packages that are not in the transaction context rely on the current packages to be removed: current_to_remove = {*context.to_remove.keys()} required_by_installed = self.deps_analyser.map_all_required_by( current_to_remove, {*to_sync}) if required_by_installed: # updating provided context: provided_not_mapped = set() for pkg in current_to_remove.difference( {*to_remove_provided.keys()}): if pkg not in context.pkgs_data: provided_not_mapped.add(pkg) else: provided = context.pkgs_data[pkg].get('p') if provided: to_remove_provided[pkg] = provided else: provided_not_mapped.add(pkg) if provided_not_mapped: to_remove_provided.update( pacman.map_provided(remote=False, pkgs=provided_not_mapped)) deps_no_data = { dep for dep in required_by_installed if dep in context.pkgs_data } deps_nodata_deps = pacman.map_required_dependencies( *deps_no_data) if deps_no_data else {} reverse_to_remove_provided = { p: name for name, provided in to_remove_provided.items() for p in provided } for pkg in required_by_installed: if pkg not in context.to_remove: if pkg in context.pkgs_data: dep_deps = context.pkgs_data[pkg].get('d') else: dep_deps = deps_nodata_deps.get(pkg) if dep_deps: source = ', '.join( (reverse_to_remove_provided[d] for d in dep_deps if d in reverse_to_remove_provided)) reason = "{} '{}'".format( self.i18n['arch.info.depends on'].capitalize(), source if source else '?') context.to_remove[pkg] = UpgradeRequirement( pkg=ArchPackage(name=pkg, installed=True, i18n=self.i18n), reason=reason) for name in context.to_remove: # upgrading lists if name in context.pkgs_data: del context.pkgs_data[name] if name in context.aur_to_update: del context.aur_to_update[name] if name in context.repo_to_update: del context.repo_to_update[name] removed_size = pacman.get_installed_size( [*context.to_remove.keys()]) if removed_size: for name, size in removed_size.items(): if size is not None: req = context.to_remove.get(name) if req: req.extra_size = size