|
|
4f4af9 |
From 6ed0458744090ab307da9d9118690372b2e66ca8 Mon Sep 17 00:00:00 2001
|
|
|
4f4af9 |
From: Jaroslav Mracek <jmracek@redhat.com>
|
|
|
4f4af9 |
Date: Wed, 11 Nov 2020 12:47:21 +0100
|
|
|
4f4af9 |
Subject: [PATCH 1/5] Make module_base better industrialized for method reuse
|
|
|
4f4af9 |
|
|
|
4f4af9 |
It will allow to use internal for module switch command.
|
|
|
4f4af9 |
---
|
|
|
4f4af9 |
dnf/module/module_base.py | 29 ++++++++++++++++++++---------
|
|
|
4f4af9 |
1 file changed, 20 insertions(+), 9 deletions(-)
|
|
|
4f4af9 |
|
|
|
4f4af9 |
diff --git a/dnf/module/module_base.py b/dnf/module/module_base.py
|
|
|
4f4af9 |
index 49c871c4..0da4fab1 100644
|
|
|
4f4af9 |
--- a/dnf/module/module_base.py
|
|
|
4f4af9 |
+++ b/dnf/module/module_base.py
|
|
|
4f4af9 |
@@ -323,7 +323,7 @@ class ModuleBase(object):
|
|
|
4f4af9 |
assert len(streamDict) == 1
|
|
|
4f4af9 |
return moduleDict
|
|
|
4f4af9 |
|
|
|
4f4af9 |
- def _resolve_specs_enable_update_sack(self, module_specs):
|
|
|
4f4af9 |
+ def _resolve_specs_enable(self, module_specs):
|
|
|
4f4af9 |
no_match_specs = []
|
|
|
4f4af9 |
error_spec = []
|
|
|
4f4af9 |
module_dicts = {}
|
|
|
4f4af9 |
@@ -339,6 +339,9 @@ class ModuleBase(object):
|
|
|
4f4af9 |
error_spec.append(spec)
|
|
|
4f4af9 |
logger.error(ucd(e))
|
|
|
4f4af9 |
logger.error(_("Unable to resolve argument {}").format(spec))
|
|
|
4f4af9 |
+ return no_match_specs, error_spec, module_dicts
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ def _update_sack(self):
|
|
|
4f4af9 |
hot_fix_repos = [i.id for i in self.base.repos.iter_enabled() if i.module_hotfixes]
|
|
|
4f4af9 |
try:
|
|
|
4f4af9 |
solver_errors = self.base.sack.filter_modules(
|
|
|
4f4af9 |
@@ -347,6 +350,10 @@ class ModuleBase(object):
|
|
|
4f4af9 |
debugsolver=self.base.conf.debug_solver)
|
|
|
4f4af9 |
except hawkey.Exception as e:
|
|
|
4f4af9 |
raise dnf.exceptions.Error(ucd(e))
|
|
|
4f4af9 |
+ return solver_errors
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ def _enable_dependencies(self, module_dicts):
|
|
|
4f4af9 |
+ error_spec = []
|
|
|
4f4af9 |
for spec, (nsvcap, moduleDict) in module_dicts.items():
|
|
|
4f4af9 |
for streamDict in moduleDict.values():
|
|
|
4f4af9 |
for modules in streamDict.values():
|
|
|
4f4af9 |
@@ -357,6 +364,17 @@ class ModuleBase(object):
|
|
|
4f4af9 |
error_spec.append(spec)
|
|
|
4f4af9 |
logger.error(ucd(e))
|
|
|
4f4af9 |
logger.error(_("Unable to resolve argument {}").format(spec))
|
|
|
4f4af9 |
+ return error_spec
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ def _resolve_specs_enable_update_sack(self, module_specs):
|
|
|
4f4af9 |
+ no_match_specs, error_spec, module_dicts = self._resolve_specs_enable(module_specs)
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ solver_errors = self._update_sack()
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ dependency_error_spec = self._enable_dependencies(module_dicts)
|
|
|
4f4af9 |
+ if dependency_error_spec:
|
|
|
4f4af9 |
+ error_spec.extend(dependency_error_spec)
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
return no_match_specs, error_spec, solver_errors, module_dicts
|
|
|
4f4af9 |
|
|
|
4f4af9 |
def _modules_reset_or_disable(self, module_specs, to_state):
|
|
|
4f4af9 |
@@ -379,14 +397,7 @@ class ModuleBase(object):
|
|
|
4f4af9 |
if to_state == STATE_DISABLED:
|
|
|
4f4af9 |
self.base._moduleContainer.disable(name)
|
|
|
4f4af9 |
|
|
|
4f4af9 |
- hot_fix_repos = [i.id for i in self.base.repos.iter_enabled() if i.module_hotfixes]
|
|
|
4f4af9 |
- try:
|
|
|
4f4af9 |
- solver_errors = self.base.sack.filter_modules(
|
|
|
4f4af9 |
- self.base._moduleContainer, hot_fix_repos, self.base.conf.installroot,
|
|
|
4f4af9 |
- self.base.conf.module_platform_id, update_only=True,
|
|
|
4f4af9 |
- debugsolver=self.base.conf.debug_solver)
|
|
|
4f4af9 |
- except hawkey.Exception as e:
|
|
|
4f4af9 |
- raise dnf.exceptions.Error(ucd(e))
|
|
|
4f4af9 |
+ solver_errors = self._update_sack()
|
|
|
4f4af9 |
return no_match_specs, solver_errors
|
|
|
4f4af9 |
|
|
|
4f4af9 |
def _get_package_name_set_and_remove_profiles(self, module_list, nsvcap, remove=False):
|
|
|
4f4af9 |
--
|
|
|
4f4af9 |
2.26.2
|
|
|
4f4af9 |
|
|
|
4f4af9 |
|
|
|
4f4af9 |
From e6473f4e6f17bb635e023b8905f29b318b8795bf Mon Sep 17 00:00:00 2001
|
|
|
4f4af9 |
From: Jaroslav Mracek <jmracek@redhat.com>
|
|
|
4f4af9 |
Date: Wed, 11 Nov 2020 17:09:16 +0100
|
|
|
4f4af9 |
Subject: [PATCH 2/5] Add module switch-to support (RhBug:1792020)
|
|
|
4f4af9 |
|
|
|
4f4af9 |
It is a combination of module rpm distrosync, module profile switch and
|
|
|
4f4af9 |
module stream switch.
|
|
|
4f4af9 |
|
|
|
4f4af9 |
= changelog =
|
|
|
4f4af9 |
msg: Add new `module switch-to` command for switching content
|
|
|
4f4af9 |
of module streams
|
|
|
4f4af9 |
type: enhancement
|
|
|
4f4af9 |
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1792020
|
|
|
4f4af9 |
---
|
|
|
4f4af9 |
VERSION.cmake | 2 +-
|
|
|
4f4af9 |
dnf.spec | 2 +-
|
|
|
4f4af9 |
dnf/cli/commands/module.py | 24 ++++-
|
|
|
4f4af9 |
dnf/module/module_base.py | 182 ++++++++++++++++++++++++++++++++-----
|
|
|
4f4af9 |
4 files changed, 185 insertions(+), 25 deletions(-)
|
|
|
4f4af9 |
|
|
|
4f4af9 |
diff --git a/dnf/cli/commands/module.py b/dnf/cli/commands/module.py
|
|
|
4f4af9 |
index 5a6c0069..4cdc915e 100644
|
|
|
4f4af9 |
--- a/dnf/cli/commands/module.py
|
|
|
4f4af9 |
+++ b/dnf/cli/commands/module.py
|
|
|
4f4af9 |
@@ -271,6 +271,28 @@ class ModuleCommand(commands.Command):
|
|
|
4f4af9 |
|
|
|
4f4af9 |
logger.error(dnf.exceptions.MarkingErrors(no_match_group_specs=skipped_groups))
|
|
|
4f4af9 |
|
|
|
4f4af9 |
+ class SwitchToSubCommand(SubCommand):
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ aliases = ('switch-to',)
|
|
|
4f4af9 |
+ summary = _('switch a module to a stream and distrosync rpm packages')
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ def configure(self):
|
|
|
4f4af9 |
+ demands = self.cli.demands
|
|
|
4f4af9 |
+ demands.available_repos = True
|
|
|
4f4af9 |
+ demands.sack_activation = True
|
|
|
4f4af9 |
+ demands.resolving = True
|
|
|
4f4af9 |
+ demands.root_user = True
|
|
|
4f4af9 |
+ self.base.conf.module_stream_switch = True
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ def run_on_module(self):
|
|
|
4f4af9 |
+ try:
|
|
|
4f4af9 |
+ self.module_base.switch_to(self.opts.module_spec, strict=self.base.conf.strict)
|
|
|
4f4af9 |
+ except dnf.exceptions.MarkingErrors as e:
|
|
|
4f4af9 |
+ if self.base.conf.strict:
|
|
|
4f4af9 |
+ if e.no_match_group_specs or e.error_group_specs:
|
|
|
4f4af9 |
+ raise e
|
|
|
4f4af9 |
+ logger.error(str(e))
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
class ProvidesSubCommand(SubCommand):
|
|
|
4f4af9 |
|
|
|
4f4af9 |
aliases = ("provides", )
|
|
|
4f4af9 |
@@ -319,7 +341,7 @@ class ModuleCommand(commands.Command):
|
|
|
4f4af9 |
|
|
|
4f4af9 |
SUBCMDS = {ListSubCommand, InfoSubCommand, EnableSubCommand,
|
|
|
4f4af9 |
DisableSubCommand, ResetSubCommand, InstallSubCommand, UpdateSubCommand,
|
|
|
4f4af9 |
- RemoveSubCommand, ProvidesSubCommand, RepoquerySubCommand}
|
|
|
4f4af9 |
+ RemoveSubCommand, SwitchToSubCommand, ProvidesSubCommand, RepoquerySubCommand}
|
|
|
4f4af9 |
|
|
|
4f4af9 |
SUBCMDS_NOT_REQUIRED_ARG = {ListSubCommand}
|
|
|
4f4af9 |
|
|
|
4f4af9 |
diff --git a/dnf/module/module_base.py b/dnf/module/module_base.py
|
|
|
4f4af9 |
index 0da4fab1..03d54f72 100644
|
|
|
4f4af9 |
--- a/dnf/module/module_base.py
|
|
|
4f4af9 |
+++ b/dnf/module/module_base.py
|
|
|
4f4af9 |
@@ -140,31 +140,140 @@ class ModuleBase(object):
|
|
|
4f4af9 |
if fail_safe_repo_used:
|
|
|
4f4af9 |
raise dnf.exceptions.Error(_(
|
|
|
4f4af9 |
"Installing module from Fail-Safe repository is not allowed"))
|
|
|
4f4af9 |
- # Remove source packages they cannot be installed or upgraded
|
|
|
4f4af9 |
- base_no_source_query = self.base.sack.query().filterm(arch__neq=['src', 'nosrc']).apply()
|
|
|
4f4af9 |
- install_base_query = base_no_source_query.filter(nevra_strict=install_set_artefacts)
|
|
|
4f4af9 |
+ __, profiles_errors = self._install_profiles_internal(
|
|
|
4f4af9 |
+ install_set_artefacts, install_dict, strict)
|
|
|
4f4af9 |
+ if profiles_errors:
|
|
|
4f4af9 |
+ error_specs.extend(profiles_errors)
|
|
|
4f4af9 |
|
|
|
4f4af9 |
- # add hot-fix packages
|
|
|
4f4af9 |
- hot_fix_repos = [i.id for i in self.base.repos.iter_enabled() if i.module_hotfixes]
|
|
|
4f4af9 |
- hotfix_packages = base_no_source_query.filter(
|
|
|
4f4af9 |
- reponame=hot_fix_repos, name=install_dict.keys())
|
|
|
4f4af9 |
- install_base_query = install_base_query.union(hotfix_packages)
|
|
|
4f4af9 |
+ if no_match_specs or error_specs or solver_errors:
|
|
|
4f4af9 |
+ raise dnf.exceptions.MarkingErrors(no_match_group_specs=no_match_specs,
|
|
|
4f4af9 |
+ error_group_specs=error_specs,
|
|
|
4f4af9 |
+ module_depsolv_errors=solver_errors)
|
|
|
4f4af9 |
|
|
|
4f4af9 |
- for pkg_name, set_specs in install_dict.items():
|
|
|
4f4af9 |
- query = install_base_query.filter(name=pkg_name)
|
|
|
4f4af9 |
- if not query:
|
|
|
4f4af9 |
- # package can also be non-modular or part of another stream
|
|
|
4f4af9 |
- query = base_no_source_query.filter(name=pkg_name)
|
|
|
4f4af9 |
- if not query:
|
|
|
4f4af9 |
- for spec in set_specs:
|
|
|
4f4af9 |
- logger.error(_("Unable to resolve argument {}").format(spec))
|
|
|
4f4af9 |
- logger.error(_("No match for package {}").format(pkg_name))
|
|
|
4f4af9 |
- error_specs.extend(set_specs)
|
|
|
4f4af9 |
- continue
|
|
|
4f4af9 |
- self.base._goal.group_members.add(pkg_name)
|
|
|
4f4af9 |
+ def switch_to(self, module_specs, strict=True):
|
|
|
4f4af9 |
+ # :api
|
|
|
4f4af9 |
+ no_match_specs, error_specs, module_dicts = self._resolve_specs_enable(module_specs)
|
|
|
4f4af9 |
+ # collect name of artifacts from new modules for distrosync
|
|
|
4f4af9 |
+ new_artifacts_names = set()
|
|
|
4f4af9 |
+ # collect name of artifacts from active modules for distrosync before sack update
|
|
|
4f4af9 |
+ active_artifacts_names = set()
|
|
|
4f4af9 |
+ src_arches = {"nosrc", "src"}
|
|
|
4f4af9 |
+ for spec, (nsvcap, moduledict) in module_dicts.items():
|
|
|
4f4af9 |
+ for name in moduledict.keys():
|
|
|
4f4af9 |
+ for module in self.base._moduleContainer.query(name, "", "", "", ""):
|
|
|
4f4af9 |
+ if self.base._moduleContainer.isModuleActive(module):
|
|
|
4f4af9 |
+ for artifact in module.getArtifacts():
|
|
|
4f4af9 |
+ arch = artifact.rsplit(".", 1)[1]
|
|
|
4f4af9 |
+ if arch in src_arches:
|
|
|
4f4af9 |
+ continue
|
|
|
4f4af9 |
+ pkg_name = artifact.rsplit("-", 2)[0]
|
|
|
4f4af9 |
+ active_artifacts_names.add(pkg_name)
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ solver_errors = self._update_sack()
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ dependency_error_spec = self._enable_dependencies(module_dicts)
|
|
|
4f4af9 |
+ if dependency_error_spec:
|
|
|
4f4af9 |
+ error_specs.extend(dependency_error_spec)
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ # <package_name, set_of_spec>
|
|
|
4f4af9 |
+ fail_safe_repo = hawkey.MODULE_FAIL_SAFE_REPO_NAME
|
|
|
4f4af9 |
+ install_dict = {}
|
|
|
4f4af9 |
+ install_set_artifacts = set()
|
|
|
4f4af9 |
+ fail_safe_repo_used = False
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ # list of name: [profiles] for module profiles being removed
|
|
|
4f4af9 |
+ removed_profiles = self.base._moduleContainer.getRemovedProfiles()
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ for spec, (nsvcap, moduledict) in module_dicts.items():
|
|
|
4f4af9 |
+ for name, streamdict in moduledict.items():
|
|
|
4f4af9 |
+ for stream, module_list in streamdict.items():
|
|
|
4f4af9 |
+ install_module_list = [x for x in module_list
|
|
|
4f4af9 |
+ if self.base._moduleContainer.isModuleActive(x.getId())]
|
|
|
4f4af9 |
+ if not install_module_list:
|
|
|
4f4af9 |
+ "No active matches for argument '{0}' in module '{1}:{2}'"
|
|
|
4f4af9 |
+ logger.error(_("No active matches for argument '{0}' in module "
|
|
|
4f4af9 |
+ "'{1}:{2}'").format(spec, name, stream))
|
|
|
4f4af9 |
+ error_specs.append(spec)
|
|
|
4f4af9 |
+ continue
|
|
|
4f4af9 |
+ profiles = []
|
|
|
4f4af9 |
+ latest_module = self._get_latest(install_module_list)
|
|
|
4f4af9 |
+ if latest_module.getRepoID() == fail_safe_repo:
|
|
|
4f4af9 |
+ msg = _(
|
|
|
4f4af9 |
+ "Installing module '{0}' from Fail-Safe repository {1} is not allowed")
|
|
|
4f4af9 |
+ logger.critical(msg.format(latest_module.getNameStream(), fail_safe_repo))
|
|
|
4f4af9 |
+ fail_safe_repo_used = True
|
|
|
4f4af9 |
+ if nsvcap.profile:
|
|
|
4f4af9 |
+ profiles.extend(latest_module.getProfiles(nsvcap.profile))
|
|
|
4f4af9 |
+ if not profiles:
|
|
|
4f4af9 |
+ available_profiles = latest_module.getProfiles()
|
|
|
4f4af9 |
+ if available_profiles:
|
|
|
4f4af9 |
+ profile_names = ", ".join(sorted(
|
|
|
4f4af9 |
+ [profile.getName() for profile in available_profiles]))
|
|
|
4f4af9 |
+ msg = _("Unable to match profile for argument {}. Available "
|
|
|
4f4af9 |
+ "profiles for '{}:{}': {}").format(
|
|
|
4f4af9 |
+ spec, name, stream, profile_names)
|
|
|
4f4af9 |
+ else:
|
|
|
4f4af9 |
+ msg = _("Unable to match profile for argument {}").format(spec)
|
|
|
4f4af9 |
+ logger.error(msg)
|
|
|
4f4af9 |
+ no_match_specs.append(spec)
|
|
|
4f4af9 |
+ continue
|
|
|
4f4af9 |
+ elif name in removed_profiles:
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ for profile in removed_profiles[name]:
|
|
|
4f4af9 |
+ module_profiles = latest_module.getProfiles(profile)
|
|
|
4f4af9 |
+ if not module_profiles:
|
|
|
4f4af9 |
+ logger.warning(
|
|
|
4f4af9 |
+ _("Installed profile '{0}' is not available in module "
|
|
|
4f4af9 |
+ "'{1}' stream '{2}'").format(profile, name, stream))
|
|
|
4f4af9 |
+ continue
|
|
|
4f4af9 |
+ profiles.extend(module_profiles)
|
|
|
4f4af9 |
+ for profile in profiles:
|
|
|
4f4af9 |
+ self.base._moduleContainer.install(latest_module, profile.getName())
|
|
|
4f4af9 |
+ for pkg_name in profile.getContent():
|
|
|
4f4af9 |
+ install_dict.setdefault(pkg_name, set()).add(spec)
|
|
|
4f4af9 |
+ for module in install_module_list:
|
|
|
4f4af9 |
+ artifacts = module.getArtifacts()
|
|
|
4f4af9 |
+ install_set_artifacts.update(artifacts)
|
|
|
4f4af9 |
+ for artifact in artifacts:
|
|
|
4f4af9 |
+ arch = artifact.rsplit(".", 1)[1]
|
|
|
4f4af9 |
+ if arch in src_arches:
|
|
|
4f4af9 |
+ continue
|
|
|
4f4af9 |
+ pkg_name = artifact.rsplit("-", 2)[0]
|
|
|
4f4af9 |
+ new_artifacts_names.add(pkg_name)
|
|
|
4f4af9 |
+ if fail_safe_repo_used:
|
|
|
4f4af9 |
+ raise dnf.exceptions.Error(_(
|
|
|
4f4af9 |
+ "Installing module from Fail-Safe repository is not allowed"))
|
|
|
4f4af9 |
+ install_base_query, profiles_errors = self._install_profiles_internal(
|
|
|
4f4af9 |
+ install_set_artifacts, install_dict, strict)
|
|
|
4f4af9 |
+ if profiles_errors:
|
|
|
4f4af9 |
+ error_specs.extend(profiles_errors)
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ # distrosync module name
|
|
|
4f4af9 |
+ all_names = set()
|
|
|
4f4af9 |
+ all_names.update(new_artifacts_names)
|
|
|
4f4af9 |
+ all_names.update(active_artifacts_names)
|
|
|
4f4af9 |
+ remove_query = self.base.sack.query().filterm(empty=True)
|
|
|
4f4af9 |
+ for pkg_name in all_names:
|
|
|
4f4af9 |
+ query = self.base.sack.query().filterm(name=pkg_name)
|
|
|
4f4af9 |
+ installed = query.installed()
|
|
|
4f4af9 |
+ if not installed:
|
|
|
4f4af9 |
+ continue
|
|
|
4f4af9 |
+ available = query.available()
|
|
|
4f4af9 |
+ if not available:
|
|
|
4f4af9 |
+ logger.warning(_("No packages available to distrosync for package name "
|
|
|
4f4af9 |
+ "'{}'").format(pkg_name))
|
|
|
4f4af9 |
+ if pkg_name not in new_artifacts_names:
|
|
|
4f4af9 |
+ remove_query = remove_query.union(query)
|
|
|
4f4af9 |
+ continue
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ only_new_module = query.intersection(install_base_query)
|
|
|
4f4af9 |
+ if only_new_module:
|
|
|
4f4af9 |
+ query = only_new_module
|
|
|
4f4af9 |
sltr = dnf.selector.Selector(self.base.sack)
|
|
|
4f4af9 |
sltr.set(pkg=query)
|
|
|
4f4af9 |
- self.base._goal.install(select=sltr, optional=(not strict))
|
|
|
4f4af9 |
+ self.base._goal.distupgrade(select=sltr)
|
|
|
4f4af9 |
+ self.base._remove_if_unneeded(remove_query)
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
if no_match_specs or error_specs or solver_errors:
|
|
|
4f4af9 |
raise dnf.exceptions.MarkingErrors(no_match_group_specs=no_match_specs,
|
|
|
4f4af9 |
error_group_specs=error_specs,
|
|
|
4f4af9 |
@@ -183,7 +292,7 @@ class ModuleBase(object):
|
|
|
4f4af9 |
fail_safe_repo = hawkey.MODULE_FAIL_SAFE_REPO_NAME
|
|
|
4f4af9 |
fail_safe_repo_used = False
|
|
|
4f4af9 |
|
|
|
4f4af9 |
- # Remove source packages they cannot be installed or upgraded
|
|
|
4f4af9 |
+ # Remove source packages because they cannot be installed or upgraded
|
|
|
4f4af9 |
base_no_source_query = self.base.sack.query().filterm(arch__neq=['src', 'nosrc']).apply()
|
|
|
4f4af9 |
|
|
|
4f4af9 |
for spec in module_specs:
|
|
|
4f4af9 |
@@ -694,6 +803,35 @@ class ModuleBase(object):
|
|
|
4f4af9 |
def _format_repoid(self, repo_name):
|
|
|
4f4af9 |
return "{}\n".format(self.base.output.term.bold(repo_name))
|
|
|
4f4af9 |
|
|
|
4f4af9 |
+ def _install_profiles_internal(self, install_set_artifacts, install_dict, strict):
|
|
|
4f4af9 |
+ # Remove source packages because they cannot be installed or upgraded
|
|
|
4f4af9 |
+ base_no_source_query = self.base.sack.query().filterm(arch__neq=['src', 'nosrc']).apply()
|
|
|
4f4af9 |
+ install_base_query = base_no_source_query.filter(nevra_strict=install_set_artifacts)
|
|
|
4f4af9 |
+ error_specs = []
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ # add hot-fix packages
|
|
|
4f4af9 |
+ hot_fix_repos = [i.id for i in self.base.repos.iter_enabled() if i.module_hotfixes]
|
|
|
4f4af9 |
+ hotfix_packages = base_no_source_query.filter(
|
|
|
4f4af9 |
+ reponame=hot_fix_repos, name=install_dict.keys())
|
|
|
4f4af9 |
+ install_base_query = install_base_query.union(hotfix_packages)
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ for pkg_name, set_specs in install_dict.items():
|
|
|
4f4af9 |
+ query = install_base_query.filter(name=pkg_name)
|
|
|
4f4af9 |
+ if not query:
|
|
|
4f4af9 |
+ # package can also be non-modular or part of another stream
|
|
|
4f4af9 |
+ query = base_no_source_query.filter(name=pkg_name)
|
|
|
4f4af9 |
+ if not query:
|
|
|
4f4af9 |
+ for spec in set_specs:
|
|
|
4f4af9 |
+ logger.error(_("Unable to resolve argument {}").format(spec))
|
|
|
4f4af9 |
+ logger.error(_("No match for package {}").format(pkg_name))
|
|
|
4f4af9 |
+ error_specs.extend(set_specs)
|
|
|
4f4af9 |
+ continue
|
|
|
4f4af9 |
+ self.base._goal.group_members.add(pkg_name)
|
|
|
4f4af9 |
+ sltr = dnf.selector.Selector(self.base.sack)
|
|
|
4f4af9 |
+ sltr.set(pkg=query)
|
|
|
4f4af9 |
+ self.base._goal.install(select=sltr, optional=(not strict))
|
|
|
4f4af9 |
+ return install_base_query, error_specs
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
|
|
|
4f4af9 |
def format_modular_solver_errors(errors):
|
|
|
4f4af9 |
msg = dnf.util._format_resolve_problems(errors)
|
|
|
4f4af9 |
--
|
|
|
4f4af9 |
2.26.2
|
|
|
4f4af9 |
|
|
|
4f4af9 |
|
|
|
4f4af9 |
From df8c74679193bf27db584b3ad225997b2f5f4b87 Mon Sep 17 00:00:00 2001
|
|
|
4f4af9 |
From: Jaroslav Mracek <jmracek@redhat.com>
|
|
|
4f4af9 |
Date: Thu, 12 Nov 2020 13:51:02 +0100
|
|
|
4f4af9 |
Subject: [PATCH 3/5] [minor] Rename all variables with artefact to artifact
|
|
|
4f4af9 |
|
|
|
4f4af9 |
---
|
|
|
4f4af9 |
dnf/module/module_base.py | 10 +++++-----
|
|
|
4f4af9 |
1 file changed, 5 insertions(+), 5 deletions(-)
|
|
|
4f4af9 |
|
|
|
4f4af9 |
diff --git a/dnf/module/module_base.py b/dnf/module/module_base.py
|
|
|
4f4af9 |
index 03d54f72..7298c9a3 100644
|
|
|
4f4af9 |
--- a/dnf/module/module_base.py
|
|
|
4f4af9 |
+++ b/dnf/module/module_base.py
|
|
|
4f4af9 |
@@ -73,7 +73,7 @@ class ModuleBase(object):
|
|
|
4f4af9 |
# <package_name, set_of_spec>
|
|
|
4f4af9 |
fail_safe_repo = hawkey.MODULE_FAIL_SAFE_REPO_NAME
|
|
|
4f4af9 |
install_dict = {}
|
|
|
4f4af9 |
- install_set_artefacts = set()
|
|
|
4f4af9 |
+ install_set_artifacts = set()
|
|
|
4f4af9 |
fail_safe_repo_used = False
|
|
|
4f4af9 |
for spec, (nsvcap, moduledict) in module_dicts.items():
|
|
|
4f4af9 |
for name, streamdict in moduledict.items():
|
|
|
4f4af9 |
@@ -136,12 +136,12 @@ class ModuleBase(object):
|
|
|
4f4af9 |
for pkg_name in profile.getContent():
|
|
|
4f4af9 |
install_dict.setdefault(pkg_name, set()).add(spec)
|
|
|
4f4af9 |
for module in install_module_list:
|
|
|
4f4af9 |
- install_set_artefacts.update(module.getArtifacts())
|
|
|
4f4af9 |
+ install_set_artifacts.update(module.getArtifacts())
|
|
|
4f4af9 |
if fail_safe_repo_used:
|
|
|
4f4af9 |
raise dnf.exceptions.Error(_(
|
|
|
4f4af9 |
"Installing module from Fail-Safe repository is not allowed"))
|
|
|
4f4af9 |
__, profiles_errors = self._install_profiles_internal(
|
|
|
4f4af9 |
- install_set_artefacts, install_dict, strict)
|
|
|
4f4af9 |
+ install_set_artifacts, install_dict, strict)
|
|
|
4f4af9 |
if profiles_errors:
|
|
|
4f4af9 |
error_specs.extend(profiles_errors)
|
|
|
4f4af9 |
|
|
|
4f4af9 |
@@ -326,8 +326,8 @@ class ModuleBase(object):
|
|
|
4f4af9 |
else:
|
|
|
4f4af9 |
for profile in latest_module.getProfiles():
|
|
|
4f4af9 |
upgrade_package_set.update(profile.getContent())
|
|
|
4f4af9 |
- for artefact in latest_module.getArtifacts():
|
|
|
4f4af9 |
- subj = hawkey.Subject(artefact)
|
|
|
4f4af9 |
+ for artifact in latest_module.getArtifacts():
|
|
|
4f4af9 |
+ subj = hawkey.Subject(artifact)
|
|
|
4f4af9 |
for nevra_obj in subj.get_nevra_possibilities(
|
|
|
4f4af9 |
forms=[hawkey.FORM_NEVRA]):
|
|
|
4f4af9 |
upgrade_package_set.add(nevra_obj.name)
|
|
|
4f4af9 |
--
|
|
|
4f4af9 |
2.26.2
|
|
|
4f4af9 |
|
|
|
4f4af9 |
|
|
|
4f4af9 |
From 0818bb80fc0846f602f338a2119671be97c47217 Mon Sep 17 00:00:00 2001
|
|
|
4f4af9 |
From: Jaroslav Mracek <jmracek@redhat.com>
|
|
|
4f4af9 |
Date: Thu, 12 Nov 2020 15:11:29 +0100
|
|
|
4f4af9 |
Subject: [PATCH 4/5] [doc] Add description of dnf module switch-to
|
|
|
4f4af9 |
|
|
|
4f4af9 |
---
|
|
|
4f4af9 |
doc/command_ref.rst | 30 ++++++++++++++++++++++--------
|
|
|
4f4af9 |
1 file changed, 22 insertions(+), 8 deletions(-)
|
|
|
4f4af9 |
|
|
|
4f4af9 |
diff --git a/doc/command_ref.rst b/doc/command_ref.rst
|
|
|
4f4af9 |
index 83879013..c12837ea 100644
|
|
|
4f4af9 |
--- a/doc/command_ref.rst
|
|
|
4f4af9 |
+++ b/doc/command_ref.rst
|
|
|
4f4af9 |
@@ -979,15 +979,31 @@ Module subcommands take :ref:`\<module-spec>\ <specifying_modules-label>`... arg
|
|
|
4f4af9 |
In case no profile was provided, all default profiles get installed.
|
|
|
4f4af9 |
Module streams get enabled accordingly.
|
|
|
4f4af9 |
|
|
|
4f4af9 |
- This command cannot be used for switching module streams. It is recommended to remove all
|
|
|
4f4af9 |
- installed content from the module and reset the module using the
|
|
|
4f4af9 |
- :ref:`reset <module_reset_command-label>` command. After you reset the module, you can install
|
|
|
4f4af9 |
- the other stream.
|
|
|
4f4af9 |
+ This command cannot be used for switching module streams. Use the
|
|
|
4f4af9 |
+ :ref:`dnf module switch-to <module_switch_to_command-label>` command for that.
|
|
|
4f4af9 |
|
|
|
4f4af9 |
``dnf [options] module update <module-spec>...``
|
|
|
4f4af9 |
Update packages associated with an active module stream, optionally restricted to a profile.
|
|
|
4f4af9 |
If the `profile_name` is provided, only the packages referenced by that profile will be updated.
|
|
|
4f4af9 |
|
|
|
4f4af9 |
+.. _module_switch_to_command-label:
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+``dnf [options] module switch-to <module-spec>...``
|
|
|
4f4af9 |
+ Switch to or enable a module stream, change versions of installed packages to versions provided
|
|
|
4f4af9 |
+ by the new stream, and remove packages from the old stream that are no longer available. It also
|
|
|
4f4af9 |
+ updates installed profiles if they are available for the new stream. When a profile was
|
|
|
4f4af9 |
+ provided, it installs that profile and does not update any already installed profiles.
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ This command can be used as a stronger version of the
|
|
|
4f4af9 |
+ :ref:`dnf module enable <module_enable_command-label>` command, which not only enables modules,
|
|
|
4f4af9 |
+ but also does a `distrosync` to all modular packages in the enabled modules.
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
+ It can also be used as a stronger version of the
|
|
|
4f4af9 |
+ :ref:`dnf module install <module_install_command-label>` command, but it requires to specify
|
|
|
4f4af9 |
+ profiles that are supposed to be installed, because `switch-to` command does not use `default
|
|
|
4f4af9 |
+ profiles`. The `switch-to` command doesn't only install profiles, it also makes a `distrosync`
|
|
|
4f4af9 |
+ to all modular packages in the installed module.
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
``dnf [options] module remove <module-spec>...``
|
|
|
4f4af9 |
Remove installed module profiles, including packages that were installed with the
|
|
|
4f4af9 |
:ref:`dnf module install <module_install_command-label>` command. Will not remove packages
|
|
|
4f4af9 |
@@ -1010,10 +1026,8 @@ Module subcommands take :ref:`\<module-spec>\ <specifying_modules-label>`... arg
|
|
|
4f4af9 |
of modular dependency issue the operation will be rejected. To perform the action anyway please use
|
|
|
4f4af9 |
\-\ :ref:`-skip-broken <skip-broken_option-label>` option.
|
|
|
4f4af9 |
|
|
|
4f4af9 |
- This command cannot be used for switching module streams. It is recommended to remove all
|
|
|
4f4af9 |
- installed content from the module, and reset the module using the
|
|
|
4f4af9 |
- :ref:`reset <module_reset_command-label>` command. After you reset the module, you can enable
|
|
|
4f4af9 |
- the other stream.
|
|
|
4f4af9 |
+ This command cannot be used for switching module streams. Use the
|
|
|
4f4af9 |
+ :ref:`dnf module switch-to <module_switch_to_command-label>` command for that.
|
|
|
4f4af9 |
|
|
|
4f4af9 |
.. _module_disable_command-label:
|
|
|
4f4af9 |
|
|
|
4f4af9 |
--
|
|
|
4f4af9 |
2.26.2
|
|
|
4f4af9 |
|
|
|
4f4af9 |
|
|
|
4f4af9 |
From 6b0b2b99e40c20706145e774626658825f5bc55d Mon Sep 17 00:00:00 2001
|
|
|
4f4af9 |
From: Jaroslav Mracek <jmracek@redhat.com>
|
|
|
4f4af9 |
Date: Wed, 25 Nov 2020 12:34:30 +0100
|
|
|
4f4af9 |
Subject: [PATCH 5/5] Do not use source rpms for module switch
|
|
|
4f4af9 |
|
|
|
4f4af9 |
It prevents misleading message from libsolv that it tries to install
|
|
|
4f4af9 |
source rpm.
|
|
|
4f4af9 |
---
|
|
|
4f4af9 |
dnf/module/module_base.py | 4 +++-
|
|
|
4f4af9 |
1 file changed, 3 insertions(+), 1 deletion(-)
|
|
|
4f4af9 |
|
|
|
4f4af9 |
diff --git a/dnf/module/module_base.py b/dnf/module/module_base.py
|
|
|
4f4af9 |
index 7298c9a3..02d5d5a3 100644
|
|
|
4f4af9 |
--- a/dnf/module/module_base.py
|
|
|
4f4af9 |
+++ b/dnf/module/module_base.py
|
|
|
4f4af9 |
@@ -253,8 +253,10 @@ class ModuleBase(object):
|
|
|
4f4af9 |
all_names.update(new_artifacts_names)
|
|
|
4f4af9 |
all_names.update(active_artifacts_names)
|
|
|
4f4af9 |
remove_query = self.base.sack.query().filterm(empty=True)
|
|
|
4f4af9 |
+ base_no_source_query = self.base.sack.query().filterm(arch__neq=['src', 'nosrc']).apply()
|
|
|
4f4af9 |
+
|
|
|
4f4af9 |
for pkg_name in all_names:
|
|
|
4f4af9 |
- query = self.base.sack.query().filterm(name=pkg_name)
|
|
|
4f4af9 |
+ query = base_no_source_query.filter(name=pkg_name)
|
|
|
4f4af9 |
installed = query.installed()
|
|
|
4f4af9 |
if not installed:
|
|
|
4f4af9 |
continue
|
|
|
4f4af9 |
--
|
|
|
4f4af9 |
2.26.2
|
|
|
4f4af9 |
|