Added patch for almalinux bugtracker
This commit is contained in:
commit
e458ecf927
@ -0,0 +1,79 @@
|
||||
From 0592ff47bc1b9029eb9b25d59410062038fdacd3 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Mracek <jmracek@redhat.com>
|
||||
Date: Thu, 15 Feb 2024 11:28:59 +0100
|
||||
Subject: [PATCH] Add all candidates for reinstall to solver
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: 96f8d79c37e119ff56f730797865121b63241a6b
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-25005
|
||||
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
dnf/base.py | 9 ++++++---
|
||||
dnf/query.py | 5 ++++-
|
||||
tests/test_queries.py | 7 ++++++-
|
||||
3 files changed, 16 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/dnf/base.py b/dnf/base.py
|
||||
index 50869ec4..adb5ad6f 100644
|
||||
--- a/dnf/base.py
|
||||
+++ b/dnf/base.py
|
||||
@@ -2333,19 +2333,22 @@ class Base(object):
|
||||
|
||||
if not installed_pkgs:
|
||||
raise dnf.exceptions.PackagesNotInstalledError(
|
||||
- 'no package matched', pkg_spec, available_nevra2pkg.values())
|
||||
+ 'no package matched', pkg_spec, available_q.run())
|
||||
|
||||
cnt = 0
|
||||
clean_deps = self.conf.clean_requirements_on_remove
|
||||
+ strict = self.conf.strict
|
||||
for installed_pkg in installed_pkgs:
|
||||
try:
|
||||
- available_pkg = available_nevra2pkg[ucd(installed_pkg)]
|
||||
+ available_pkgs = available_nevra2pkg[ucd(installed_pkg)]
|
||||
except KeyError:
|
||||
if not remove_na:
|
||||
continue
|
||||
self._goal.erase(installed_pkg, clean_deps=clean_deps)
|
||||
else:
|
||||
- self._goal.install(available_pkg)
|
||||
+ sltr = dnf.selector.Selector(self.sack)
|
||||
+ sltr.set(pkg=available_pkgs)
|
||||
+ self._goal.install(select=sltr, optional=(not strict))
|
||||
cnt += 1
|
||||
|
||||
if cnt == 0:
|
||||
diff --git a/dnf/query.py b/dnf/query.py
|
||||
index ab4139bf..02e631a6 100644
|
||||
--- a/dnf/query.py
|
||||
+++ b/dnf/query.py
|
||||
@@ -43,4 +43,7 @@ def _by_provides(sack, patterns, ignore_case=False, get_query=False):
|
||||
return q.run()
|
||||
|
||||
def _per_nevra_dict(pkg_list):
|
||||
- return {ucd(pkg):pkg for pkg in pkg_list}
|
||||
+ nevra_dic = {}
|
||||
+ for pkg in pkg_list:
|
||||
+ nevra_dic.setdefault(ucd(pkg), []).append(pkg)
|
||||
+ return nevra_dic
|
||||
diff --git a/tests/test_queries.py b/tests/test_queries.py
|
||||
index cdcb7ca4..e0253008 100644
|
||||
--- a/tests/test_queries.py
|
||||
+++ b/tests/test_queries.py
|
||||
@@ -128,4 +128,9 @@ class DictsTest(tests.support.TestCase):
|
||||
dct = dnf.query._per_nevra_dict(pkgs)
|
||||
self.assertCountEqual(dct.keys(),
|
||||
["lotus-3-16.x86_64", "lotus-3-16.i686"])
|
||||
- self.assertCountEqual(dct.values(), pkgs)
|
||||
+ test_list = []
|
||||
+ for list_items in dct.values():
|
||||
+ for item in list_items:
|
||||
+ test_list.append(item)
|
||||
+
|
||||
+ self.assertCountEqual(test_list, pkgs)
|
||||
--
|
||||
2.44.0
|
||||
|
||||
41
SOURCES/0016-Fix-handling-installonly-packages-reasons.patch
Normal file
41
SOURCES/0016-Fix-handling-installonly-packages-reasons.patch
Normal file
@ -0,0 +1,41 @@
|
||||
From 657197afd95f387d0c60a288b7cdcbfa914f9cd2 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Mracek <jmracek@redhat.com>
|
||||
Date: Mon, 11 Mar 2024 12:36:48 +0100
|
||||
Subject: [PATCH 1/4] Fix handling installonly packages reasons
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: a4d815e4df87f5afbae9d37c7faf6a9871d50b53
|
||||
|
||||
The original code took the first item from all remaining packages.
|
||||
It means a random reason and use it to keep installonly package reason.
|
||||
|
||||
Related: https://issues.redhat.com/browse/RHEL-15902
|
||||
Closes: https://github.com/rpm-software-management/dnf/issues/2061
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
dnf/base.py | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dnf/base.py b/dnf/base.py
|
||||
index adb5ad6f..b8237183 100644
|
||||
--- a/dnf/base.py
|
||||
+++ b/dnf/base.py
|
||||
@@ -815,9 +815,11 @@ class Base(object):
|
||||
if erasures:
|
||||
remaining_installed_query = self.sack.query(flags=hawkey.IGNORE_EXCLUDES).installed()
|
||||
remaining_installed_query.filterm(pkg__neq=erasures)
|
||||
+ remaining_installed_query.apply()
|
||||
for pkg in erasures:
|
||||
- if remaining_installed_query.filter(name=pkg.name):
|
||||
- remaining = remaining_installed_query[0]
|
||||
+ tmp_remaining_installed_query = remaining_installed_query.filter(name=pkg.name, arch=pkg.arch)
|
||||
+ if tmp_remaining_installed_query:
|
||||
+ remaining = tmp_remaining_installed_query[0]
|
||||
ts.get_reason(remaining)
|
||||
self.history.set_reason(remaining, ts.get_reason(remaining))
|
||||
self._ds_callback.pkg_added(pkg, 'e')
|
||||
--
|
||||
2.45.0
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
From 64ca173adf414354c158e429ffec23e4560bb65f Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Mracek <jmracek@redhat.com>
|
||||
Date: Fri, 8 Mar 2024 12:51:26 +0100
|
||||
Subject: [PATCH 2/4] Remove confusing sentence from documentation
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: 824a95e1786b460102d9bf4a2cec0ce7973f882e
|
||||
|
||||
Installonly packages are handled by autoremove command in a similar
|
||||
way like other package.
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-15902
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
doc/command_ref.rst | 3 ---
|
||||
1 file changed, 3 deletions(-)
|
||||
|
||||
diff --git a/doc/command_ref.rst b/doc/command_ref.rst
|
||||
index 0e6cea01..b92a1f10 100644
|
||||
--- a/doc/command_ref.rst
|
||||
+++ b/doc/command_ref.rst
|
||||
@@ -501,9 +501,6 @@ Autoremove Command
|
||||
|
||||
Removes all "leaf" packages from the system that were originally installed as dependencies of user-installed packages, but which are no longer required by any such package.
|
||||
|
||||
-Packages listed in :ref:`installonlypkgs <installonlypkgs-label>` are never automatically removed by
|
||||
-this command.
|
||||
-
|
||||
``dnf [options] autoremove <spec>...``
|
||||
|
||||
This is an alias for the :ref:`\remove_command-label` command with clean_requirements_on_remove set to
|
||||
--
|
||||
2.45.0
|
||||
|
||||
36
SOURCES/0018-Remove-leaf-word-from-documentation.patch
Normal file
36
SOURCES/0018-Remove-leaf-word-from-documentation.patch
Normal file
@ -0,0 +1,36 @@
|
||||
From 2ea32ace13f6a30f86e03b690f284c0ec0992a19 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Mracek <jmracek@redhat.com>
|
||||
Date: Fri, 8 Mar 2024 12:56:57 +0100
|
||||
Subject: [PATCH 3/4] Remove "leaf" word from documentation
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: a6d4cd745ce27c09d6cdb4302177b2bfed600549
|
||||
|
||||
Leaf packages term is not define in documentation and it even
|
||||
represent different set of packages that are showed by leaves command.
|
||||
|
||||
Related: https://issues.redhat.com/browse/RHELDOCS-17711
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-15902
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
doc/command_ref.rst | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/doc/command_ref.rst b/doc/command_ref.rst
|
||||
index b92a1f10..8991df2f 100644
|
||||
--- a/doc/command_ref.rst
|
||||
+++ b/doc/command_ref.rst
|
||||
@@ -499,7 +499,7 @@ Autoremove Command
|
||||
|
||||
``dnf [options] autoremove``
|
||||
|
||||
- Removes all "leaf" packages from the system that were originally installed as dependencies of user-installed packages, but which are no longer required by any such package.
|
||||
+ Removes all packages from the system that were originally installed as dependencies of user-installed packages, but which are no longer required by any such package.
|
||||
|
||||
``dnf [options] autoremove <spec>...``
|
||||
|
||||
--
|
||||
2.45.0
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
From c09865aa3af8248c69b7aa064fe6e96f68e03de1 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Mracek <jmracek@redhat.com>
|
||||
Date: Fri, 8 Mar 2024 14:06:26 +0100
|
||||
Subject: [PATCH 4/4] Update documentation of history userinstalled command
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: 929d9133971b53eabfd65d989ded0de8f72f95ea
|
||||
|
||||
The described behavior differs from current behavior therefore
|
||||
it might create a confusion.
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-15902
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
doc/command_ref.rst | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/doc/command_ref.rst b/doc/command_ref.rst
|
||||
index 8991df2f..ffb84407 100644
|
||||
--- a/doc/command_ref.rst
|
||||
+++ b/doc/command_ref.rst
|
||||
@@ -795,8 +795,8 @@ transactions and act according to this information (assuming the
|
||||
the current state of RPMDB, it will not undo the transaction.
|
||||
|
||||
``dnf history userinstalled``
|
||||
- Show all installonly packages, packages installed outside of DNF and packages not
|
||||
- installed as dependency. I.e. it lists packages that will stay on the system when
|
||||
+ Show all packages installed by user, installed from a group or a module profile, and packages
|
||||
+ installed outside of DNF. I.e. it lists packages that will stay on the system when
|
||||
:ref:`\autoremove_command-label` or :ref:`\remove_command-label` along with
|
||||
`clean_requirements_on_remove` configuration option set to True is executed. Note the same
|
||||
results can be accomplished with ``dnf repoquery --userinstalled``, and the repoquery
|
||||
--
|
||||
2.45.0
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
From 5388d980c8137c3ee6924f145bd284169d838fad Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Tue, 30 Jan 2024 21:36:46 +0000
|
||||
Subject: [PATCH] automatic: Use add_security_filters, not
|
||||
_update_security_filters
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: 0b4b8cc8940a4073b33f1bb772651ae27e55f299
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-21874
|
||||
|
||||
It seems that these two approaches for selecting security updates
|
||||
sometimes disagree. The regular `dnf update` command uses
|
||||
base.add_security_filters to select security updates, so dnf-automatic
|
||||
should do the same.
|
||||
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
dnf/automatic/main.py | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dnf/automatic/main.py b/dnf/automatic/main.py
|
||||
index f6f4049b..caef627f 100644
|
||||
--- a/dnf/automatic/main.py
|
||||
+++ b/dnf/automatic/main.py
|
||||
@@ -375,8 +375,7 @@ def main(args):
|
||||
|
||||
def upgrade(base, upgrade_type):
|
||||
if upgrade_type == 'security':
|
||||
- base._update_security_filters.append(base.sack.query().upgrades().filterm(
|
||||
- advisory_type='security'))
|
||||
+ base.add_security_filters("gte", ("security",))
|
||||
base.upgrade_all()
|
||||
elif upgrade_type == 'default':
|
||||
base.upgrade_all()
|
||||
--
|
||||
2.45.0
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
From c24e1521813dc002994f243c2b9de331b763b434 Mon Sep 17 00:00:00 2001
|
||||
From: Pavla Kratochvilova <pkratoch@redhat.com>
|
||||
Date: Fri, 5 Apr 2024 14:42:38 +0200
|
||||
Subject: [PATCH 1/2] remove --duplicates: when no duplicates, exit with 0
|
||||
(RHEL-6424)
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: 720338fed8124b120b56cc99cc0b13dfe48ffe95
|
||||
|
||||
If no duplicates are present, then the command succesfully removed all
|
||||
duplicates and should exit with 0 and write the message to stdout
|
||||
instead of stderr.
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-6424
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
dnf/cli/commands/remove.py | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dnf/cli/commands/remove.py b/dnf/cli/commands/remove.py
|
||||
index e455ba6e..af9622fd 100644
|
||||
--- a/dnf/cli/commands/remove.py
|
||||
+++ b/dnf/cli/commands/remove.py
|
||||
@@ -92,7 +92,8 @@ class RemoveCommand(commands.Command):
|
||||
instonly = self.base._get_installonly_query(q.installed())
|
||||
dups = q.duplicated().difference(instonly)
|
||||
if not dups:
|
||||
- raise dnf.exceptions.Error(_('No duplicated packages found for removal.'))
|
||||
+ logger.info(_('No duplicated packages found for removal.'))
|
||||
+ return
|
||||
|
||||
for (name, arch), pkgs_list in dups._na_dict().items():
|
||||
if len(pkgs_list) < 2:
|
||||
--
|
||||
2.45.0
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
From 1e78096d569eecbd3201c821cb3484328caf8789 Mon Sep 17 00:00:00 2001
|
||||
From: Pavla Kratochvilova <pkratoch@redhat.com>
|
||||
Date: Fri, 5 Apr 2024 14:43:04 +0200
|
||||
Subject: [PATCH 2/2] remove --oldinstallonly: when no old installonly
|
||||
packages, exit with 0
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: 87eb5a7a3561381b5ef5e70548f49288251300fc
|
||||
|
||||
If no old installonly packages are present, then the command succesfully
|
||||
removed all of them and should exit with 0 and write the message to
|
||||
stdout instead of stderr.
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-6424
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
dnf/cli/commands/remove.py | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dnf/cli/commands/remove.py b/dnf/cli/commands/remove.py
|
||||
index af9622fd..32e78d6d 100644
|
||||
--- a/dnf/cli/commands/remove.py
|
||||
+++ b/dnf/cli/commands/remove.py
|
||||
@@ -124,8 +124,7 @@ class RemoveCommand(commands.Command):
|
||||
for pkg in instonly:
|
||||
self.base.package_remove(pkg)
|
||||
else:
|
||||
- raise dnf.exceptions.Error(
|
||||
- _('No old installonly packages found for removal.'))
|
||||
+ logger.info(_('No old installonly packages found for removal.'))
|
||||
return
|
||||
|
||||
# Remove groups.
|
||||
--
|
||||
2.45.0
|
||||
|
||||
@ -0,0 +1,138 @@
|
||||
From 9870192e1acdfa6bb786faf8ae7f989795e52003 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Mracek <jmracek@redhat.com>
|
||||
Date: Wed, 22 May 2024 11:09:34 +0200
|
||||
Subject: [PATCH 1/2] Limit queries to nevra forms when provided by command
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: b3b9b3a48ca5efd9935f3f12bb65530a51ade09c
|
||||
|
||||
Command `dnf install-n <provide>` does not install only according
|
||||
to package mame but still search in provides. The patch limits
|
||||
searrch only to NEVRA forms for install, remove, autoremove,
|
||||
and repoquery commands.
|
||||
|
||||
Resolves partially: https://issues.redhat.com/browse/RHEL-5747
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-38470
|
||||
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
dnf/base.py | 14 ++++++++++++--
|
||||
dnf/cli/commands/repoquery.py | 5 +++--
|
||||
doc/api_base.rst | 6 +++++-
|
||||
doc/command_ref.rst | 7 +++++--
|
||||
4 files changed, 25 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/dnf/base.py b/dnf/base.py
|
||||
index b8237183..13222407 100644
|
||||
--- a/dnf/base.py
|
||||
+++ b/dnf/base.py
|
||||
@@ -2061,9 +2061,14 @@ class Base(object):
|
||||
def install(self, pkg_spec, reponame=None, strict=True, forms=None):
|
||||
# :api
|
||||
"""Mark package(s) given by pkg_spec and reponame for installation."""
|
||||
+ kwargs = {'forms': forms, 'with_src': False}
|
||||
+ if forms:
|
||||
+ kwargs['with_nevra'] = True
|
||||
+ kwargs['with_provides'] = False
|
||||
+ kwargs['with_filenames'] = False
|
||||
|
||||
subj = dnf.subject.Subject(pkg_spec)
|
||||
- solution = subj.get_best_solution(self.sack, forms=forms, with_src=False)
|
||||
+ solution = subj.get_best_solution(self.sack, **kwargs)
|
||||
|
||||
if self.conf.multilib_policy == "all" or subj._is_arch_specified(solution):
|
||||
q = solution['query']
|
||||
@@ -2303,8 +2308,13 @@ class Base(object):
|
||||
def remove(self, pkg_spec, reponame=None, forms=None):
|
||||
# :api
|
||||
"""Mark the specified package for removal."""
|
||||
+ kwargs = {'forms': forms}
|
||||
+ if forms:
|
||||
+ kwargs['with_nevra'] = True
|
||||
+ kwargs['with_provides'] = False
|
||||
+ kwargs['with_filenames'] = False
|
||||
|
||||
- matches = dnf.subject.Subject(pkg_spec).get_best_query(self.sack, forms=forms)
|
||||
+ matches = dnf.subject.Subject(pkg_spec).get_best_query(self.sack, **kwargs)
|
||||
installed = [
|
||||
pkg for pkg in matches.installed()
|
||||
if reponame is None or
|
||||
diff --git a/dnf/cli/commands/repoquery.py b/dnf/cli/commands/repoquery.py
|
||||
index dcd7996f..e8ca38c5 100644
|
||||
--- a/dnf/cli/commands/repoquery.py
|
||||
+++ b/dnf/cli/commands/repoquery.py
|
||||
@@ -447,9 +447,10 @@ class RepoQueryCommand(commands.Command):
|
||||
if self.opts.key:
|
||||
remote_packages = self._add_add_remote_packages()
|
||||
|
||||
- kwark = {}
|
||||
+ kwark = {'with_provides': False}
|
||||
if self.opts.command in self.nevra_forms:
|
||||
kwark["forms"] = [self.nevra_forms[self.opts.command]]
|
||||
+ kwark['with_filenames'] = False
|
||||
pkgs = []
|
||||
query_results = q.filter(empty=True)
|
||||
|
||||
@@ -460,7 +461,7 @@ class RepoQueryCommand(commands.Command):
|
||||
for key in self.opts.key:
|
||||
query_results = query_results.union(
|
||||
dnf.subject.Subject(key, ignore_case=True).get_best_query(
|
||||
- self.base.sack, with_provides=False, query=q, **kwark))
|
||||
+ self.base.sack, query=q, **kwark))
|
||||
q = query_results
|
||||
|
||||
if self.opts.recent:
|
||||
diff --git a/doc/api_base.rst b/doc/api_base.rst
|
||||
index 389b28ec..95d2d570 100644
|
||||
--- a/doc/api_base.rst
|
||||
+++ b/doc/api_base.rst
|
||||
@@ -280,7 +280,11 @@
|
||||
.. method:: install(pkg_spec, reponame=None, strict=True, forms=None)
|
||||
|
||||
Mark packages matching `pkg_spec` for installation.
|
||||
- `reponame` can be a name of a repository or a list of repository names. If given, the selection of available packages is limited to packages from these repositories. If strict is set to False, the installation ignores packages with dependency solving problems. Parameter `forms` has the same meaning as in :meth:`dnf.subject.Subject.get_best_query`.
|
||||
+ `reponame` can be a name of a repository or a list of repository names. If given, the selection of available
|
||||
+ packages is limited to packages from these repositories. If strict is set to False, the installation ignores
|
||||
+ packages with dependency solving problems. Parameter `forms` is list of pattern forms from `hawkey`_.
|
||||
+ Leaving the parameter to ``None`` results in using a reasonable default list of forms. When forms is specified,
|
||||
+ method will not match `pkg_spec` with provides and file provides.
|
||||
|
||||
.. method:: package_downgrade(pkg, strict=False)
|
||||
|
||||
diff --git a/doc/command_ref.rst b/doc/command_ref.rst
|
||||
index ffb84407..e97c0d60 100644
|
||||
--- a/doc/command_ref.rst
|
||||
+++ b/doc/command_ref.rst
|
||||
@@ -857,7 +857,8 @@ Install Command
|
||||
are considered correct, the resulting package is picked simply by lexicographical order.
|
||||
|
||||
There are also a few specific install commands ``install-n``, ``install-na`` and
|
||||
- ``install-nevra`` that allow the specification of an exact argument in the NEVRA format.
|
||||
+ ``install-nevra`` that allow the specification of an exact argument in the NEVRA format. As a consequence, <spec>
|
||||
+ will be not matched with provides and file provides.
|
||||
|
||||
See also :ref:`\configuration_files_replacement_policy-label`.
|
||||
|
||||
@@ -1190,7 +1191,8 @@ Remove Command
|
||||
Removes old installonly packages, keeping only latest versions and version of running kernel.
|
||||
|
||||
There are also a few specific remove commands ``remove-n``, ``remove-na`` and ``remove-nevra``
|
||||
- that allow the specification of an exact argument in the NEVRA format.
|
||||
+ that allow the specification of an exact argument in the NEVRA format. As a consequence, <spec>
|
||||
+ will be not matched with provides and file provides.
|
||||
|
||||
Remove Examples
|
||||
---------------
|
||||
@@ -1254,6 +1256,7 @@ Repoquery Command
|
||||
|
||||
There are also a few specific repoquery commands ``repoquery-n``, ``repoquery-na`` and ``repoquery-nevra``
|
||||
that allow the specification of an exact argument in the NEVRA format (does not affect arguments of options like --whatprovides <arg>, ...).
|
||||
+ As a consequence, <spec> will be not matched with file provides.
|
||||
|
||||
Select Options
|
||||
--------------
|
||||
--
|
||||
2.45.1
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
From b406aa778031abe550b84bdbdd6826ac3cf0866f Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Mracek <jmracek@redhat.com>
|
||||
Date: Thu, 23 May 2024 11:25:29 +0200
|
||||
Subject: [PATCH 2/2] [doc] Remove provide of spec definition for repoquery
|
||||
command
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: f211e1a41a3d3180481e930836ee1a52a7a32487
|
||||
|
||||
Repoquery command never matched spec with provides.
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-38470
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
doc/command_ref.rst | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/doc/command_ref.rst b/doc/command_ref.rst
|
||||
index e97c0d60..c419e7ed 100644
|
||||
--- a/doc/command_ref.rst
|
||||
+++ b/doc/command_ref.rst
|
||||
@@ -1265,7 +1265,7 @@ Together with ``<package-file-spec>``, control what packages are displayed in th
|
||||
packages to those matching the specification. All packages are considered if no ``<package-file-spec>`` is specified.
|
||||
|
||||
``<package-file-spec>``
|
||||
- Package specification in the NEVRA format (name[-[epoch:]version[-release]][.arch]), a package provide or a file provide. See :ref:`Specifying Packages
|
||||
+ Package specification in the NEVRA format (name[-[epoch:]version[-release]][.arch]) or a file provide. See :ref:`Specifying Packages
|
||||
<specifying_packages-label>`.
|
||||
|
||||
``-a``, ``--all``
|
||||
--
|
||||
2.45.1
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
From 103d442551bfa11a2dae72fd31941ba1d5435bb6 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kolarik <jkolarik@redhat.com>
|
||||
Date: Tue, 30 Apr 2024 06:50:14 +0000
|
||||
Subject: [PATCH] man: Improve upgrade-minimal command docs (RHEL-6417)
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: 4a2b425d3f0b7ea95f9584834e86a15ad3c447ab
|
||||
|
||||
Making the man pages for the `upgrade-minimal` command clearer about how packages with advisories are upgraded.
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-6417
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
doc/command_ref.rst | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/doc/command_ref.rst b/doc/command_ref.rst
|
||||
index c419e7ed..42dd6e8a 100644
|
||||
--- a/doc/command_ref.rst
|
||||
+++ b/doc/command_ref.rst
|
||||
@@ -1761,11 +1761,11 @@ Upgrade-Minimal Command
|
||||
| Deprecated aliases: ``update-minimal``
|
||||
|
||||
``dnf [options] upgrade-minimal``
|
||||
- Updates each package to the latest available version that provides a bugfix, enhancement
|
||||
- or a fix for a security issue (security).
|
||||
+ Updates each package to the nearest available version that provides
|
||||
+ a bugfix, enhancement or a fix for a security issue (security).
|
||||
|
||||
``dnf [options] upgrade-minimal <package-spec>...``
|
||||
- Updates each specified package to the latest available version that provides
|
||||
+ Updates each specified package to the nearest available version that provides
|
||||
a bugfix, enhancement or a fix for security issue (security). Updates
|
||||
dependencies as necessary.
|
||||
|
||||
--
|
||||
2.45.2
|
||||
|
||||
@ -0,0 +1,38 @@
|
||||
From 9ceb9b3591899aaa9bb4932bc20be2fa650cbddc Mon Sep 17 00:00:00 2001
|
||||
From: Pavla Kratochvilova <pkratoch@redhat.com>
|
||||
Date: Mon, 18 Mar 2024 11:58:08 +0100
|
||||
Subject: [PATCH] doc: Makecache with timer tries only one mirror
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: a6d82221ae32045f0f788708a52d2f2bf5c5740b
|
||||
Related: https://bugzilla.redhat.com/show_bug.cgi?id=922667
|
||||
Related: https://issues.redhat.com/browse/RHEL-1342
|
||||
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
doc/command_ref.rst | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/doc/command_ref.rst b/doc/command_ref.rst
|
||||
index 42dd6e8a..36817c00 100644
|
||||
--- a/doc/command_ref.rst
|
||||
+++ b/doc/command_ref.rst
|
||||
@@ -973,10 +973,11 @@ Makecache Command
|
||||
|
||||
``dnf [options] makecache --timer``
|
||||
Like plain ``makecache``, but instructs DNF to be more resource-aware,
|
||||
- meaning it will not do anything if running on battery power and will terminate
|
||||
+ meaning it will not do anything if running on battery power, it will terminate
|
||||
immediately if it's too soon after the last successful ``makecache`` run
|
||||
(see :manpage:`dnf.conf(5)`, :ref:`metadata_timer_sync
|
||||
- <metadata_timer_sync-label>`).
|
||||
+ <metadata_timer_sync-label>`), and if the first mirror in a repository mirrorlist fails,
|
||||
+ it will not try to synchronize the metadata from more mirrors for that repository.
|
||||
|
||||
.. _mark_command-label:
|
||||
|
||||
--
|
||||
2.45.2
|
||||
|
||||
@ -0,0 +1,99 @@
|
||||
From 6af6633b3e1e92405ec63ef4d3d697891213f8cb Mon Sep 17 00:00:00 2001
|
||||
From: David Cantrell <dcantrell@redhat.com>
|
||||
Date: Thu, 15 Feb 2024 14:03:32 -0500
|
||||
Subject: [PATCH 1/4] Add detection for ostree-based systems and warn users
|
||||
about losing changes
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: 5c050ba2324c5fb95bf0e0501c7925f38f6a09dc
|
||||
|
||||
On ostree-based systems, users can use dnf to customize the
|
||||
environment but those changes will be lost at the next ostree-based
|
||||
image update. If you want to retain changes between ostree-updates
|
||||
you need to make use of rpm-ostree right now.
|
||||
|
||||
Signed-off-by: David Cantrell <dcantrell@redhat.com>
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-49670
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
dnf/cli/cli.py | 9 +++++++++
|
||||
dnf/util.py | 31 +++++++++++++++++++++++++++++++
|
||||
2 files changed, 40 insertions(+)
|
||||
|
||||
diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py
|
||||
index 0c4f4c6ad..1fd0e96c3 100644
|
||||
--- a/dnf/cli/cli.py
|
||||
+++ b/dnf/cli/cli.py
|
||||
@@ -214,6 +214,15 @@ class BaseCli(dnf.Base):
|
||||
elif 'test' in self.conf.tsflags:
|
||||
logger.info(_("{prog} will only download packages, install gpg keys, and check the "
|
||||
"transaction.").format(prog=dnf.util.MAIN_PROG_UPPER))
|
||||
+ if dnf.util.is_container():
|
||||
+ _container_msg = _("""
|
||||
+*** This system is managed with ostree. Changes to the system
|
||||
+*** made with dnf will be lost with the next ostree-based update.
|
||||
+*** If you do not want to lose these changes, use 'rpm-ostree'.
|
||||
+""")
|
||||
+ logger.info(_container_msg)
|
||||
+ raise CliError(_("Operation aborted."))
|
||||
+
|
||||
if self._promptWanted():
|
||||
if self.conf.assumeno or not self.output.userconfirm():
|
||||
raise CliError(_("Operation aborted."))
|
||||
diff --git a/dnf/util.py b/dnf/util.py
|
||||
index 16c5bc89c..9909f8fea 100644
|
||||
--- a/dnf/util.py
|
||||
+++ b/dnf/util.py
|
||||
@@ -33,11 +33,13 @@ import errno
|
||||
import functools
|
||||
import hawkey
|
||||
import itertools
|
||||
+import json
|
||||
import locale
|
||||
import logging
|
||||
import os
|
||||
import pwd
|
||||
import shutil
|
||||
+import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
@@ -631,3 +633,32 @@ def _post_transaction_output(base, transaction, action_callback):
|
||||
def _name_unset_wrapper(input_name):
|
||||
# returns <name-unset> for everything that evaluates to False (None, empty..)
|
||||
return input_name if input_name else _("<name-unset>")
|
||||
+
|
||||
+
|
||||
+def is_container():
|
||||
+ """Returns true is the system is managed as an immutable container,
|
||||
+ false otherwise. If msg is True, a warning message is displayed
|
||||
+ for the user.
|
||||
+ """
|
||||
+
|
||||
+ bootc = '/usr/bin/bootc'
|
||||
+ ostree = '/sysroot/ostree'
|
||||
+
|
||||
+ if os.path.isfile(bootc) and os.access(bootc, os.X_OK):
|
||||
+ p = subprocess.Popen([bootc, "status", "--json"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
+ (out, err) = p.communicate()
|
||||
+
|
||||
+ if p.returncode == 0:
|
||||
+ # check the output of 'bootc status'
|
||||
+ j = json.loads(out)
|
||||
+
|
||||
+ # XXX: the API from bootc status is evolving
|
||||
+ status = j.get("status", "")
|
||||
+ kind = j.get("kind", "")
|
||||
+
|
||||
+ if kind.lower() == "bootchost" and bool(status.get("isContainer", None)):
|
||||
+ return True
|
||||
+ elif os.path.isdir(ostree):
|
||||
+ return True
|
||||
+
|
||||
+ return False
|
||||
\ No newline at end of file
|
||||
--
|
||||
2.46.2
|
||||
|
||||
107
SOURCES/0028-Update-ostree-bootc-host-system-check.patch
Normal file
107
SOURCES/0028-Update-ostree-bootc-host-system-check.patch
Normal file
@ -0,0 +1,107 @@
|
||||
From 6157248a5035a7752115143d8d29773384c1db3f Mon Sep 17 00:00:00 2001
|
||||
From: Joseph Marrero <jmarrero@redhat.com>
|
||||
Date: Tue, 16 Jul 2024 15:48:41 -0400
|
||||
Subject: [PATCH 2/4] Update ostree/bootc host system check.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: 6120fe52511775b60b6031d4169988c025610ab5
|
||||
|
||||
This changes the is_container() func for _is_bootc_host()
|
||||
and updates the logic and message. This should detect on
|
||||
all ostree and bootc hosts to date that are not using
|
||||
bootc usroverlay or ostree admin unlock for development
|
||||
purposes.
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-49670
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
dnf/cli/cli.py | 11 +++++------
|
||||
dnf/util.py | 33 ++++++++-------------------------
|
||||
2 files changed, 13 insertions(+), 31 deletions(-)
|
||||
|
||||
diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py
|
||||
index 1fd0e96c3..8521dd351 100644
|
||||
--- a/dnf/cli/cli.py
|
||||
+++ b/dnf/cli/cli.py
|
||||
@@ -214,13 +214,12 @@ class BaseCli(dnf.Base):
|
||||
elif 'test' in self.conf.tsflags:
|
||||
logger.info(_("{prog} will only download packages, install gpg keys, and check the "
|
||||
"transaction.").format(prog=dnf.util.MAIN_PROG_UPPER))
|
||||
- if dnf.util.is_container():
|
||||
- _container_msg = _("""
|
||||
-*** This system is managed with ostree. Changes to the system
|
||||
-*** made with dnf will be lost with the next ostree-based update.
|
||||
-*** If you do not want to lose these changes, use 'rpm-ostree'.
|
||||
+ if dnf.util._is_bootc_host():
|
||||
+ _bootc_host_msg = _("""
|
||||
+*** Error: system is configured to be read-only; for more
|
||||
+*** information run `bootc status` or `ostree admin status`.
|
||||
""")
|
||||
- logger.info(_container_msg)
|
||||
+ logger.info(_bootc_host_msg)
|
||||
raise CliError(_("Operation aborted."))
|
||||
|
||||
if self._promptWanted():
|
||||
diff --git a/dnf/util.py b/dnf/util.py
|
||||
index 9909f8fea..e8f587a03 100644
|
||||
--- a/dnf/util.py
|
||||
+++ b/dnf/util.py
|
||||
@@ -33,13 +33,11 @@ import errno
|
||||
import functools
|
||||
import hawkey
|
||||
import itertools
|
||||
-import json
|
||||
import locale
|
||||
import logging
|
||||
import os
|
||||
import pwd
|
||||
import shutil
|
||||
-import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
@@ -635,30 +633,15 @@ def _name_unset_wrapper(input_name):
|
||||
return input_name if input_name else _("<name-unset>")
|
||||
|
||||
|
||||
-def is_container():
|
||||
+def _is_bootc_host():
|
||||
"""Returns true is the system is managed as an immutable container,
|
||||
false otherwise. If msg is True, a warning message is displayed
|
||||
for the user.
|
||||
"""
|
||||
-
|
||||
- bootc = '/usr/bin/bootc'
|
||||
- ostree = '/sysroot/ostree'
|
||||
-
|
||||
- if os.path.isfile(bootc) and os.access(bootc, os.X_OK):
|
||||
- p = subprocess.Popen([bootc, "status", "--json"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
- (out, err) = p.communicate()
|
||||
-
|
||||
- if p.returncode == 0:
|
||||
- # check the output of 'bootc status'
|
||||
- j = json.loads(out)
|
||||
-
|
||||
- # XXX: the API from bootc status is evolving
|
||||
- status = j.get("status", "")
|
||||
- kind = j.get("kind", "")
|
||||
-
|
||||
- if kind.lower() == "bootchost" and bool(status.get("isContainer", None)):
|
||||
- return True
|
||||
- elif os.path.isdir(ostree):
|
||||
- return True
|
||||
-
|
||||
- return False
|
||||
\ No newline at end of file
|
||||
+ ostree_booted = '/run/ostree-booted'
|
||||
+ usr = '/usr/'
|
||||
+ # Check if usr is writtable and we are in a running ostree system.
|
||||
+ # We want this code to return true only when the system is in locked state. If someone ran
|
||||
+ # bootc overlay or ostree admin unlock we would want normal DNF path to be ran as it will be
|
||||
+ # temporary changes (until reboot).
|
||||
+ return os.path.isfile(ostree_booted) and not os.access(usr, os.W_OK)
|
||||
--
|
||||
2.46.2
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
From 0bab6b9620f9872271c9458212538eb03b8b085c Mon Sep 17 00:00:00 2001
|
||||
From: Joseph Marrero <jmarrero@redhat.com>
|
||||
Date: Mon, 22 Jul 2024 15:33:32 -0400
|
||||
Subject: [PATCH 3/4] Update bootc hosts message to point to bootc --help
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: e2535589ce16bc36b96b37369502a3c312f6056a
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-49670
|
||||
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
dnf/cli/cli.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py
|
||||
index 8521dd351..99af9069b 100644
|
||||
--- a/dnf/cli/cli.py
|
||||
+++ b/dnf/cli/cli.py
|
||||
@@ -217,7 +217,7 @@ class BaseCli(dnf.Base):
|
||||
if dnf.util._is_bootc_host():
|
||||
_bootc_host_msg = _("""
|
||||
*** Error: system is configured to be read-only; for more
|
||||
-*** information run `bootc status` or `ostree admin status`.
|
||||
+*** information run `bootc --help`.
|
||||
""")
|
||||
logger.info(_bootc_host_msg)
|
||||
raise CliError(_("Operation aborted."))
|
||||
--
|
||||
2.46.2
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
From ca4c52214b16fe298c44939cd7aaccd9b7549869 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
|
||||
Date: Thu, 15 Aug 2024 14:04:55 +0200
|
||||
Subject: [PATCH 4/4] Allow --installroot on read-only bootc system
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: a1aa8d0e048751859a2bec1b2fb12fcca93c6e83
|
||||
|
||||
Some people use --installroot on a read-only bootc system to install
|
||||
a system into a chroot subtree. However, current bootc check did not
|
||||
take into account --installroot and rejected the operation.
|
||||
|
||||
This patch augments the check for the installroot being different
|
||||
from /.
|
||||
|
||||
It's pointless to check for installroot writability here because
|
||||
installroot is written before this check when updating the
|
||||
repositories and computing a transaction. Moving this check sooner
|
||||
would not help because some directories (/opt, /) are kept read-only
|
||||
even on writable bootc.
|
||||
|
||||
Resolves: #2108
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-49670
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
dnf/cli/cli.py | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py
|
||||
index 99af9069b..36cfa74b5 100644
|
||||
--- a/dnf/cli/cli.py
|
||||
+++ b/dnf/cli/cli.py
|
||||
@@ -214,7 +214,8 @@ class BaseCli(dnf.Base):
|
||||
elif 'test' in self.conf.tsflags:
|
||||
logger.info(_("{prog} will only download packages, install gpg keys, and check the "
|
||||
"transaction.").format(prog=dnf.util.MAIN_PROG_UPPER))
|
||||
- if dnf.util._is_bootc_host():
|
||||
+ if dnf.util._is_bootc_host() and \
|
||||
+ os.path.realpath(self.conf.installroot) == "/":
|
||||
_bootc_host_msg = _("""
|
||||
*** Error: system is configured to be read-only; for more
|
||||
*** information run `bootc --help`.
|
||||
--
|
||||
2.46.2
|
||||
|
||||
33
SOURCES/0031-smtplib-catch-OSError-not-SMTPException.patch
Normal file
33
SOURCES/0031-smtplib-catch-OSError-not-SMTPException.patch
Normal file
@ -0,0 +1,33 @@
|
||||
From ea2d17cc484c7c49686145f4b2e98e4b73b9c967 Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Mon, 13 Mar 2023 14:50:41 -0400
|
||||
Subject: [PATCH] smtplib: catch OSError, not SMTPException
|
||||
|
||||
Some, but not all, types of connection error are caught by smtplib and
|
||||
reraised as an smtplib.SMTPException. Notably, TimeoutError,
|
||||
socket.gaierror (name resolution failure), and ConnectionRefusedError
|
||||
and are not caught.
|
||||
|
||||
The more generic OSError should be caught here instead.
|
||||
|
||||
Resolves #1905
|
||||
---
|
||||
dnf/automatic/emitter.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dnf/automatic/emitter.py b/dnf/automatic/emitter.py
|
||||
index 4aea4b02..648f1a1d 100644
|
||||
--- a/dnf/automatic/emitter.py
|
||||
+++ b/dnf/automatic/emitter.py
|
||||
@@ -106,7 +106,7 @@ class EmailEmitter(Emitter):
|
||||
smtp = smtplib.SMTP(self._conf.email_host, timeout=300)
|
||||
smtp.sendmail(email_from, email_to, message.as_string())
|
||||
smtp.close()
|
||||
- except smtplib.SMTPException as exc:
|
||||
+ except OSError as exc:
|
||||
msg = _("Failed to send an email via '%s': %s") % (
|
||||
self._conf.email_host, exc)
|
||||
logger.error(msg)
|
||||
--
|
||||
2.46.1
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
From fdeb208b7b6522bd458142867683b1bf68cd355d Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
|
||||
Date: Thu, 10 Oct 2024 10:57:48 +0200
|
||||
Subject: [PATCH] Allow --downloadonly on read-only bootc system
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: 8d888d26e6da27ba37243d7504eb42472f389bde
|
||||
|
||||
"dnf install --downloadonly" failed on read-only bootc system despite
|
||||
not running the transaction. The downloaded packages are stored under
|
||||
writable /var or to a directory explicitly choosen by a user.
|
||||
|
||||
This patch suppresses the bootc read-only bailout if --downloadonly
|
||||
option is used.
|
||||
|
||||
https://issues.redhat.com/browse/RHEL-61745
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
dnf/cli/cli.py | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py
|
||||
index 36cfa74b5..3dc08d616 100644
|
||||
--- a/dnf/cli/cli.py
|
||||
+++ b/dnf/cli/cli.py
|
||||
@@ -215,7 +215,8 @@ class BaseCli(dnf.Base):
|
||||
logger.info(_("{prog} will only download packages, install gpg keys, and check the "
|
||||
"transaction.").format(prog=dnf.util.MAIN_PROG_UPPER))
|
||||
if dnf.util._is_bootc_host() and \
|
||||
- os.path.realpath(self.conf.installroot) == "/":
|
||||
+ os.path.realpath(self.conf.installroot) == "/" and \
|
||||
+ not self.conf.downloadonly:
|
||||
_bootc_host_msg = _("""
|
||||
*** Error: system is configured to be read-only; for more
|
||||
*** information run `bootc --help`.
|
||||
--
|
||||
2.47.0
|
||||
|
||||
@ -0,0 +1,81 @@
|
||||
From d8bd8174426a2d053b20acc7c2bcd83a572fc1d5 Mon Sep 17 00:00:00 2001
|
||||
From: Marek Blaha <mblaha@redhat.com>
|
||||
Date: Thu, 17 Oct 2024 13:30:21 +0200
|
||||
Subject: [PATCH] automatic: Check availability of config file
|
||||
|
||||
Upstream commit: 13ecc3921fb1566c2af7b80d5cb515d8fc4e5ec9
|
||||
RHEL issue: https://issues.redhat.com/browse/RHEL-49743
|
||||
|
||||
If a configuration file is explicitly specified on the command line,
|
||||
ensure that it exists and is readable. If the file is not found, notify
|
||||
the user immediately and terminate the process.
|
||||
|
||||
This resolves issues where users may run dnf-automatic with unrecognized
|
||||
positional arguments, such as `dnf-automatic install`.
|
||||
|
||||
The most natural approach to handle a non-existing config file would be
|
||||
by catching the exception thrown by the `read()` method of the
|
||||
`libdnf.conf.ConfigParser` class. Unfortunately, the Python bindings
|
||||
override the `read()` method at the SWIG level, causing it to suppress any
|
||||
potentially raised IOError.
|
||||
For details see this section of the commit
|
||||
https://github.com/rpm-software-management/libdnf/commit/8f1fedf8551b72d6bc24018f5980714b3a103aeb
|
||||
|
||||
def ConfigParser__newRead(self, filenames):
|
||||
parsedFNames = []
|
||||
try:
|
||||
if isinstance(filenames, str) or isinstance(filenames, unicode):
|
||||
filenames = [filenames]
|
||||
except NameError:
|
||||
pass
|
||||
for fname in filenames:
|
||||
try:
|
||||
self.readFileName(fname)
|
||||
parsedFNames.append(fname)
|
||||
except IOError:
|
||||
pass
|
||||
except Exception as e:
|
||||
raise RuntimeError("Parsing file '%s' failed: %s" % (fname, str(e)))
|
||||
return parsedFNames
|
||||
ConfigParser.read = ConfigParser__newRead
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-46030
|
||||
---
|
||||
dnf/automatic/main.py | 14 ++++++++++++--
|
||||
1 file changed, 12 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dnf/automatic/main.py b/dnf/automatic/main.py
|
||||
index caef627f..bb0bd493 100644
|
||||
--- a/dnf/automatic/main.py
|
||||
+++ b/dnf/automatic/main.py
|
||||
@@ -74,7 +74,7 @@ def build_emitters(conf):
|
||||
|
||||
def parse_arguments(args):
|
||||
parser = argparse.ArgumentParser()
|
||||
- parser.add_argument('conf_path', nargs='?', default=dnf.const.CONF_AUTOMATIC_FILENAME)
|
||||
+ parser.add_argument('conf_path', nargs='?')
|
||||
parser.add_argument('--timer', action='store_true')
|
||||
parser.add_argument('--installupdates', dest='installupdates', action='store_true')
|
||||
parser.add_argument('--downloadupdates', dest='downloadupdates', action='store_true')
|
||||
@@ -89,7 +89,17 @@ def parse_arguments(args):
|
||||
class AutomaticConfig(object):
|
||||
def __init__(self, filename=None, downloadupdates=None,
|
||||
installupdates=None):
|
||||
- if not filename:
|
||||
+ if filename:
|
||||
+ # Specific config file was explicitely requested. Check that it exists
|
||||
+ # and is readable.
|
||||
+ if os.access(filename, os.F_OK):
|
||||
+ if not os.access(filename, os.R_OK):
|
||||
+ raise dnf.exceptions.Error(
|
||||
+ "Configuration file \"{}\" is not readable.".format(filename))
|
||||
+ else:
|
||||
+ raise dnf.exceptions.Error(
|
||||
+ "Configuration file \"{}\" not found.".format(filename))
|
||||
+ else:
|
||||
filename = dnf.const.CONF_AUTOMATIC_FILENAME
|
||||
self.commands = CommandsConfig()
|
||||
self.email = EmailConfig()
|
||||
--
|
||||
2.47.0
|
||||
|
||||
247
SOURCES/0034-automatic-emitters-send-error-messages.patch
Normal file
247
SOURCES/0034-automatic-emitters-send-error-messages.patch
Normal file
@ -0,0 +1,247 @@
|
||||
From 130e44556d49cf9fa4a0468bb73b56182691ab86 Mon Sep 17 00:00:00 2001
|
||||
From: derickdiaz <derickdiaz123@outlook.com>
|
||||
Date: Sun, 15 Oct 2023 10:58:03 -0500
|
||||
Subject: [PATCH 1/4] Added feature to allow emitters to invoke on dnf error
|
||||
|
||||
---
|
||||
AUTHORS | 1 +
|
||||
dnf/automatic/emitter.py | 22 ++++++++++++++++++----
|
||||
dnf/automatic/main.py | 5 +++++
|
||||
3 files changed, 24 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/AUTHORS b/AUTHORS
|
||||
index 699a92c4..2e16c8ae 100644
|
||||
--- a/AUTHORS
|
||||
+++ b/AUTHORS
|
||||
@@ -68,6 +68,7 @@ DNF CONTRIBUTORS
|
||||
Christopher Meng <cickumqt@gmail.com>
|
||||
Daniel Mach <dmach@redhat.com>
|
||||
Dave Johansen <davejohansen@gmail.com>
|
||||
+ Derick Diaz <derickdiaz123@outlook.com>
|
||||
Dylan Pindur <dylanpindur@gmail.com>
|
||||
Eduard Cuba <ecuba@redhat.com>
|
||||
Evan Goode <egoode@redhat.com>
|
||||
diff --git a/dnf/automatic/emitter.py b/dnf/automatic/emitter.py
|
||||
index 648f1a1d..673da082 100644
|
||||
--- a/dnf/automatic/emitter.py
|
||||
+++ b/dnf/automatic/emitter.py
|
||||
@@ -33,6 +33,7 @@ APPLIED = _("The following updates have been applied on '%s':")
|
||||
APPLIED_TIMESTAMP = _("Updates completed at %s")
|
||||
AVAILABLE = _("The following updates are available on '%s':")
|
||||
DOWNLOADED = _("The following updates were downloaded on '%s':")
|
||||
+ERROR = _("An error has occured on: '%s'")
|
||||
|
||||
logger = logging.getLogger('dnf')
|
||||
|
||||
@@ -44,10 +45,15 @@ class Emitter(object):
|
||||
self._downloaded = False
|
||||
self._system_name = system_name
|
||||
self._trans_msg = None
|
||||
+ self._error = False
|
||||
+ self._error_msg = None
|
||||
|
||||
def _prepare_msg(self):
|
||||
msg = []
|
||||
- if self._applied:
|
||||
+ if self._error:
|
||||
+ msg.append(ERROR % self._system_name)
|
||||
+ msg.append(self._error_msg)
|
||||
+ elif self._applied:
|
||||
msg.append(APPLIED % self._system_name)
|
||||
msg.append(self._available_msg)
|
||||
msg.append(APPLIED_TIMESTAMP % time.strftime("%c"))
|
||||
@@ -72,6 +78,10 @@ class Emitter(object):
|
||||
assert self._available_msg
|
||||
self._downloaded = True
|
||||
|
||||
+ def notify_error(self, msg):
|
||||
+ self._error = True
|
||||
+ self._error_msg = msg
|
||||
+
|
||||
|
||||
class EmailEmitter(Emitter):
|
||||
def __init__(self, system_name, conf):
|
||||
@@ -79,7 +89,9 @@ class EmailEmitter(Emitter):
|
||||
self._conf = conf
|
||||
|
||||
def _prepare_msg(self):
|
||||
- if self._applied:
|
||||
+ if self._error:
|
||||
+ subj = _("An error has occured on '%s'.") % self._system_name
|
||||
+ elif self._applied:
|
||||
subj = _("Updates applied on '%s'.") % self._system_name
|
||||
elif self._downloaded:
|
||||
subj = _("Updates downloaded on '%s'.") % self._system_name
|
||||
@@ -95,6 +107,8 @@ class EmailEmitter(Emitter):
|
||||
message.set_charset('utf-8')
|
||||
email_from = self._conf.email_from
|
||||
email_to = self._conf.email_to
|
||||
+ email_host = self._conf.email_host
|
||||
+ email_port = self._conf.email_port
|
||||
message['Date'] = email.utils.formatdate()
|
||||
message['From'] = email_from
|
||||
message['Subject'] = subj
|
||||
@@ -103,12 +117,12 @@ class EmailEmitter(Emitter):
|
||||
|
||||
# Send the email
|
||||
try:
|
||||
- smtp = smtplib.SMTP(self._conf.email_host, timeout=300)
|
||||
+ smtp = smtplib.SMTP(email_host, email_port, timeout=300)
|
||||
smtp.sendmail(email_from, email_to, message.as_string())
|
||||
smtp.close()
|
||||
except OSError as exc:
|
||||
msg = _("Failed to send an email via '%s': %s") % (
|
||||
- self._conf.email_host, exc)
|
||||
+ email_host, exc)
|
||||
logger.error(msg)
|
||||
|
||||
|
||||
diff --git a/dnf/automatic/main.py b/dnf/automatic/main.py
|
||||
index bb0bd493..8aca210a 100644
|
||||
--- a/dnf/automatic/main.py
|
||||
+++ b/dnf/automatic/main.py
|
||||
@@ -314,6 +314,7 @@ def main(args):
|
||||
try:
|
||||
conf = AutomaticConfig(opts.conf_path, opts.downloadupdates,
|
||||
opts.installupdates)
|
||||
+ emitters = None
|
||||
with dnf.Base() as base:
|
||||
cli = dnf.cli.Cli(base)
|
||||
cli._read_conf_file()
|
||||
@@ -376,9 +377,13 @@ def main(args):
|
||||
exit_code = os.waitstatus_to_exitcode(os.system(conf.commands.reboot_command))
|
||||
if exit_code != 0:
|
||||
logger.error('Error: reboot command returned nonzero exit code: %d', exit_code)
|
||||
+ emitters.notify_error('Error: reboot command returned nonzero exit code: %d', exit_code)
|
||||
+ emitters.commit()
|
||||
return 1
|
||||
except dnf.exceptions.Error as exc:
|
||||
logger.error(_('Error: %s'), ucd(exc))
|
||||
+ emitters.notify_error(_('Error: %s') % str(exc))
|
||||
+ emitters.commit()
|
||||
return 1
|
||||
return 0
|
||||
|
||||
--
|
||||
2.47.1
|
||||
|
||||
|
||||
From 1d18e7c6c03d6de084a6845db3a2dc50f02c8e4c Mon Sep 17 00:00:00 2001
|
||||
From: derickdiaz <derickdiaz123@outlook.com>
|
||||
Date: Thu, 19 Oct 2023 04:58:45 -0500
|
||||
Subject: [PATCH 2/4] Checks if emitter is null incase build_emitters throws a
|
||||
ConfigError
|
||||
|
||||
---
|
||||
dnf/automatic/main.py | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dnf/automatic/main.py b/dnf/automatic/main.py
|
||||
index 8aca210a..04926346 100644
|
||||
--- a/dnf/automatic/main.py
|
||||
+++ b/dnf/automatic/main.py
|
||||
@@ -382,8 +382,9 @@ def main(args):
|
||||
return 1
|
||||
except dnf.exceptions.Error as exc:
|
||||
logger.error(_('Error: %s'), ucd(exc))
|
||||
- emitters.notify_error(_('Error: %s') % str(exc))
|
||||
- emitters.commit()
|
||||
+ if conf.emitters != None:
|
||||
+ emitters.notify_error(_('Error: %s') % str(exc))
|
||||
+ emitters.commit()
|
||||
return 1
|
||||
return 0
|
||||
|
||||
--
|
||||
2.47.1
|
||||
|
||||
|
||||
From 3e45752f0b74d2c4297da429a57b3e5148374195 Mon Sep 17 00:00:00 2001
|
||||
From: derickdiaz <derickdiaz123@outlook.com>
|
||||
Date: Thu, 19 Oct 2023 05:21:23 -0500
|
||||
Subject: [PATCH 3/4] Added 'send_error_messages' Boolean Option and updated
|
||||
man docs
|
||||
|
||||
Added option 'send_error_messages'
|
||||
|
||||
Fixed Option String List
|
||||
|
||||
Changed option to Boolean
|
||||
---
|
||||
dnf/automatic/main.py | 8 +++-----
|
||||
doc/automatic.rst | 5 +++++
|
||||
2 files changed, 8 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/dnf/automatic/main.py b/dnf/automatic/main.py
|
||||
index 04926346..0a9d5041 100644
|
||||
--- a/dnf/automatic/main.py
|
||||
+++ b/dnf/automatic/main.py
|
||||
@@ -239,6 +239,7 @@ class EmittersConfig(Config):
|
||||
libdnf.conf.VectorString(['email', 'stdio'])))
|
||||
self.add_option('output_width', libdnf.conf.OptionNumberInt32(80))
|
||||
self.add_option('system_name', libdnf.conf.OptionString(socket.gethostname()))
|
||||
+ self.add_option('send_error_messages', libdnf.conf.OptionBool(False))
|
||||
|
||||
|
||||
def gpgsigcheck(base, pkgs):
|
||||
@@ -376,13 +377,10 @@ def main(args):
|
||||
(conf.commands.reboot == 'when-needed' and base.reboot_needed())):
|
||||
exit_code = os.waitstatus_to_exitcode(os.system(conf.commands.reboot_command))
|
||||
if exit_code != 0:
|
||||
- logger.error('Error: reboot command returned nonzero exit code: %d', exit_code)
|
||||
- emitters.notify_error('Error: reboot command returned nonzero exit code: %d', exit_code)
|
||||
- emitters.commit()
|
||||
- return 1
|
||||
+ raise dnf.exceptions.Error('reboot command returned nonzero exit code: %d', exit_code)
|
||||
except dnf.exceptions.Error as exc:
|
||||
logger.error(_('Error: %s'), ucd(exc))
|
||||
- if conf.emitters != None:
|
||||
+ if conf.emitters.send_error_messages and emitters != None:
|
||||
emitters.notify_error(_('Error: %s') % str(exc))
|
||||
emitters.commit()
|
||||
return 1
|
||||
diff --git a/doc/automatic.rst b/doc/automatic.rst
|
||||
index 329c2f46..2d514b78 100644
|
||||
--- a/doc/automatic.rst
|
||||
+++ b/doc/automatic.rst
|
||||
@@ -120,6 +120,11 @@ Choosing how the results should be reported.
|
||||
|
||||
How the system is called in the reports.
|
||||
|
||||
+``send_error_messages``
|
||||
+ boolean, default: False
|
||||
+
|
||||
+ Invokes emitters when an errors occurs
|
||||
+
|
||||
---------------------
|
||||
``[command]`` section
|
||||
---------------------
|
||||
--
|
||||
2.47.1
|
||||
|
||||
|
||||
From 33d52a8072c47b74603cf38ec807c26657799578 Mon Sep 17 00:00:00 2001
|
||||
From: derickdiaz <derickdiaz123@outlook.com>
|
||||
Date: Fri, 27 Oct 2023 12:00:21 -0500
|
||||
Subject: [PATCH 4/4] Fixed Typo in docs
|
||||
|
||||
---
|
||||
doc/automatic.rst | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/doc/automatic.rst b/doc/automatic.rst
|
||||
index 2d514b78..4f8eec68 100644
|
||||
--- a/doc/automatic.rst
|
||||
+++ b/doc/automatic.rst
|
||||
@@ -123,7 +123,7 @@ Choosing how the results should be reported.
|
||||
``send_error_messages``
|
||||
boolean, default: False
|
||||
|
||||
- Invokes emitters when an errors occurs
|
||||
+ Invokes emitters when an error occurs.
|
||||
|
||||
---------------------
|
||||
``[command]`` section
|
||||
--
|
||||
2.47.1
|
||||
|
||||
60
SOURCES/0035-automatic-Enhance-errors-reporting.patch
Normal file
60
SOURCES/0035-automatic-Enhance-errors-reporting.patch
Normal file
@ -0,0 +1,60 @@
|
||||
From 2a1046f4dbf855902056e463a9d35612e93f786e Mon Sep 17 00:00:00 2001
|
||||
From: Marek Blaha <mblaha@redhat.com>
|
||||
Date: Mon, 9 Dec 2024 13:42:44 +0100
|
||||
Subject: [PATCH] automatic: Enhance errors reporting
|
||||
|
||||
Emitters must be initialized early to ensure they can report errors that
|
||||
might occur in earlier stages of execution, before transaction
|
||||
resolution. Also a broader range of exceptions must be caught to
|
||||
ensure they are communicated to the user through the configured
|
||||
emitters.
|
||||
For example "No space left on the device" error can be raised during the
|
||||
fill_sack() call. This patch should report it via configured emitters.
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-61882
|
||||
---
|
||||
dnf/automatic/main.py | 9 +++++----
|
||||
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dnf/automatic/main.py b/dnf/automatic/main.py
|
||||
index 0a9d5041..5ca4ad39 100644
|
||||
--- a/dnf/automatic/main.py
|
||||
+++ b/dnf/automatic/main.py
|
||||
@@ -311,11 +311,13 @@ def wait_for_network(repos, timeout):
|
||||
|
||||
def main(args):
|
||||
(opts, parser) = parse_arguments(args)
|
||||
+ conf = None
|
||||
+ emitters = None
|
||||
|
||||
try:
|
||||
conf = AutomaticConfig(opts.conf_path, opts.downloadupdates,
|
||||
opts.installupdates)
|
||||
- emitters = None
|
||||
+ emitters = build_emitters(conf)
|
||||
with dnf.Base() as base:
|
||||
cli = dnf.cli.Cli(base)
|
||||
cli._read_conf_file()
|
||||
@@ -349,7 +351,6 @@ def main(args):
|
||||
return 0
|
||||
|
||||
lst = output.list_transaction(trans, total_width=80)
|
||||
- emitters = build_emitters(conf)
|
||||
emitters.notify_available(lst)
|
||||
if not conf.commands.download_updates:
|
||||
emitters.commit()
|
||||
@@ -378,9 +379,9 @@ def main(args):
|
||||
exit_code = os.waitstatus_to_exitcode(os.system(conf.commands.reboot_command))
|
||||
if exit_code != 0:
|
||||
raise dnf.exceptions.Error('reboot command returned nonzero exit code: %d', exit_code)
|
||||
- except dnf.exceptions.Error as exc:
|
||||
+ except Exception as exc:
|
||||
logger.error(_('Error: %s'), ucd(exc))
|
||||
- if conf.emitters.send_error_messages and emitters != None:
|
||||
+ if conf is not None and conf.emitters.send_error_messages and emitters is not None:
|
||||
emitters.notify_error(_('Error: %s') % str(exc))
|
||||
emitters.commit()
|
||||
return 1
|
||||
--
|
||||
2.47.1
|
||||
|
||||
29
SOURCES/0036-Update-need_reboot-for-dnf-automatic.patch
Normal file
29
SOURCES/0036-Update-need_reboot-for-dnf-automatic.patch
Normal file
@ -0,0 +1,29 @@
|
||||
From ed14b8c8425c6fb6dbade3028ac0118086052b1b Mon Sep 17 00:00:00 2001
|
||||
From: Klaas Demter <Klaas-@users.noreply.github.com>
|
||||
Date: Tue, 15 Oct 2024 11:58:15 +0200
|
||||
Subject: [PATCH] Update need_reboot for dnf-automatic
|
||||
|
||||
The need_reboot from dnf-automatic did not match NEED_REBOOT from
|
||||
needs-restarting.
|
||||
---
|
||||
dnf/base.py | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dnf/base.py b/dnf/base.py
|
||||
index 13222407..168207b5 100644
|
||||
--- a/dnf/base.py
|
||||
+++ b/dnf/base.py
|
||||
@@ -2832,8 +2832,8 @@ class Base(object):
|
||||
|
||||
# List taken from DNF needs-restarting
|
||||
need_reboot = frozenset(('kernel', 'kernel-rt', 'glibc',
|
||||
- 'linux-firmware', 'systemd', 'dbus',
|
||||
- 'dbus-broker', 'dbus-daemon'))
|
||||
+ 'linux-firmware', 'systemd', 'dbus',
|
||||
+ 'dbus-broker', 'dbus-daemon', 'microcode_ctl'))
|
||||
changed_pkgs = self.transaction.install_set | self.transaction.remove_set
|
||||
return any(pkg.name in need_reboot for pkg in changed_pkgs)
|
||||
|
||||
--
|
||||
2.47.1
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
From c57c26e0cf8a3bba061f5ddf619c40f36a94aab9 Mon Sep 17 00:00:00 2001
|
||||
From: Marek Blaha <mblaha@redhat.com>
|
||||
Date: Thu, 12 Dec 2024 08:09:48 +0100
|
||||
Subject: [PATCH] automatic: Fix incorrect Error class instantiation
|
||||
|
||||
dnf.exceptions.Error class constructor accepts only one argument - error
|
||||
message.
|
||||
---
|
||||
dnf/automatic/main.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dnf/automatic/main.py b/dnf/automatic/main.py
|
||||
index 5ca4ad39..51057dfb 100644
|
||||
--- a/dnf/automatic/main.py
|
||||
+++ b/dnf/automatic/main.py
|
||||
@@ -378,7 +378,7 @@ def main(args):
|
||||
(conf.commands.reboot == 'when-needed' and base.reboot_needed())):
|
||||
exit_code = os.waitstatus_to_exitcode(os.system(conf.commands.reboot_command))
|
||||
if exit_code != 0:
|
||||
- raise dnf.exceptions.Error('reboot command returned nonzero exit code: %d', exit_code)
|
||||
+ raise dnf.exceptions.Error('reboot command returned nonzero exit code: %d' % exit_code)
|
||||
except Exception as exc:
|
||||
logger.error(_('Error: %s'), ucd(exc))
|
||||
if conf is not None and conf.emitters.send_error_messages and emitters is not None:
|
||||
--
|
||||
2.47.1
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
From be3f218b6964116bc2948a9b7b93247322dc979f Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
|
||||
Date: Thu, 12 Dec 2024 12:59:03 +0100
|
||||
Subject: [PATCH] doc: `--disableexcludepkgs=all` doesn't affect just file
|
||||
configuration
|
||||
|
||||
The option `--disableexcludepkgs=all` disables all configuration
|
||||
includes and excludes including packages specified on the commandline
|
||||
via `--exclude=`, `-x=`, the deprecated `--excludepkgs=` and file
|
||||
configuration via `--excludepkgs=`, `--includepkgs=`.
|
||||
---
|
||||
doc/command_ref.rst | 9 +++++----
|
||||
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/doc/command_ref.rst b/doc/command_ref.rst
|
||||
index 36817c00..75ded68c 100644
|
||||
--- a/doc/command_ref.rst
|
||||
+++ b/doc/command_ref.rst
|
||||
@@ -165,12 +165,13 @@ Options
|
||||
.. _disableexcludes-label:
|
||||
|
||||
``--disableexcludes=[all|main|<repoid>], --disableexcludepkgs=[all|main|<repoid>]``
|
||||
+ Disable ``excludepkgs`` and ``includepkgs`` configuration options. Takes one of the following three options:
|
||||
|
||||
- Disable the configuration file excludes. Takes one of the following three options:
|
||||
+ * ``all``, disables all ``excludepkgs`` and ``includepkgs`` configurations
|
||||
+ * ``main``, disables ``excludepkgs`` and ``includepkgs`` defined in the ``[main]`` section
|
||||
+ * ``repoid``, disables ``excludepkgs`` and ``includepkgs`` defined for the given repository
|
||||
|
||||
- * ``all``, disables all configuration file excludes
|
||||
- * ``main``, disables excludes defined in the ``[main]`` section
|
||||
- * ``repoid``, disables excludes defined for the given repository
|
||||
+ Note that the \-\ :ref:`-exclude <exclude_option-label>` option appends to the ``[main]`` ``excludepkgs`` configuration and therefore is disabled when ``main`` or ``all`` is specified.
|
||||
|
||||
``--disable, --set-disabled``
|
||||
Disable specified repositories (automatically saves). The option has to be used together with the
|
||||
--
|
||||
2.46.2
|
||||
|
||||
181
SOURCES/0039-Add-support-for-transient.patch
Normal file
181
SOURCES/0039-Add-support-for-transient.patch
Normal file
@ -0,0 +1,181 @@
|
||||
From e236290f4aec12ad9b2e5cdfa48ec8e3172bb89c Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Thu, 7 Nov 2024 02:31:25 +0000
|
||||
Subject: [PATCH 39/44] Add support for --transient
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: 6091f3fccea988208ca417a504569947e4c99263
|
||||
|
||||
Adds support for the --transient option on all transactions. Passing
|
||||
--transient on a bootc system will call `bootc usr-overlay` to create a
|
||||
transient writeable /usr and continue the transaction.
|
||||
|
||||
Specifying --transient on a non-bootc system will throw an error; we
|
||||
don't want to mislead users to thinking this feature works on non-bootc
|
||||
systems.
|
||||
|
||||
If --transient is not specified and the bootc system is in a locked
|
||||
state, the operation will be aborted and a message will be printed
|
||||
suggesting to try again with --transient.
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-70917
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
dnf/cli/cli.py | 40 ++++++++++++++++++++++++++++++---------
|
||||
dnf/cli/option_parser.py | 3 +++
|
||||
dnf/conf/config.py | 2 +-
|
||||
dnf/util.py | 41 +++++++++++++++++++++++++++++-----------
|
||||
4 files changed, 65 insertions(+), 21 deletions(-)
|
||||
|
||||
diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py
|
||||
index 3dc08d616..33fe20aab 100644
|
||||
--- a/dnf/cli/cli.py
|
||||
+++ b/dnf/cli/cli.py
|
||||
@@ -205,28 +205,50 @@ class BaseCli(dnf.Base):
|
||||
else:
|
||||
self.output.reportDownloadSize(install_pkgs, install_only)
|
||||
|
||||
+ bootc_unlock_requested = False
|
||||
+
|
||||
if trans or self._moduleContainer.isChanged() or \
|
||||
(self._history and (self._history.group or self._history.env)):
|
||||
# confirm with user
|
||||
if self.conf.downloadonly:
|
||||
logger.info(_("{prog} will only download packages for the transaction.").format(
|
||||
prog=dnf.util.MAIN_PROG_UPPER))
|
||||
+
|
||||
elif 'test' in self.conf.tsflags:
|
||||
logger.info(_("{prog} will only download packages, install gpg keys, and check the "
|
||||
"transaction.").format(prog=dnf.util.MAIN_PROG_UPPER))
|
||||
- if dnf.util._is_bootc_host() and \
|
||||
- os.path.realpath(self.conf.installroot) == "/" and \
|
||||
- not self.conf.downloadonly:
|
||||
- _bootc_host_msg = _("""
|
||||
-*** Error: system is configured to be read-only; for more
|
||||
-*** information run `bootc --help`.
|
||||
-""")
|
||||
- logger.info(_bootc_host_msg)
|
||||
- raise CliError(_("Operation aborted."))
|
||||
+
|
||||
+ is_bootc_transaction = dnf.util._is_bootc_host() and \
|
||||
+ os.path.realpath(self.conf.installroot) == "/" and \
|
||||
+ not self.conf.downloadonly
|
||||
+
|
||||
+ # Handle bootc transactions. `--transient` must be specified if
|
||||
+ # /usr is not already writeable.
|
||||
+ if is_bootc_transaction:
|
||||
+ if self.conf.persistence == "persist":
|
||||
+ logger.info(_("Persistent transactions aren't supported on bootc systems."))
|
||||
+ raise CliError(_("Operation aborted."))
|
||||
+ assert self.conf.persistence in ("auto", "transient")
|
||||
+ if not dnf.util._is_bootc_unlocked():
|
||||
+ if self.conf.persistence == "auto":
|
||||
+ logger.info(_("This bootc system is configured to be read-only. Pass --transient to "
|
||||
+ "perform this and subsequent transactions in a transient overlay which "
|
||||
+ "will reset when the system reboots."))
|
||||
+ raise CliError(_("Operation aborted."))
|
||||
+ assert self.conf.persistence == "transient"
|
||||
+ logger.info(_("A transient overlay will be created on /usr that will be discarded on reboot. "
|
||||
+ "Keep in mind that changes to /etc and /var will still persist, and packages "
|
||||
+ "commonly modify these directories."))
|
||||
+ bootc_unlock_requested = True
|
||||
+ elif self.conf.persistence == "transient":
|
||||
+ raise CliError(_("Transient transactions are only supported on bootc systems."))
|
||||
|
||||
if self._promptWanted():
|
||||
if self.conf.assumeno or not self.output.userconfirm():
|
||||
raise CliError(_("Operation aborted."))
|
||||
+
|
||||
+ if bootc_unlock_requested:
|
||||
+ dnf.util._bootc_unlock()
|
||||
else:
|
||||
logger.info(_('Nothing to do.'))
|
||||
return
|
||||
diff --git a/dnf/cli/option_parser.py b/dnf/cli/option_parser.py
|
||||
index 41ff16451..66e69cc98 100644
|
||||
--- a/dnf/cli/option_parser.py
|
||||
+++ b/dnf/cli/option_parser.py
|
||||
@@ -320,6 +320,9 @@ class OptionParser(argparse.ArgumentParser):
|
||||
general_grp.add_argument("--downloadonly", dest="downloadonly",
|
||||
action="store_true", default=False,
|
||||
help=_("only download packages"))
|
||||
+ general_grp.add_argument("--transient", dest="persistence",
|
||||
+ action="store_const", const="transient", default=None,
|
||||
+ help=_("Use a transient overlay which will reset on reboot"))
|
||||
general_grp.add_argument("--comment", dest="comment", default=None,
|
||||
help=_("add a comment to transaction"))
|
||||
# Updateinfo options...
|
||||
diff --git a/dnf/conf/config.py b/dnf/conf/config.py
|
||||
index 32516d1a8..ed6daeb2d 100644
|
||||
--- a/dnf/conf/config.py
|
||||
+++ b/dnf/conf/config.py
|
||||
@@ -342,7 +342,7 @@ class MainConf(BaseConfig):
|
||||
'best', 'assumeyes', 'assumeno', 'clean_requirements_on_remove', 'gpgcheck',
|
||||
'showdupesfromrepos', 'plugins', 'ip_resolve',
|
||||
'rpmverbosity', 'disable_excludes', 'color',
|
||||
- 'downloadonly', 'exclude', 'excludepkgs', 'skip_broken',
|
||||
+ 'downloadonly', 'persistence', 'exclude', 'excludepkgs', 'skip_broken',
|
||||
'tsflags', 'arch', 'basearch', 'ignorearch', 'cacheonly', 'comment']
|
||||
|
||||
for name in config_args:
|
||||
diff --git a/dnf/util.py b/dnf/util.py
|
||||
index e8f587a03..f22e3901b 100644
|
||||
--- a/dnf/util.py
|
||||
+++ b/dnf/util.py
|
||||
@@ -38,6 +38,7 @@ import logging
|
||||
import os
|
||||
import pwd
|
||||
import shutil
|
||||
+import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
@@ -634,14 +635,32 @@ def _name_unset_wrapper(input_name):
|
||||
|
||||
|
||||
def _is_bootc_host():
|
||||
- """Returns true is the system is managed as an immutable container,
|
||||
- false otherwise. If msg is True, a warning message is displayed
|
||||
- for the user.
|
||||
- """
|
||||
- ostree_booted = '/run/ostree-booted'
|
||||
- usr = '/usr/'
|
||||
- # Check if usr is writtable and we are in a running ostree system.
|
||||
- # We want this code to return true only when the system is in locked state. If someone ran
|
||||
- # bootc overlay or ostree admin unlock we would want normal DNF path to be ran as it will be
|
||||
- # temporary changes (until reboot).
|
||||
- return os.path.isfile(ostree_booted) and not os.access(usr, os.W_OK)
|
||||
+ """Returns true is the system is managed as an immutable container, false
|
||||
+ otherwise."""
|
||||
+ ostree_booted = "/run/ostree-booted"
|
||||
+ return os.path.isfile(ostree_booted)
|
||||
+
|
||||
+
|
||||
+def _is_bootc_unlocked():
|
||||
+ """Check whether /usr is writeable, e.g. if we are in a normal mutable
|
||||
+ system or if we are in a bootc after `bootc usr-overlay` or `ostree admin
|
||||
+ unlock` was run."""
|
||||
+ usr = "/usr"
|
||||
+ return os.access(usr, os.W_OK)
|
||||
+
|
||||
+
|
||||
+def _bootc_unlock():
|
||||
+ """Set up a writeable overlay on bootc systems."""
|
||||
+
|
||||
+ if _is_bootc_unlocked():
|
||||
+ return
|
||||
+
|
||||
+ unlock_command = ["bootc", "usr-overlay"]
|
||||
+
|
||||
+ try:
|
||||
+ completed_process = subprocess.run(unlock_command, text=True)
|
||||
+ completed_process.check_returncode()
|
||||
+ except FileNotFoundError:
|
||||
+ raise dnf.exceptions.Error(_("bootc command not found. Is this a bootc system?"))
|
||||
+ except subprocess.CalledProcessError:
|
||||
+ raise dnf.exceptions.Error(_("Failed to unlock system: %s", completed_process.stderr))
|
||||
--
|
||||
2.48.1
|
||||
|
||||
74
SOURCES/0040-bootc-Document-transient-and-persistence.patch
Normal file
74
SOURCES/0040-bootc-Document-transient-and-persistence.patch
Normal file
@ -0,0 +1,74 @@
|
||||
From ec5cbd19adc6f384923e95d42357f23696b3c950 Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Tue, 17 Dec 2024 18:58:32 +0000
|
||||
Subject: [PATCH 40/44] bootc: Document `--transient` and `persistence`
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: 80a62d89ba3c00f4e0bd3fea995d04ccf9ba8098
|
||||
|
||||
Documents the new `--transient` command-line argument and `persistence`
|
||||
configuration option. I tried to use a table for listing the valid
|
||||
options for `persistence`, but RST does not automatically wrap table
|
||||
cells containing long lines, so a list was much easier.
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-70917
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
doc/command_ref.rst | 9 +++++++++
|
||||
doc/conf_ref.rst | 11 +++++++++++
|
||||
2 files changed, 20 insertions(+)
|
||||
|
||||
diff --git a/doc/command_ref.rst b/doc/command_ref.rst
|
||||
index 75ded68cd..8b55d5a76 100644
|
||||
--- a/doc/command_ref.rst
|
||||
+++ b/doc/command_ref.rst
|
||||
@@ -389,6 +389,11 @@ Options
|
||||
``--showduplicates``
|
||||
Show duplicate packages in repositories. Applicable for the list and search commands.
|
||||
|
||||
+.. _transient_option-label:
|
||||
+
|
||||
+``--transient``
|
||||
+ Applicable only on bootc (bootable containers) systems. Perform transactions using a transient overlay which will be lost on the next reboot. See also the :ref:`persistence <persistence-label>` configuration option.
|
||||
+
|
||||
.. _verbose_options-label:
|
||||
|
||||
``-v, --verbose``
|
||||
@@ -708,6 +713,10 @@ transactions and act according to this information (assuming the
|
||||
which specifies a transaction by a package which it manipulated. When no
|
||||
transaction is specified, list all known transactions.
|
||||
|
||||
+ Note that transient transactions (see :ref:`--transient
|
||||
+ <transient_option-label>`) will be listed even though they do not make
|
||||
+ persistent changes to files under ``/usr`` or to the RPM database.
|
||||
+
|
||||
The "Action(s)" column lists each type of action taken in the transaction. The possible values are:
|
||||
|
||||
* Install (I): a new package was installed on the system
|
||||
diff --git a/doc/conf_ref.rst b/doc/conf_ref.rst
|
||||
index 42a9a37e5..a34e355b6 100644
|
||||
--- a/doc/conf_ref.rst
|
||||
+++ b/doc/conf_ref.rst
|
||||
@@ -430,6 +430,17 @@ configuration file by your distribution to override the DNF defaults.
|
||||
|
||||
Directory where DNF stores its persistent data between runs. Default is ``"/var/lib/dnf"``.
|
||||
|
||||
+.. _persistence-label:
|
||||
+
|
||||
+``persistence``
|
||||
+ :ref:`string <string-label>`
|
||||
+
|
||||
+ Whether changes should persist across system reboots. Default is ``auto``. Passing :ref:`--transient <transient_option-label>` will override this setting to ``transient``. Valid values are:
|
||||
+
|
||||
+ * ``auto``: Changes will persist across reboots, unless the target is a running bootc system and the system is already in an unlocked state (i.e. ``/usr`` is writable).
|
||||
+ * ``transient``: Changes will be lost on the next reboot. Only applicable on bootc systems. Beware that changes to ``/etc`` and ``/var`` will persist, depending on the configuration of your bootc system. See also https://containers.github.io/bootc/man/bootc-usr-overlay.html.
|
||||
+ * ``persist``: Changes will persist across reboots.
|
||||
+
|
||||
.. _pluginconfpath-label:
|
||||
|
||||
``pluginconfpath``
|
||||
--
|
||||
2.48.1
|
||||
|
||||
@ -0,0 +1,166 @@
|
||||
From 5a5572b8adc335075cdae321ad1447e1b8bd8760 Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Wed, 15 Jan 2025 21:43:58 +0000
|
||||
Subject: [PATCH 41/44] bootc: Use ostree GObject API to get deployment status
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: f3abee56452e40ce475f714666c3a16426759c96
|
||||
|
||||
Using libostree gives us more detail about the current state of the
|
||||
deployment than only checking whether /usr is writable.
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-70917
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
dnf/cli/cli.py | 13 ++++----
|
||||
dnf/util.py | 80 +++++++++++++++++++++++++++++++++++---------------
|
||||
2 files changed, 65 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py
|
||||
index 33fe20aab..e7ca86ba8 100644
|
||||
--- a/dnf/cli/cli.py
|
||||
+++ b/dnf/cli/cli.py
|
||||
@@ -218,18 +218,22 @@ class BaseCli(dnf.Base):
|
||||
logger.info(_("{prog} will only download packages, install gpg keys, and check the "
|
||||
"transaction.").format(prog=dnf.util.MAIN_PROG_UPPER))
|
||||
|
||||
- is_bootc_transaction = dnf.util._is_bootc_host() and \
|
||||
+ is_bootc_transaction = dnf.util._Bootc.is_bootc_host() and \
|
||||
os.path.realpath(self.conf.installroot) == "/" and \
|
||||
not self.conf.downloadonly
|
||||
|
||||
# Handle bootc transactions. `--transient` must be specified if
|
||||
# /usr is not already writeable.
|
||||
+ bootc = None
|
||||
if is_bootc_transaction:
|
||||
if self.conf.persistence == "persist":
|
||||
logger.info(_("Persistent transactions aren't supported on bootc systems."))
|
||||
raise CliError(_("Operation aborted."))
|
||||
assert self.conf.persistence in ("auto", "transient")
|
||||
- if not dnf.util._is_bootc_unlocked():
|
||||
+
|
||||
+ bootc = dnf.util._Bootc()
|
||||
+
|
||||
+ if not bootc.is_unlocked():
|
||||
if self.conf.persistence == "auto":
|
||||
logger.info(_("This bootc system is configured to be read-only. Pass --transient to "
|
||||
"perform this and subsequent transactions in a transient overlay which "
|
||||
@@ -239,7 +243,6 @@ class BaseCli(dnf.Base):
|
||||
logger.info(_("A transient overlay will be created on /usr that will be discarded on reboot. "
|
||||
"Keep in mind that changes to /etc and /var will still persist, and packages "
|
||||
"commonly modify these directories."))
|
||||
- bootc_unlock_requested = True
|
||||
elif self.conf.persistence == "transient":
|
||||
raise CliError(_("Transient transactions are only supported on bootc systems."))
|
||||
|
||||
@@ -247,8 +250,8 @@ class BaseCli(dnf.Base):
|
||||
if self.conf.assumeno or not self.output.userconfirm():
|
||||
raise CliError(_("Operation aborted."))
|
||||
|
||||
- if bootc_unlock_requested:
|
||||
- dnf.util._bootc_unlock()
|
||||
+ if bootc:
|
||||
+ bootc.unlock_and_prepare()
|
||||
else:
|
||||
logger.info(_('Nothing to do.'))
|
||||
return
|
||||
diff --git a/dnf/util.py b/dnf/util.py
|
||||
index f22e3901b..994fddafc 100644
|
||||
--- a/dnf/util.py
|
||||
+++ b/dnf/util.py
|
||||
@@ -634,33 +634,67 @@ def _name_unset_wrapper(input_name):
|
||||
return input_name if input_name else _("<name-unset>")
|
||||
|
||||
|
||||
-def _is_bootc_host():
|
||||
- """Returns true is the system is managed as an immutable container, false
|
||||
- otherwise."""
|
||||
- ostree_booted = "/run/ostree-booted"
|
||||
- return os.path.isfile(ostree_booted)
|
||||
+class _Bootc:
|
||||
+ usr = "/usr"
|
||||
|
||||
+ def __init__(self):
|
||||
+ if not self.is_bootc_host():
|
||||
+ raise RuntimeError(_("Not running on a bootc system."))
|
||||
|
||||
-def _is_bootc_unlocked():
|
||||
- """Check whether /usr is writeable, e.g. if we are in a normal mutable
|
||||
- system or if we are in a bootc after `bootc usr-overlay` or `ostree admin
|
||||
- unlock` was run."""
|
||||
- usr = "/usr"
|
||||
- return os.access(usr, os.W_OK)
|
||||
+ import gi
|
||||
+ self._gi = gi
|
||||
|
||||
+ gi.require_version("OSTree", "1.0")
|
||||
+ from gi.repository import OSTree
|
||||
|
||||
-def _bootc_unlock():
|
||||
- """Set up a writeable overlay on bootc systems."""
|
||||
+ self._OSTree = OSTree
|
||||
|
||||
- if _is_bootc_unlocked():
|
||||
- return
|
||||
+ self._sysroot = self._OSTree.Sysroot.new_default()
|
||||
+ assert self._sysroot.load(None)
|
||||
|
||||
- unlock_command = ["bootc", "usr-overlay"]
|
||||
+ self._booted_deployment = self._sysroot.require_booted_deployment()
|
||||
+ assert self._booted_deployment is not None
|
||||
|
||||
- try:
|
||||
- completed_process = subprocess.run(unlock_command, text=True)
|
||||
- completed_process.check_returncode()
|
||||
- except FileNotFoundError:
|
||||
- raise dnf.exceptions.Error(_("bootc command not found. Is this a bootc system?"))
|
||||
- except subprocess.CalledProcessError:
|
||||
- raise dnf.exceptions.Error(_("Failed to unlock system: %s", completed_process.stderr))
|
||||
+ @staticmethod
|
||||
+ def is_bootc_host():
|
||||
+ """Returns true is the system is managed as an immutable container, false
|
||||
+ otherwise."""
|
||||
+ ostree_booted = "/run/ostree-booted"
|
||||
+ return os.path.isfile(ostree_booted)
|
||||
+
|
||||
+ def _get_unlocked_state(self):
|
||||
+ return self._booted_deployment.get_unlocked()
|
||||
+
|
||||
+ def is_unlocked(self):
|
||||
+ return self._get_unlocked_state() != self._OSTree.DeploymentUnlockedState.NONE
|
||||
+
|
||||
+ def unlock_and_prepare(self):
|
||||
+ """Set up a writeable overlay on bootc systems."""
|
||||
+
|
||||
+ bootc_unlocked_state = self._get_unlocked_state()
|
||||
+
|
||||
+ valid_bootc_unlocked_states = (
|
||||
+ self._OSTree.DeploymentUnlockedState.NONE,
|
||||
+ self._OSTree.DeploymentUnlockedState.DEVELOPMENT,
|
||||
+ # self._OSTree.DeploymentUnlockedState.TRANSIENT,
|
||||
+ # self._OSTree.DeploymentUnlockedState.HOTFIX,
|
||||
+ )
|
||||
+
|
||||
+ if bootc_unlocked_state not in valid_bootc_unlocked_states:
|
||||
+ raise ValueError(_("Unhandled bootc unlocked state: %s") % bootc_unlocked_state.value_nick)
|
||||
+
|
||||
+ if bootc_unlocked_state == self._OSTree.DeploymentUnlockedState.DEVELOPMENT:
|
||||
+ # System is already unlocked.
|
||||
+ pass
|
||||
+ elif bootc_unlocked_state == self._OSTree.DeploymentUnlockedState.NONE:
|
||||
+ unlock_command = ["ostree", "admin", "unlock"]
|
||||
+
|
||||
+ try:
|
||||
+ completed_process = subprocess.run(unlock_command, text=True)
|
||||
+ completed_process.check_returncode()
|
||||
+ except FileNotFoundError:
|
||||
+ raise dnf.exceptions.Error(_("ostree command not found. Is this a bootc system?"))
|
||||
+ except subprocess.CalledProcessError:
|
||||
+ raise dnf.exceptions.Error(_("Failed to unlock system: %s", completed_process.stderr))
|
||||
+
|
||||
+ assert os.access(self.usr, os.W_OK)
|
||||
--
|
||||
2.48.1
|
||||
|
||||
@ -0,0 +1,237 @@
|
||||
From 7e0180ad97a677e6701031f13069c20beec1d8ff Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Thu, 16 Jan 2025 14:06:26 -0500
|
||||
Subject: [PATCH 42/44] bootc: "Re-locking": use ostree admin unlock
|
||||
--transient
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: fa47a256ae7add2ce1c99ae8bedce7216001f396
|
||||
|
||||
To keep /usr read-only after DNF is finished with a transient
|
||||
transaction, we call `ostree admin unlock --transient` to mount the /usr
|
||||
overlay as read-only by default. Then, we create a private mount
|
||||
namespace for DNF and its child processes and remount the /usr overlayfs
|
||||
as read/write in the private mountns.
|
||||
|
||||
os.unshare is unfortunately only available in Python >= 3.12, so we have
|
||||
to call libc.unshare via Python ctypes here and hardcode the CLONE_NEWNS
|
||||
flag that we need to pass.
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-70917
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
dnf/cli/cli.py | 33 ++++++++++---------
|
||||
dnf/util.py | 86 ++++++++++++++++++++++++++++++++++++++------------
|
||||
2 files changed, 83 insertions(+), 36 deletions(-)
|
||||
|
||||
diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py
|
||||
index e7ca86ba8..23170a82b 100644
|
||||
--- a/dnf/cli/cli.py
|
||||
+++ b/dnf/cli/cli.py
|
||||
@@ -205,8 +205,6 @@ class BaseCli(dnf.Base):
|
||||
else:
|
||||
self.output.reportDownloadSize(install_pkgs, install_only)
|
||||
|
||||
- bootc_unlock_requested = False
|
||||
-
|
||||
if trans or self._moduleContainer.isChanged() or \
|
||||
(self._history and (self._history.group or self._history.env)):
|
||||
# confirm with user
|
||||
@@ -218,40 +216,45 @@ class BaseCli(dnf.Base):
|
||||
logger.info(_("{prog} will only download packages, install gpg keys, and check the "
|
||||
"transaction.").format(prog=dnf.util.MAIN_PROG_UPPER))
|
||||
|
||||
- is_bootc_transaction = dnf.util._Bootc.is_bootc_host() and \
|
||||
+ is_bootc_transaction = dnf.util._BootcSystem.is_bootc_system() and \
|
||||
os.path.realpath(self.conf.installroot) == "/" and \
|
||||
not self.conf.downloadonly
|
||||
|
||||
# Handle bootc transactions. `--transient` must be specified if
|
||||
# /usr is not already writeable.
|
||||
- bootc = None
|
||||
+ bootc_system = None
|
||||
if is_bootc_transaction:
|
||||
if self.conf.persistence == "persist":
|
||||
logger.info(_("Persistent transactions aren't supported on bootc systems."))
|
||||
raise CliError(_("Operation aborted."))
|
||||
assert self.conf.persistence in ("auto", "transient")
|
||||
|
||||
- bootc = dnf.util._Bootc()
|
||||
+ bootc_system = dnf.util._BootcSystem()
|
||||
|
||||
- if not bootc.is_unlocked():
|
||||
+ if not bootc_system.is_writable():
|
||||
if self.conf.persistence == "auto":
|
||||
logger.info(_("This bootc system is configured to be read-only. Pass --transient to "
|
||||
- "perform this and subsequent transactions in a transient overlay which "
|
||||
- "will reset when the system reboots."))
|
||||
+ "perform this transaction in a transient overlay which will reset when "
|
||||
+ "the system reboots."))
|
||||
raise CliError(_("Operation aborted."))
|
||||
assert self.conf.persistence == "transient"
|
||||
- logger.info(_("A transient overlay will be created on /usr that will be discarded on reboot. "
|
||||
- "Keep in mind that changes to /etc and /var will still persist, and packages "
|
||||
- "commonly modify these directories."))
|
||||
- elif self.conf.persistence == "transient":
|
||||
- raise CliError(_("Transient transactions are only supported on bootc systems."))
|
||||
+ if not bootc_system.is_unlocked_transient():
|
||||
+ # Only tell the user about the transient overlay if
|
||||
+ # it's not already in place
|
||||
+ logger.info(_("A transient overlay will be created on /usr that will be discarded on reboot. "
|
||||
+ "Keep in mind that changes to /etc and /var will still persist, and packages "
|
||||
+ "commonly modify these directories."))
|
||||
+ else:
|
||||
+ # Not a bootc transaction.
|
||||
+ if self.conf.persistence == "transient":
|
||||
+ raise CliError(_("Transient transactions are only supported on bootc systems."))
|
||||
|
||||
if self._promptWanted():
|
||||
if self.conf.assumeno or not self.output.userconfirm():
|
||||
raise CliError(_("Operation aborted."))
|
||||
|
||||
- if bootc:
|
||||
- bootc.unlock_and_prepare()
|
||||
+ if bootc_system:
|
||||
+ bootc_system.make_writable()
|
||||
else:
|
||||
logger.info(_('Nothing to do.'))
|
||||
return
|
||||
diff --git a/dnf/util.py b/dnf/util.py
|
||||
index 994fddafc..0161f80d8 100644
|
||||
--- a/dnf/util.py
|
||||
+++ b/dnf/util.py
|
||||
@@ -25,6 +25,7 @@ from __future__ import unicode_literals
|
||||
from .pycomp import PY3, basestring
|
||||
from dnf.i18n import _, ucd
|
||||
import argparse
|
||||
+import ctypes
|
||||
import dnf
|
||||
import dnf.callback
|
||||
import dnf.const
|
||||
@@ -634,11 +635,12 @@ def _name_unset_wrapper(input_name):
|
||||
return input_name if input_name else _("<name-unset>")
|
||||
|
||||
|
||||
-class _Bootc:
|
||||
+class _BootcSystem:
|
||||
usr = "/usr"
|
||||
+ CLONE_NEWNS = 0x00020000 # defined in linux/include/uapi/linux/sched.h
|
||||
|
||||
def __init__(self):
|
||||
- if not self.is_bootc_host():
|
||||
+ if not self.is_bootc_system():
|
||||
raise RuntimeError(_("Not running on a bootc system."))
|
||||
|
||||
import gi
|
||||
@@ -656,45 +658,87 @@ class _Bootc:
|
||||
assert self._booted_deployment is not None
|
||||
|
||||
@staticmethod
|
||||
- def is_bootc_host():
|
||||
+ def is_bootc_system():
|
||||
"""Returns true is the system is managed as an immutable container, false
|
||||
otherwise."""
|
||||
ostree_booted = "/run/ostree-booted"
|
||||
return os.path.isfile(ostree_booted)
|
||||
|
||||
+ @classmethod
|
||||
+ def is_writable(cls):
|
||||
+ """Returns true if and only if /usr is writable."""
|
||||
+ return os.access(cls.usr, os.W_OK)
|
||||
+
|
||||
def _get_unlocked_state(self):
|
||||
return self._booted_deployment.get_unlocked()
|
||||
|
||||
- def is_unlocked(self):
|
||||
- return self._get_unlocked_state() != self._OSTree.DeploymentUnlockedState.NONE
|
||||
+ def is_unlocked_transient(self):
|
||||
+ """Returns true if and only if the bootc system is unlocked in a
|
||||
+ transient state, i.e. a overlayfs is mounted as read-only on /usr.
|
||||
+ Changes can be made to the overlayfs by remounting /usr as
|
||||
+ read/write in a private mount namespace."""
|
||||
+ return self._get_unlocked_state() == self._OSTree.DeploymentUnlockedState.TRANSIENT
|
||||
+
|
||||
+ @classmethod
|
||||
+ def _set_up_mountns(cls):
|
||||
+ # os.unshare is only available in Python >= 3.12.
|
||||
+
|
||||
+ # Access symbols in libraries loaded by the Python interpreter,
|
||||
+ # which will include libc. See https://bugs.python.org/issue34592.
|
||||
+ libc = ctypes.CDLL(None)
|
||||
+ if libc.unshare(cls.CLONE_NEWNS) != 0:
|
||||
+ raise OSError("Failed to unshare mount namespace")
|
||||
+
|
||||
+ mount_command = ["mount", "--options-source=disable", "-o", "remount,rw", cls.usr]
|
||||
+ try:
|
||||
+ completed_process = subprocess.run(mount_command, text=True)
|
||||
+ completed_process.check_returncode()
|
||||
+ except FileNotFoundError:
|
||||
+ raise dnf.exceptions.Error(_("%s: command not found.") % mount_command[0])
|
||||
+ except subprocess.CalledProcessError:
|
||||
+ raise dnf.exceptions.Error(_("Failed to mount %s as read/write: %s", cls.usr, completed_process.stderr))
|
||||
|
||||
- def unlock_and_prepare(self):
|
||||
- """Set up a writeable overlay on bootc systems."""
|
||||
+ @staticmethod
|
||||
+ def _unlock():
|
||||
+ unlock_command = ["ostree", "admin", "unlock", "--transient"]
|
||||
+ try:
|
||||
+ completed_process = subprocess.run(unlock_command, text=True)
|
||||
+ completed_process.check_returncode()
|
||||
+ except FileNotFoundError:
|
||||
+ raise dnf.exceptions.Error(_("%s: command not found. Is this a bootc system?") % unlock_command[0])
|
||||
+ except subprocess.CalledProcessError:
|
||||
+ raise dnf.exceptions.Error(_("Failed to unlock system: %s", completed_process.stderr))
|
||||
+
|
||||
+ def make_writable(self):
|
||||
+ """Set up a writable overlay on bootc systems."""
|
||||
|
||||
bootc_unlocked_state = self._get_unlocked_state()
|
||||
|
||||
valid_bootc_unlocked_states = (
|
||||
self._OSTree.DeploymentUnlockedState.NONE,
|
||||
self._OSTree.DeploymentUnlockedState.DEVELOPMENT,
|
||||
- # self._OSTree.DeploymentUnlockedState.TRANSIENT,
|
||||
- # self._OSTree.DeploymentUnlockedState.HOTFIX,
|
||||
+ self._OSTree.DeploymentUnlockedState.TRANSIENT,
|
||||
+ self._OSTree.DeploymentUnlockedState.HOTFIX,
|
||||
)
|
||||
-
|
||||
if bootc_unlocked_state not in valid_bootc_unlocked_states:
|
||||
raise ValueError(_("Unhandled bootc unlocked state: %s") % bootc_unlocked_state.value_nick)
|
||||
|
||||
- if bootc_unlocked_state == self._OSTree.DeploymentUnlockedState.DEVELOPMENT:
|
||||
- # System is already unlocked.
|
||||
+ writable_unlocked_states = (
|
||||
+ self._OSTree.DeploymentUnlockedState.DEVELOPMENT,
|
||||
+ self._OSTree.DeploymentUnlockedState.HOTFIX,
|
||||
+ )
|
||||
+ if bootc_unlocked_state in writable_unlocked_states:
|
||||
+ # System is already unlocked in development mode, and usr is
|
||||
+ # already mounted read/write.
|
||||
pass
|
||||
elif bootc_unlocked_state == self._OSTree.DeploymentUnlockedState.NONE:
|
||||
- unlock_command = ["ostree", "admin", "unlock"]
|
||||
-
|
||||
- try:
|
||||
- completed_process = subprocess.run(unlock_command, text=True)
|
||||
- completed_process.check_returncode()
|
||||
- except FileNotFoundError:
|
||||
- raise dnf.exceptions.Error(_("ostree command not found. Is this a bootc system?"))
|
||||
- except subprocess.CalledProcessError:
|
||||
- raise dnf.exceptions.Error(_("Failed to unlock system: %s", completed_process.stderr))
|
||||
+ # System is not unlocked. Unlock it in transient mode, then set up
|
||||
+ # a mount namespace for DNF.
|
||||
+ self._unlock()
|
||||
+ self._set_up_mountns()
|
||||
+ elif bootc_unlocked_state == self._OSTree.DeploymentUnlockedState.TRANSIENT:
|
||||
+ # System is unlocked in transient mode, so usr is mounted
|
||||
+ # read-only. Set up a mount namespace for DNF.
|
||||
+ self._set_up_mountns()
|
||||
|
||||
assert os.access(self.usr, os.W_OK)
|
||||
--
|
||||
2.48.1
|
||||
|
||||
56
SOURCES/0043-spec-Add-dnf-bootc-subpackage.patch
Normal file
56
SOURCES/0043-spec-Add-dnf-bootc-subpackage.patch
Normal file
@ -0,0 +1,56 @@
|
||||
From 9c2a1a6a36d748d059140bf6ee9113d5e9641477 Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Tue, 28 Jan 2025 11:27:00 -0500
|
||||
Subject: [PATCH 43/44] spec: Add dnf-bootc subpackage
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: 76a0c339eb172b1b2a4b1aa8b4db8d6a5145916b
|
||||
|
||||
dnf-bootc's only job is to Require python3-gobject-base, ostree,
|
||||
ostree-libs, and util-linux-core, which are needed to interact with
|
||||
bootc systems. We don't want to add these dependencies on `python3-dnf`
|
||||
because we don't want them on non-bootc systems, so we use a subpackage.
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-70917
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
dnf.spec | 14 ++++++++++++++
|
||||
1 file changed, 14 insertions(+)
|
||||
|
||||
diff --git a/dnf.spec b/dnf.spec
|
||||
index e9abd9041..b60f2692b 100644
|
||||
--- a/dnf.spec
|
||||
+++ b/dnf.spec
|
||||
@@ -180,6 +180,17 @@ Requires: %{name} = %{version}-%{release}
|
||||
%description automatic
|
||||
Systemd units that can periodically download package upgrades and apply them.
|
||||
|
||||
+%package bootc
|
||||
+Summary: %{pkg_summary} - additional bootc dependencies
|
||||
+Requires: python3-%{name} = %{version}-%{release}
|
||||
+Requires: ostree
|
||||
+Requires: ostree-libs
|
||||
+Requires: python3-gobject-base
|
||||
+Requires: util-linux-core
|
||||
+
|
||||
+%description bootc
|
||||
+Additional dependencies needed to perform transactions on booted bootc (bootable containers) systems.
|
||||
+
|
||||
|
||||
%prep
|
||||
%autosetup
|
||||
@@ -358,6 +369,9 @@ popd
|
||||
%{_unitdir}/%{name}-automatic-install.timer
|
||||
%{python3_sitelib}/%{name}/automatic/
|
||||
|
||||
+%files bootc
|
||||
+# bootc subpackage does not include any files
|
||||
+
|
||||
%changelog
|
||||
* Fri Sep 09 2022 Jaroslav Rohel <jrohel@redhat.com> - 4.14.0-1
|
||||
- doc: Describe how gpg keys are stored for `repo_ggpcheck` (RhBug:2020678)
|
||||
--
|
||||
2.48.1
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
From 19754a7c80e1c2232c370f394ad0d36f5713bf1e Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Wed, 5 Feb 2025 10:35:08 -0500
|
||||
Subject: [PATCH 44/44] Require libdnf >= 0.74.0 with `persistence` option
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Upstream commit: 5a4f6c42e61ed764ff85eea69125947a280d665d
|
||||
|
||||
This backport actually uses RHEL-9 libdnf version.
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-70917
|
||||
Signed-off-by: Petr Písař <ppisar@redhat.com>
|
||||
---
|
||||
dnf.spec | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dnf.spec b/dnf.spec
|
||||
index b60f2692b..313a3cb2a 100644
|
||||
--- a/dnf.spec
|
||||
+++ b/dnf.spec
|
||||
@@ -2,7 +2,7 @@
|
||||
%define __cmake_in_source_build 1
|
||||
|
||||
# default dependencies
|
||||
-%global hawkey_version 0.66.0
|
||||
+%global hawkey_version 0.74.0
|
||||
%global libcomps_version 0.1.8
|
||||
%global libmodulemd_version 2.9.3
|
||||
%global rpm_version 4.14.0
|
||||
@@ -21,6 +21,10 @@
|
||||
%global rpm_version 4.11.3-25.el7.centos.1
|
||||
%endif
|
||||
|
||||
+%if 0%{?rhel} == 9
|
||||
+ %global hawkey_version 0.69.0-13
|
||||
+%endif
|
||||
+
|
||||
# override dependencies for fedora 26
|
||||
%if 0%{?fedora} == 26
|
||||
%global rpm_version 4.13.0.1-7
|
||||
--
|
||||
2.48.1
|
||||
|
||||
120
SPECS/dnf.spec
120
SPECS/dnf.spec
@ -2,7 +2,7 @@
|
||||
%define __cmake_in_source_build 1
|
||||
|
||||
# default dependencies
|
||||
%global hawkey_version 0.66.0
|
||||
%global hawkey_version 0.74.0
|
||||
%global libcomps_version 0.1.8
|
||||
%global libmodulemd_version 2.9.3
|
||||
%global rpm_version 4.14.0
|
||||
@ -21,6 +21,10 @@
|
||||
%global rpm_version 4.11.3-25.el7.centos.1
|
||||
%endif
|
||||
|
||||
%if 0%{?rhel} == 9
|
||||
%global hawkey_version 0.69.0-13
|
||||
%endif
|
||||
|
||||
# override dependencies for fedora 26
|
||||
%if 0%{?fedora} == 26
|
||||
%global rpm_version 4.13.0.1-7
|
||||
@ -69,7 +73,7 @@ It supports RPMs, modules and comps groups & environments.
|
||||
|
||||
Name: dnf
|
||||
Version: 4.14.0
|
||||
Release: 9%{?dist}.alma.1
|
||||
Release: 25%{?dist}.alma.1
|
||||
Summary: %{pkg_summary}
|
||||
# For a breakdown of the licensing, see PACKAGE-LICENSING
|
||||
License: GPLv2+
|
||||
@ -89,9 +93,39 @@ Patch11: 0011-Document-symbols-in-dnf-history-list-output.patch
|
||||
Patch12: 0012-RHEL-11345-Fix-japanese-translations.patch
|
||||
Patch13: 0013-RHEL-6396-Fix-substitution-in-kvp-in-add_new_repo.patch
|
||||
Patch14: 0014-RHEL-6304-base-Add-obsoleters-of-only-latest-versions.patch
|
||||
Patch15: 0015-Add-all-candidates-for-reinstall-to-solver.patch
|
||||
Patch16: 0016-Fix-handling-installonly-packages-reasons.patch
|
||||
Patch17: 0017-Remove-confusing-sentence-from-documentation.patch
|
||||
Patch18: 0018-Remove-leaf-word-from-documentation.patch
|
||||
Patch19: 0019-Update-documentation-of-history-userinstalled-comman.patch
|
||||
Patch20: 0020-automatic-Use-add_security_filters-not-_update_secur.patch
|
||||
Patch21: 0021-remove-duplicates-when-no-duplicates-exit-with-0-RHE.patch
|
||||
Patch22: 0022-remove-oldinstallonly-when-no-old-installonly-packag.patch
|
||||
Patch23: 0023-Limit-queries-to-nevra-forms-when-provided-by-comman.patch
|
||||
Patch24: 0024-doc-Remove-provide-of-spec-definition-for-repoquery-.patch
|
||||
Patch25: 0025-man-Improve-upgrade-minimal-command-docs-RHEL-6417.patch
|
||||
Patch26: 0026-doc-Makecache-with-timer-tries-only-one-mirror.patch
|
||||
Patch27: 0027-Add-detection-for-ostree-based-systems-and-warn-user.patch
|
||||
Patch28: 0028-Update-ostree-bootc-host-system-check.patch
|
||||
Patch29: 0029-Update-bootc-hosts-message-to-point-to-bootc-help.patch
|
||||
Patch30: 0030-Allow-installroot-on-read-only-bootc-system.patch
|
||||
Patch31: 0031-smtplib-catch-OSError-not-SMTPException.patch
|
||||
Patch32: 0032-Allow-downloadonly-on-read-only-bootc-system.patch
|
||||
Patch33: 0033-automatic-Check-availability-of-config-file.patch
|
||||
Patch34: 0034-automatic-emitters-send-error-messages.patch
|
||||
Patch35: 0035-automatic-Enhance-errors-reporting.patch
|
||||
Patch36: 0036-Update-need_reboot-for-dnf-automatic.patch
|
||||
Patch37: 0037-automatic-Fix-incorrect-Error-class-instantiation.patch
|
||||
PAtch38: 0038-doc-disableexcludepkgs-all-doesn-t-affect-just-file.patch
|
||||
Patch39: 0039-Add-support-for-transient.patch
|
||||
Patch40: 0040-bootc-Document-transient-and-persistence.patch
|
||||
Patch41: 0041-bootc-Use-ostree-GObject-API-to-get-deployment-statu.patch
|
||||
Patch42: 0042-bootc-Re-locking-use-ostree-admin-unlock-transient.patch
|
||||
Patch43: 0043-spec-Add-dnf-bootc-subpackage.patch
|
||||
Patch44: 0044-Require-libdnf-0.74.0-with-persistence-option.patch
|
||||
|
||||
#Almalinux patches
|
||||
Patch10000: almalinux_bugtracker.patch
|
||||
# AlmaLinux Patch
|
||||
Patch10000: almalinux_bugtracker.patch
|
||||
|
||||
BuildArch: noarch
|
||||
BuildRequires: cmake
|
||||
@ -201,6 +235,17 @@ Requires: %{name} = %{version}-%{release}
|
||||
%description automatic
|
||||
Systemd units that can periodically download package upgrades and apply them.
|
||||
|
||||
%package bootc
|
||||
Summary: %{pkg_summary} - additional bootc dependencies
|
||||
Requires: python3-%{name} = %{version}-%{release}
|
||||
Requires: ostree
|
||||
Requires: ostree-libs
|
||||
Requires: python3-gobject-base
|
||||
Requires: util-linux-core
|
||||
|
||||
%description bootc
|
||||
Additional dependencies needed to perform transactions on booted bootc (bootable containers) systems.
|
||||
|
||||
|
||||
%prep
|
||||
%autosetup -p1
|
||||
@ -379,14 +424,79 @@ popd
|
||||
%{_unitdir}/%{name}-automatic-install.timer
|
||||
%{python3_sitelib}/%{name}/automatic/
|
||||
|
||||
%files bootc
|
||||
# bootc subpackage does not include any files
|
||||
|
||||
%changelog
|
||||
* Thu Mar 28 2024 Eduard Abdullin <eabdullin@almalinux.org> - 4.14.0-9.alma.1
|
||||
* Tue May 13 2025 Eduard Abdullin <eabdullin@almalinux.org> - 4.14.0-25.alma.1
|
||||
- Added patch for almalinux bugtracker
|
||||
|
||||
* Tue Feb 04 2025 Petr Pisar <ppisar@redhat.com> - 4.14.0-25
|
||||
- Add support for transient transactions (RHEL-70917)
|
||||
|
||||
* Mon Jan 13 2025 Ales Matej <amatej@redhat.com> - 4.14.0-24
|
||||
- doc: `--disableexcludepkgs=all` doesn't affect just file configuration
|
||||
(RHEL-28779)
|
||||
|
||||
* Thu Dec 12 2024 Marek Blaha <mblaha@redhat.com> - 4.14.0-23
|
||||
- automatic: Update need_reboot to match needs-restarting (RHEL-62830)
|
||||
|
||||
* Wed Dec 11 2024 Marek Blaha <mblaha@redhat.com> - 4.14.0-22
|
||||
- automatic: Added feature to allow emitters to invoke on dnf error
|
||||
(RHEL-45505, RHEL-61882)
|
||||
|
||||
* Mon Oct 21 2024 Marek Blaha <mblaha@redhat.com> - 4.14.0-21
|
||||
- automatic: Check availability of config file (RHEL-49743)
|
||||
|
||||
* Thu Oct 10 2024 Petr Pisar <ppisar@redhat.com> - 4.14.0-20
|
||||
- Allow "dnf install --downloadonly" on locked OSTree and bootc systems
|
||||
(RHEL-61745)
|
||||
|
||||
* Mon Oct 07 2024 Marek Blaha <mblaha@redhat.com> - 4.14.0-19
|
||||
- Catch more specific OSError instead of SMTPException in dnf-automatic email
|
||||
emitter (RHEL-49743)
|
||||
|
||||
* Tue Oct 01 2024 Petr Pisar <ppisar@redhat.com> - 4.14.0-18
|
||||
- More specific error message on a locked OSTree system or a bootc system
|
||||
without a usr-overlay (RHEL-49670)
|
||||
|
||||
* Tue Aug 06 2024 Petr Pisar <ppisar@redhat.com> - 4.14.0-17
|
||||
- Revert more specific error message on a locked OSTree system or a bootc system
|
||||
without a usr-overlay (RHEL-49670)
|
||||
|
||||
* Wed Jul 24 2024 Petr Pisar <ppisar@redhat.com> - 4.14.0-16
|
||||
- More specific error message on a locked OSTree system or a bootc system
|
||||
without a usr-overlay (RHEL-49670)
|
||||
|
||||
* Wed Jun 12 2024 Petr Pisar <ppisar@redhat.com> - 4.14.0-15
|
||||
- Document that "dnf makecache --timer" exits on a first failed mirror
|
||||
(RHEL-1342)
|
||||
|
||||
* Mon Jun 03 2024 Petr Pisar <ppisar@redhat.com> - 4.14.0-14
|
||||
- Fix dnf upgrade-minimal documentation in dnf(8) manual (RHEL-6417)
|
||||
|
||||
* Thu May 23 2024 Petr Pisar <ppisar@redhat.com> - 4.14.0-13
|
||||
- Fix dnf remove-n, install-n, and autoremove-n commands to only match package
|
||||
names (RHEL-38470)
|
||||
|
||||
* Tue May 21 2024 Petr Pisar <ppisar@redhat.com> - 4.14.0-12
|
||||
- Fix reporting nothing-to-do for "dnf remove --duplicates" (RHEL-6424)
|
||||
- Fix reporting nothing-to-do for "dnf remove --oldinstallonly" (RHEL-6424)
|
||||
|
||||
* Mon May 06 2024 Petr Pisar <ppisar@redhat.com> - 4.14.0-11
|
||||
- Fix handling an installation reason of install-only packages on autoremove
|
||||
(RHEL-15902)
|
||||
- Fix dnf-automatic service to apply security updates the same way as dnf tool
|
||||
(RHEL-21874)
|
||||
|
||||
* Tue Apr 23 2024 Petr Pisar <ppisar@redhat.com> - 4.14.0-10
|
||||
- Fix preferring the lowest-cost repositories on a reinstallation (RHEL-25005)
|
||||
|
||||
* Wed Oct 25 2023 Jaroslav Rohel <jrohel@redhat.com> - 4.14.0-9
|
||||
- Fix japanese translations (RHEL-11345)
|
||||
- Fix substitution in kay-value-pair list in add_new_repo (RHEL-6396)
|
||||
- base: Add obsoleters of only latest versions (RHEL-6304)
|
||||
|
||||
* Wed Jun 28 2023 Jaroslav Rohel <jrohel@redhat.com> - 4.14.0-8
|
||||
- Return an error when transaction fails (RhBug:2170093,2212262)
|
||||
- Document symbols in `dnf history list` output (RhBug:2172067,2218113)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user