Compare commits
No commits in common. "c8" and "c9-beta" have entirely different histories.
.dnf.metadata.gitignore
SOURCES
0001-Pass-whole-URL-in-relativeUrl-to-PackageTarget-for-R.patch0001-Set-top-level-directory-for-unittest.patch0002-Document-changes-to-offline-upgrade-command-RhBug-19.patch0002-dnf-rpm-miscutils.py-fix-usage-of-_.patch0003-Move-system-upgrade-plugin-to-core-RhBug-2054235.patch0003-Pass-the-package-to-rpmkeys-stdin.patch0004-Fix-plugins-unit-tests.patch0004-Use-rpmkeys-alone-to-verify-signature.patch0005-Ignore-processing-variable-files-with-unsupported-en.patch0005-Lower-_pkgverify_level-to-signature-for-signature-ch.patch0006-Update-translations.patch0006-add-default-colors-to-documentation.patch0007-Add-reboot-option-to-DNF-Automatic.patch0007-add-author.patch0008-Omit-src-RPMs-from-check-update-RhBug-2151910.patch0008-update-colors-according-to-libdnf-libdnf-conf-Config.patch0009-Fix-reporting-irrecoverable-errors-on-packages-downl.patch0009-automatic-Fix-online-detection-with-proxy-RhBz2022440.patch0010-Add-fail_fast-parameter-to-download_payloads-methods.patch0010-automatic-Return-an-error-when-transaction-fails-RhB.patch0011-Document-symbols-in-dnf-history-list-output.patch0011-comps-Make-the-install_or_skip-method-not-catch-Comp.patch0012-RHEL-11345-Fix-japanese-translations.patch0012-doc-Improve-description-of-multilib_policy-all-RhBug.patch0013-Fix-Python-dnf-API-does-not-respect-cacheonly-RhBug-.patch0013-RHEL-6396-Fix-substitution-in-kvp-in-add_new_repo.patch0014-Documentation-API-notes-for-cacheonly.patch0014-RHEL-6304-base-Add-obsoleters-of-only-latest-versions.patch0015-Add-all-candidates-for-reinstall-to-solver.patch0015-Allow-destdir-option-with-modulesync-command.patch0016-Fix-handling-installonly-packages-reasons.patch0016-Update-translations-RhBug-2017270.patch0017-Add-documentation-for-query-api-flags.patch0017-Remove-confusing-sentence-from-documentation.patch0018-Fix-processing-of-download-errors-RhBug-2024527.patch0018-Remove-leaf-word-from-documentation.patch0019-Fix-unittests-that-relied-on-checksum-being-at-the-e.patch0019-Update-documentation-of-history-userinstalled-comman.patch0020-automatic-Use-add_security_filters-not-_update_secur.patch0020-cli-commands-history-Fix-history-undo-on-a-Reason-Ch.patch0021-Fix-remove-when-no-repos-are-enabled-RhBz-2064341.patch0021-remove-duplicates-when-no-duplicates-exit-with-0-RHE.patch0022-doc-Improve-proxy-configuration-option-documentation.patch0022-remove-oldinstallonly-when-no-old-installonly-packag.patch0023-Base.reset-plug-temporary-leak-of-libsolv-s-page-fil.patch0023-Limit-queries-to-nevra-forms-when-provided-by-comman.patch0024-doc-Describe-how-gpg-keys-are-stored-for-repo_ggpche.patch0024-doc-Remove-provide-of-spec-definition-for-repoquery-.patch0025-Add-only-relevant-pkgs-to-upgrade-transaction-RhBug-.patch0025-man-Improve-upgrade-minimal-command-docs-RHEL-6417.patch0026-Use-installed_all-because-installed_query-is-filtere.patch0026-doc-Makecache-with-timer-tries-only-one-mirror.patch0027-Add-detection-for-ostree-based-systems-and-warn-user.patch0027-Don-t-include-resolved-advisories-for-obsoletes-with.patch0028-Set-default-value-for-variable-to-prevent-crash-RhBu.patch0028-Update-ostree-bootc-host-system-check.patch0029-Add-doc-related-to-destdir-and-downloadonly-options-.patch0029-Update-bootc-hosts-message-to-point-to-bootc-help.patch0030-Allow-installroot-on-read-only-bootc-system.patch0030-Expose-plugin-unload-method-to-API-RhBug-2047251.patch0031-Add-support-for-group-upgrade-rollback-RhBug-2016070.patch0031-smtplib-catch-OSError-not-SMTPException.patch0032-Allow-downloadonly-on-read-only-bootc-system.patch0032-Fix-upgrade-from-file-to-noarch-pkg-RhBug-2006018.patch0033-Allow-passing-plugin-parameters-with-dashes-in-names.patch0033-automatic-Check-availability-of-config-file.patch0034-automatic-emitters-send-error-messages.patch0035-automatic-Enhance-errors-reporting.patch0036-Add-support-for-rollback-of-group-upgrade-rollback-R.patch0036-Update-need_reboot-for-dnf-automatic.patch0037-automatic-Fix-incorrect-Error-class-instantiation.patch0038-Better-explain-traceback-of-rpm.error-with-dnf.patch0038-doc-disableexcludepkgs-all-doesn-t-affect-just-file.patch0039-Add-support-for-transient.patch0040-Update-translations.patch0040-bootc-Document-transient-and-persistence.patch0041-bootc-Use-ostree-GObject-API-to-get-deployment-statu.patch0042-bootc-Re-locking-use-ostree-admin-unlock-transient.patch0043-spec-Add-dnf-bootc-subpackage.patch0044-Require-libdnf-0.74.0-with-persistence-option.patch0045-RHEL-1245-Remove-usrbin-from-syspath-noimpor-garbage.patch0050-Fix-missing-import-in-automatic.patch
SPECS
@ -1 +1 @@
|
||||
f9c31cf46094c4bbf021e1872a9eb72d8a3f2136 SOURCES/dnf-4.7.0.tar.gz
|
||||
0697aee277730c57446b5b87bdb12456cf245203 SOURCES/dnf-4.14.0.tar.gz
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
||||
SOURCES/dnf-4.7.0.tar.gz
|
||||
SOURCES/dnf-4.14.0.tar.gz
|
||||
|
@ -0,0 +1,62 @@
|
||||
From 5e082d74b73bf1b3565cfd72a3e1ba7a45a00a8b Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hr=C3=A1zk=C3=BD?= <lhrazky@redhat.com>
|
||||
Date: Wed, 7 Sep 2022 14:40:32 +0200
|
||||
Subject: [PATCH 1/2] Pass whole URL in relativeUrl to PackageTarget for RPM
|
||||
URL download
|
||||
|
||||
The PackageTarget supports baseUrl and relativeUrl on the API, but then
|
||||
the relativeUrl is just a path fragment with no definition on whether it
|
||||
should be encoded. It's being passed unencoded paths from other places,
|
||||
and so there's a conditional encode (only if not full URL) in libdnf.
|
||||
|
||||
But full URLs are actually supported in relativeUrl (in that case
|
||||
baseUrl should be empty) and in that case the URL is expected to be
|
||||
encoded and is not encoded for the second time.
|
||||
|
||||
Hence, pass the full URL to relativeUrl instead of splitting it. We also
|
||||
need to decode the file name we store, as on the filesystem the RPM file
|
||||
name is also decoded.
|
||||
|
||||
= changelog =
|
||||
msg: Don't double-encode RPM URLs passed on CLI
|
||||
type: bugfix
|
||||
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2103015
|
||||
---
|
||||
dnf/repo.py | 7 ++++---
|
||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dnf/repo.py b/dnf/repo.py
|
||||
index ec1a2537..86fb2bf4 100644
|
||||
--- a/dnf/repo.py
|
||||
+++ b/dnf/repo.py
|
||||
@@ -47,6 +47,7 @@ import string
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
+import urllib
|
||||
|
||||
_PACKAGES_RELATIVE_DIR = "packages"
|
||||
_MIRRORLIST_FILENAME = "mirrorlist"
|
||||
@@ -295,7 +296,7 @@ class RemoteRPMPayload(PackagePayload):
|
||||
self.local_path = os.path.join(self.pkgdir, self.__str__().lstrip("/"))
|
||||
|
||||
def __str__(self):
|
||||
- return os.path.basename(self.remote_location)
|
||||
+ return os.path.basename(urllib.parse.unquote(self.remote_location))
|
||||
|
||||
def _progress_cb(self, cbdata, total, done):
|
||||
self.remote_size = total
|
||||
@@ -308,8 +309,8 @@ class RemoteRPMPayload(PackagePayload):
|
||||
|
||||
def _librepo_target(self):
|
||||
return libdnf.repo.PackageTarget(
|
||||
- self.conf._config, os.path.basename(self.remote_location),
|
||||
- self.pkgdir, 0, None, 0, os.path.dirname(self.remote_location),
|
||||
+ self.conf._config, self.remote_location,
|
||||
+ self.pkgdir, 0, None, 0, None,
|
||||
True, 0, 0, self.callbacks)
|
||||
|
||||
@property
|
||||
--
|
||||
2.37.3
|
||||
|
@ -1,26 +0,0 @@
|
||||
From 423c987b6b14ec0a6277181ac7c038b50033296d Mon Sep 17 00:00:00 2001
|
||||
From: Pavla Kratochvilova <pkratoch@redhat.com>
|
||||
Date: Wed, 19 May 2021 12:58:30 +0200
|
||||
Subject: [PATCH] Set top-level directory for unittest
|
||||
|
||||
In some build environments, the top-level directory is not added to
|
||||
the sys.path and the tests fail. This fixes the issue.
|
||||
---
|
||||
tests/CMakeLists.txt | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
|
||||
index b15cc62b..dedc46fd 100644
|
||||
--- a/tests/CMakeLists.txt
|
||||
+++ b/tests/CMakeLists.txt
|
||||
@@ -1,6 +1,6 @@
|
||||
ADD_TEST(
|
||||
NAME test
|
||||
- COMMAND ${PYTHON_EXECUTABLE} -m unittest discover -s tests
|
||||
+ COMMAND ${PYTHON_EXECUTABLE} -m unittest discover -s tests -t ${PROJECT_SOURCE_DIR}
|
||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
|
||||
|
||||
# For libdnf built with sanitizers, has no effect otherwise.
|
||||
--
|
||||
2.35.1
|
||||
|
@ -1,7 +1,8 @@
|
||||
From 97fe94c94f030f5596a3a3ac52748bdd7544ad52 Mon Sep 17 00:00:00 2001
|
||||
From a41c3aefaa4f982511363645f5608e270094cadf Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kolarik <jkolarik@redhat.com>
|
||||
Date: Tue, 1 Nov 2022 09:15:08 +0000
|
||||
Subject: [PATCH] Document changes to offline-upgrade command (RhBug:1939975)
|
||||
Subject: [PATCH 2/2] Document changes to offline-upgrade command
|
||||
(RhBug:1939975)
|
||||
|
||||
A support for security filters was added to the offline-upgrade command. This commit adds the documentation into the man pages.
|
||||
|
||||
@ -13,10 +14,10 @@ resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1939975
|
||||
1 file changed, 14 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/doc/command_ref.rst b/doc/command_ref.rst
|
||||
index bee6a109..7279b3a4 100644
|
||||
index f39f2c71..3ee66bac 100644
|
||||
--- a/doc/command_ref.rst
|
||||
+++ b/doc/command_ref.rst
|
||||
@@ -113,7 +113,7 @@ Options
|
||||
@@ -114,7 +114,7 @@ Options
|
||||
|
||||
``--advisory=<advisory>, --advisories=<advisory>``
|
||||
Include packages corresponding to the advisory ID, Eg. FEDORA-2201-123.
|
||||
@ -25,8 +26,8 @@ index bee6a109..7279b3a4 100644
|
||||
|
||||
``--allowerasing``
|
||||
Allow erasing of installed packages to resolve dependencies. This option could be used as an alternative to the ``yum swap`` command where packages to remove are not explicitly defined.
|
||||
@@ -125,12 +125,12 @@ Options
|
||||
Try the best available package versions in transactions. Specifically during :ref:`dnf upgrade <upgrade_command-label>`, which by default skips over updates that can not be installed for dependency reasons, the switch forces DNF to only consider the latest packages. When running into packages with broken dependencies, DNF will fail giving a reason why the latest version can not be installed.
|
||||
@@ -130,12 +130,12 @@ Options
|
||||
solver may use older versions of dependencies to meet their requirements.
|
||||
|
||||
``--bugfix``
|
||||
- Include packages that fix a bugfix issue. Applicable for the install, repoquery, updateinfo and
|
||||
@ -42,7 +43,7 @@ index bee6a109..7279b3a4 100644
|
||||
|
||||
``-C, --cacheonly``
|
||||
Run entirely from system cache, don't update the cache and use it even in case it is expired.
|
||||
@@ -148,8 +148,8 @@ Options
|
||||
@@ -153,8 +153,8 @@ Options
|
||||
|
||||
``--cve=<cves>, --cves=<cves>``
|
||||
Include packages that fix a CVE (Common Vulnerabilities and Exposures) ID
|
||||
@ -53,8 +54,8 @@ index bee6a109..7279b3a4 100644
|
||||
|
||||
``-d <debug level>, --debuglevel=<debug level>``
|
||||
Debugging output level. This is an integer value between 0 (no additional information strings) and 10 (shows all debugging information, even that not understandable to the user), default is 2. Deprecated, use ``-v`` instead.
|
||||
@@ -208,8 +208,8 @@ Options
|
||||
Enable additional repositories by an id or a glob.
|
||||
@@ -217,8 +217,8 @@ Options
|
||||
specified multiple times.
|
||||
|
||||
``--enhancement``
|
||||
- Include enhancement relevant packages. Applicable for the install, repoquery, updateinfo and
|
||||
@ -64,7 +65,7 @@ index bee6a109..7279b3a4 100644
|
||||
|
||||
.. _exclude_option-label:
|
||||
|
||||
@@ -280,8 +280,8 @@ Options
|
||||
@@ -289,8 +289,8 @@ Options
|
||||
``--setopt`` using configuration from ``/path/dnf.conf``.
|
||||
|
||||
``--newpackage``
|
||||
@ -75,7 +76,7 @@ index bee6a109..7279b3a4 100644
|
||||
|
||||
``--noautoremove``
|
||||
Disable removal of dependencies that are no longer used. It sets
|
||||
@@ -353,11 +353,11 @@ Options
|
||||
@@ -362,11 +362,11 @@ Options
|
||||
|
||||
``--sec-severity=<severity>, --secseverity=<severity>``
|
||||
Includes packages that provide a fix for an issue of the specified severity.
|
@ -1,36 +0,0 @@
|
||||
From 8522c4651678097157fd9f133a451c892021d30b Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Kanavin <alex.kanavin@gmail.com>
|
||||
Date: Tue, 4 May 2021 22:03:30 +0200
|
||||
Subject: [PATCH] dnf/rpm/miscutils.py: fix usage of _()
|
||||
|
||||
Specifically:
|
||||
- an import of _ was missing
|
||||
- _ was reused for a different purpose
|
||||
---
|
||||
dnf/rpm/miscutils.py | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dnf/rpm/miscutils.py b/dnf/rpm/miscutils.py
|
||||
index 235aaf28..7e33d4c4 100644
|
||||
--- a/dnf/rpm/miscutils.py
|
||||
+++ b/dnf/rpm/miscutils.py
|
||||
@@ -22,6 +22,7 @@ import subprocess
|
||||
import logging
|
||||
|
||||
from dnf.i18n import ucd
|
||||
+from dnf.i18n import _
|
||||
from shutil import which
|
||||
|
||||
|
||||
@@ -46,7 +47,7 @@ def _verifyPkgUsingRpmkeys(package, installroot):
|
||||
env={'LC_ALL': 'C'},
|
||||
stdout=subprocess.PIPE,
|
||||
cwd='/') as p:
|
||||
- data, _ = p.communicate()
|
||||
+ data, err = p.communicate()
|
||||
if p.returncode != 0 or data != (package.encode('ascii', 'strict') + b': digests signatures OK\n'):
|
||||
return 0
|
||||
else:
|
||||
--
|
||||
2.35.1
|
||||
|
@ -1,7 +1,7 @@
|
||||
From c9251d182be0bfa66345220cffe0842b44a061a8 Mon Sep 17 00:00:00 2001
|
||||
From e5732ab22f092bb3fc6ce6e8f94aad72f3654383 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kolarik <jkolarik@redhat.com>
|
||||
Date: Wed, 31 Aug 2022 07:49:39 +0200
|
||||
Subject: [PATCH] Move system-upgrade plugin to core (RhBug:2054235)
|
||||
Subject: [PATCH 1/2] Move system-upgrade plugin to core (RhBug:2054235)
|
||||
|
||||
Just doc fix.
|
||||
|
||||
@ -13,10 +13,10 @@ resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2054235
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/doc/command_ref.rst b/doc/command_ref.rst
|
||||
index 7a02448c..bee6a109 100644
|
||||
index 996ae3b4..f39f2c71 100644
|
||||
--- a/doc/command_ref.rst
|
||||
+++ b/doc/command_ref.rst
|
||||
@@ -182,8 +182,7 @@ Options
|
||||
@@ -189,8 +189,7 @@ Options
|
||||
``--downloaddir=<path>, --destdir=<path>``
|
||||
Redirect downloaded packages to provided directory. The option has to be used together with the \-\
|
||||
:ref:`-downloadonly <downloadonly-label>` command line option, with the
|
||||
@ -27,5 +27,5 @@ index 7a02448c..bee6a109 100644
|
||||
.. _downloadonly-label:
|
||||
|
||||
--
|
||||
2.37.3
|
||||
2.38.1
|
||||
|
@ -1,56 +0,0 @@
|
||||
From f109c57ab18d8b1a80e707df3c3f7ad8930bdd42 Mon Sep 17 00:00:00 2001
|
||||
From: Demi Marie Obenour <demi@invisiblethingslab.com>
|
||||
Date: Tue, 27 Apr 2021 21:07:19 -0400
|
||||
Subject: [PATCH] Pass the package to rpmkeys stdin
|
||||
|
||||
This avoids having to compute the expected stdout value, which will
|
||||
always be the constant "-: digests signatures OK\n".
|
||||
---
|
||||
dnf/rpm/miscutils.py | 10 ++++++----
|
||||
1 file changed, 6 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dnf/rpm/miscutils.py b/dnf/rpm/miscutils.py
|
||||
index 7e33d4c4..5f2621c2 100644
|
||||
--- a/dnf/rpm/miscutils.py
|
||||
+++ b/dnf/rpm/miscutils.py
|
||||
@@ -29,7 +29,8 @@ from shutil import which
|
||||
logger = logging.getLogger('dnf')
|
||||
|
||||
|
||||
-def _verifyPkgUsingRpmkeys(package, installroot):
|
||||
+def _verifyPkgUsingRpmkeys(package, installroot, fdno):
|
||||
+ os.lseek(fdno, 0, os.SEEK_SET)
|
||||
rpmkeys_binary = '/usr/bin/rpmkeys'
|
||||
if not os.path.isfile(rpmkeys_binary):
|
||||
rpmkeys_binary = which("rpmkeys")
|
||||
@@ -40,15 +41,16 @@ def _verifyPkgUsingRpmkeys(package, installroot):
|
||||
logger.critical(_('Cannot find rpmkeys executable to verify signatures.'))
|
||||
return 0
|
||||
|
||||
- args = ('rpmkeys', '--checksig', '--root', installroot, '--define', '_pkgverify_level all', '--', package)
|
||||
+ args = ('rpmkeys', '--checksig', '--root', installroot, '--define', '_pkgverify_level all', '-')
|
||||
with subprocess.Popen(
|
||||
args=args,
|
||||
executable=rpmkeys_binary,
|
||||
env={'LC_ALL': 'C'},
|
||||
+ stdin=fdno,
|
||||
stdout=subprocess.PIPE,
|
||||
cwd='/') as p:
|
||||
data, err = p.communicate()
|
||||
- if p.returncode != 0 or data != (package.encode('ascii', 'strict') + b': digests signatures OK\n'):
|
||||
+ if p.returncode != 0 or data != b'-: digests signatures OK\n':
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
@@ -85,7 +87,7 @@ def checkSig(ts, package):
|
||||
|
||||
if siginfo == '(none)':
|
||||
value = 4
|
||||
- elif "Key ID" in siginfo and _verifyPkgUsingRpmkeys(package, ts.ts.rootDir):
|
||||
+ elif "Key ID" in siginfo and _verifyPkgUsingRpmkeys(package, ts.ts.rootDir, fdno):
|
||||
value = 0
|
||||
else:
|
||||
raise ValueError('Unexpected return value %r from hdr.sprintf when checking signature.' % siginfo)
|
||||
--
|
||||
2.35.1
|
||||
|
@ -1,11 +1,8 @@
|
||||
From 9700b8fabd102fcf289281c3c04238da90d7b28e Mon Sep 17 00:00:00 2001
|
||||
From 3ef5ec915ea4b5e6fe7d25542f0daccef278c01e Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kolarik <jkolarik@redhat.com>
|
||||
Date: Tue, 13 Sep 2022 14:35:10 +0200
|
||||
Subject: [PATCH] Fix plugins unit tests + unload plugins upon their deletion
|
||||
|
||||
=changelog=
|
||||
type: bugfix
|
||||
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2134309
|
||||
---
|
||||
dnf/plugin.py | 8 ++++++--
|
||||
tests/api/test_dnf_base.py | 24 +++++++++++++++++++-----
|
||||
@ -93,5 +90,5 @@ index e84e272b..19754b07 100644
|
||||
self.base.unload_plugins()
|
||||
|
||||
--
|
||||
2.37.3
|
||||
2.38.1
|
||||
|
@ -1,174 +0,0 @@
|
||||
From 9798e9ee85f1ba39c816fa08fd3d6168cc8b29e8 Mon Sep 17 00:00:00 2001
|
||||
From: Demi Marie Obenour <demi@invisiblethingslab.com>
|
||||
Date: Fri, 9 Apr 2021 13:03:03 -0400
|
||||
Subject: [PATCH] Use rpmkeys alone to verify signature
|
||||
|
||||
This avoids having to actually parse the package to check its signature,
|
||||
which reduces attack surface. If the output of rpmkeys cannot be
|
||||
parsed, we assume the package is corrupt (the most likely cause).
|
||||
---
|
||||
dnf/rpm/miscutils.py | 126 ++++++++++++++++++++++---------------------
|
||||
1 file changed, 66 insertions(+), 60 deletions(-)
|
||||
|
||||
diff --git a/dnf/rpm/miscutils.py b/dnf/rpm/miscutils.py
|
||||
index 5f2621c2..9d5b2860 100644
|
||||
--- a/dnf/rpm/miscutils.py
|
||||
+++ b/dnf/rpm/miscutils.py
|
||||
@@ -13,47 +13,84 @@
|
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
# Copyright 2003 Duke University
|
||||
|
||||
-from __future__ import print_function, absolute_import
|
||||
-from __future__ import unicode_literals
|
||||
+from __future__ import print_function, absolute_import, unicode_literals
|
||||
|
||||
-import rpm
|
||||
import os
|
||||
import subprocess
|
||||
import logging
|
||||
-
|
||||
-from dnf.i18n import ucd
|
||||
-from dnf.i18n import _
|
||||
from shutil import which
|
||||
|
||||
+from dnf.i18n import _
|
||||
|
||||
-logger = logging.getLogger('dnf')
|
||||
+_logger = logging.getLogger('dnf')
|
||||
+_rpmkeys_binary = None
|
||||
|
||||
+def _find_rpmkeys_binary():
|
||||
+ global _rpmkeys_binary
|
||||
+ if _rpmkeys_binary is None:
|
||||
+ _rpmkeys_binary = which("rpmkeys")
|
||||
+ _logger.debug(_('Using rpmkeys executable at %s to verify signatures'),
|
||||
+ _rpmkeys_binary)
|
||||
+ return _rpmkeys_binary
|
||||
|
||||
-def _verifyPkgUsingRpmkeys(package, installroot, fdno):
|
||||
- os.lseek(fdno, 0, os.SEEK_SET)
|
||||
- rpmkeys_binary = '/usr/bin/rpmkeys'
|
||||
- if not os.path.isfile(rpmkeys_binary):
|
||||
- rpmkeys_binary = which("rpmkeys")
|
||||
- logger.info(_('Using rpmkeys executable from {path} to verify signature for package: {package}.').format(
|
||||
- path=rpmkeys_binary, package=package))
|
||||
+def _process_rpm_output(data):
|
||||
+ # No signatures or digests = corrupt package.
|
||||
+ # There is at least one line for -: and another (empty) entry after the
|
||||
+ # last newline.
|
||||
+ if len(data) < 3 or data[0] != b'-:' or data[-1]:
|
||||
+ return 2
|
||||
+ seen_sig, missing_key, not_trusted, not_signed = False, False, False, False
|
||||
+ for i in data[1:-1]:
|
||||
+ if b': BAD' in i:
|
||||
+ return 2
|
||||
+ elif i.endswith(b': NOKEY'):
|
||||
+ missing_key = True
|
||||
+ elif i.endswith(b': NOTTRUSTED'):
|
||||
+ not_trusted = True
|
||||
+ elif i.endswith(b': NOTFOUND'):
|
||||
+ not_signed = True
|
||||
+ elif not i.endswith(b': OK'):
|
||||
+ return 2
|
||||
+ if not_trusted:
|
||||
+ return 3
|
||||
+ elif missing_key:
|
||||
+ return 1
|
||||
+ elif not_signed:
|
||||
+ return 4
|
||||
+ # we still check return code, so this is safe
|
||||
+ return 0
|
||||
|
||||
- if not os.path.isfile(rpmkeys_binary):
|
||||
- logger.critical(_('Cannot find rpmkeys executable to verify signatures.'))
|
||||
- return 0
|
||||
+def _verifyPackageUsingRpmkeys(package, installroot):
|
||||
+ rpmkeys_binary = _find_rpmkeys_binary()
|
||||
+ if rpmkeys_binary is None or not os.path.isfile(rpmkeys_binary):
|
||||
+ _logger.critical(_('Cannot find rpmkeys executable to verify signatures.'))
|
||||
+ return 2
|
||||
|
||||
- args = ('rpmkeys', '--checksig', '--root', installroot, '--define', '_pkgverify_level all', '-')
|
||||
+ # "--define=_pkgverify_level all" enforces signature checking;
|
||||
+ # "--define=_pkgverify_flags 0x0" ensures that all signatures and digests
|
||||
+ # are checked.
|
||||
+ args = ('rpmkeys', '--checksig', '--root', installroot, '--verbose',
|
||||
+ '--define=_pkgverify_level all', '--define=_pkgverify_flags 0x0',
|
||||
+ '-')
|
||||
with subprocess.Popen(
|
||||
args=args,
|
||||
executable=rpmkeys_binary,
|
||||
env={'LC_ALL': 'C'},
|
||||
- stdin=fdno,
|
||||
stdout=subprocess.PIPE,
|
||||
- cwd='/') as p:
|
||||
- data, err = p.communicate()
|
||||
- if p.returncode != 0 or data != b'-: digests signatures OK\n':
|
||||
- return 0
|
||||
- else:
|
||||
- return 1
|
||||
+ cwd='/',
|
||||
+ stdin=package) as p:
|
||||
+ data = p.communicate()[0]
|
||||
+ returncode = p.returncode
|
||||
+ if type(returncode) is not int:
|
||||
+ raise AssertionError('Popen set return code to non-int')
|
||||
+ # rpmkeys can return something other than 0 or 1 in the case of a
|
||||
+ # fatal error (OOM, abort() called, SIGSEGV, etc)
|
||||
+ if returncode >= 2 or returncode < 0:
|
||||
+ return 2
|
||||
+ ret = _process_rpm_output(data.split(b'\n'))
|
||||
+ if ret:
|
||||
+ return ret
|
||||
+ return 2 if returncode else 0
|
||||
|
||||
def checkSig(ts, package):
|
||||
"""Takes a transaction set and a package, check it's sigs,
|
||||
@@ -63,40 +100,9 @@ def checkSig(ts, package):
|
||||
return 3 if the key is not trusted
|
||||
return 4 if the pkg is not gpg or pgp signed"""
|
||||
|
||||
- value = 4
|
||||
- currentflags = ts.setVSFlags(0)
|
||||
- fdno = os.open(package, os.O_RDONLY)
|
||||
+ fdno = os.open(package, os.O_RDONLY|os.O_NOCTTY|os.O_CLOEXEC)
|
||||
try:
|
||||
- hdr = ts.hdrFromFdno(fdno)
|
||||
- except rpm.error as e:
|
||||
- if str(e) == "public key not available":
|
||||
- value = 1
|
||||
- elif str(e) == "public key not trusted":
|
||||
- value = 3
|
||||
- elif str(e) == "error reading package header":
|
||||
- value = 2
|
||||
- else:
|
||||
- raise ValueError('Unexpected error value %r from ts.hdrFromFdno when checking signature.' % str(e))
|
||||
- else:
|
||||
- # checks signature from an hdr
|
||||
- string = '%|DSAHEADER?{%{DSAHEADER:pgpsig}}:{%|RSAHEADER?{%{RSAHEADER:pgpsig}}:' \
|
||||
- '{%|SIGGPG?{%{SIGGPG:pgpsig}}:{%|SIGPGP?{%{SIGPGP:pgpsig}}:{(none)}|}|}|}|'
|
||||
- try:
|
||||
- siginfo = hdr.sprintf(string)
|
||||
- siginfo = ucd(siginfo)
|
||||
-
|
||||
- if siginfo == '(none)':
|
||||
- value = 4
|
||||
- elif "Key ID" in siginfo and _verifyPkgUsingRpmkeys(package, ts.ts.rootDir, fdno):
|
||||
- value = 0
|
||||
- else:
|
||||
- raise ValueError('Unexpected return value %r from hdr.sprintf when checking signature.' % siginfo)
|
||||
- except UnicodeDecodeError:
|
||||
- pass
|
||||
-
|
||||
- del hdr
|
||||
-
|
||||
- os.close(fdno)
|
||||
-
|
||||
- ts.setVSFlags(currentflags) # put things back like they were before
|
||||
+ value = _verifyPackageUsingRpmkeys(fdno, ts.ts.rootDir)
|
||||
+ finally:
|
||||
+ os.close(fdno)
|
||||
return value
|
||||
--
|
||||
2.35.1
|
||||
|
@ -1,8 +1,8 @@
|
||||
From 23742561dcb168604d9668815a8c1ebbdf516d39 Mon Sep 17 00:00:00 2001
|
||||
From 490cf87dd27926d16fb10735b467cbc490d5c9f1 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kolarik <jkolarik@redhat.com>
|
||||
Date: Wed, 23 Nov 2022 08:44:41 +0000
|
||||
Subject: [PATCH 2/2] Ignore processing variable files with unsupported
|
||||
encoding (RhBug:2141215)
|
||||
Subject: [PATCH] Ignore processing variable files with unsupported encoding
|
||||
(RhBug:2141215)
|
||||
|
||||
This issue could be seen for example when there are some temporary files stored by text editors in the `/etc/dnf/vars` folder. These files could be in the binary format and causes `UnicodeDecodeError` exception to be thrown during processing of the var files.
|
||||
|
@ -1,37 +0,0 @@
|
||||
From 185330e5d5f5e07f40ed08c706fd997abffd5e78 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
|
||||
Date: Thu, 3 Jun 2021 11:23:31 +0200
|
||||
Subject: [PATCH] Lower _pkgverify_level to signature for signature checking
|
||||
with rpmkeys
|
||||
|
||||
We don't want to be veryfing digests as well when checking signatures.
|
||||
It would break legacy package installation in FIPS mode due to MD5
|
||||
digest being unverifiable (see https://access.redhat.com/solutions/5221661)
|
||||
|
||||
Follow up for https://github.com/rpm-software-management/dnf/pull/1753
|
||||
---
|
||||
dnf/rpm/miscutils.py | 7 +++----
|
||||
1 file changed, 3 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dnf/rpm/miscutils.py b/dnf/rpm/miscutils.py
|
||||
index 9d5b2860..46ef4754 100644
|
||||
--- a/dnf/rpm/miscutils.py
|
||||
+++ b/dnf/rpm/miscutils.py
|
||||
@@ -66,11 +66,10 @@ def _verifyPackageUsingRpmkeys(package, installroot):
|
||||
_logger.critical(_('Cannot find rpmkeys executable to verify signatures.'))
|
||||
return 2
|
||||
|
||||
- # "--define=_pkgverify_level all" enforces signature checking;
|
||||
- # "--define=_pkgverify_flags 0x0" ensures that all signatures and digests
|
||||
- # are checked.
|
||||
+ # "--define=_pkgverify_level signature" enforces signature checking;
|
||||
+ # "--define=_pkgverify_flags 0x0" ensures that all signatures are checked.
|
||||
args = ('rpmkeys', '--checksig', '--root', installroot, '--verbose',
|
||||
- '--define=_pkgverify_level all', '--define=_pkgverify_flags 0x0',
|
||||
+ '--define=_pkgverify_level signature', '--define=_pkgverify_flags 0x0',
|
||||
'-')
|
||||
with subprocess.Popen(
|
||||
args=args,
|
||||
--
|
||||
2.35.1
|
||||
|
7384
SOURCES/0006-Update-translations.patch
Normal file
7384
SOURCES/0006-Update-translations.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,101 +0,0 @@
|
||||
From 6766d3af1993d48f5548746e68268e674e52bd1d Mon Sep 17 00:00:00 2001
|
||||
From: Gary Leydon <gary.leydon@yale.edu>
|
||||
Date: Fri, 21 May 2021 14:13:59 -0400
|
||||
Subject: [PATCH] add default colors to documentation
|
||||
|
||||
---
|
||||
doc/conf_ref.rst | 24 ++++++++++++------------
|
||||
1 file changed, 12 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/doc/conf_ref.rst b/doc/conf_ref.rst
|
||||
index ec5bac2a..fcaa0319 100644
|
||||
--- a/doc/conf_ref.rst
|
||||
+++ b/doc/conf_ref.rst
|
||||
@@ -498,72 +498,72 @@ configuration file by your distribution to override the DNF defaults.
|
||||
:ref:`color <color-label>`
|
||||
|
||||
Color of available packages that are older than installed packages.
|
||||
- The option is used during list operations.
|
||||
+ The option is used during list operations. Default is dim,cyan.
|
||||
|
||||
``color_list_available_install``
|
||||
:ref:`color <color-label>`
|
||||
|
||||
Color of packages that are available for installation and none of their versions in installed.
|
||||
- The option is used during list operations.
|
||||
+ The option is used during list operations. Default is normal.
|
||||
|
||||
``color_list_available_reinstall``
|
||||
:ref:`color <color-label>`
|
||||
|
||||
- Color of available packages that are identical to installed versions and are available for reinstalls.
|
||||
+ Color of available packages that are identical to installed versions and are available for reinstalls. Default is bold,underline,green.
|
||||
The option is used during list operations.
|
||||
|
||||
``color_list_available_upgrade``
|
||||
:ref:`color <color-label>`
|
||||
|
||||
- Color of available packages that are newer than installed packages.
|
||||
+ Color of available packages that are newer than installed packages. Default is bold,blue.
|
||||
The option is used during list operations.
|
||||
|
||||
``color_list_installed_extra``
|
||||
:ref:`color <color-label>`
|
||||
|
||||
Color of installed packages that do not have any version among available packages.
|
||||
- The option is used during list operations.
|
||||
+ The option is used during list operations. Default is bold,red.
|
||||
|
||||
``color_list_installed_newer``
|
||||
:ref:`color <color-label>`
|
||||
|
||||
Color of installed packages that are newer than any version among available packages.
|
||||
- The option is used during list operations.
|
||||
+ The option is used during list operations. Default is bold,yellow.
|
||||
|
||||
``color_list_installed_older``
|
||||
:ref:`color <color-label>`
|
||||
|
||||
Color of installed packages that are older than any version among available packages.
|
||||
- The option is used during list operations.
|
||||
+ The option is used during list operations. Default is bold.
|
||||
|
||||
``color_list_installed_reinstall``
|
||||
:ref:`color <color-label>`
|
||||
|
||||
Color of installed packages that are among available packages and can be reinstalled.
|
||||
- The option is used during list operations.
|
||||
+ The option is used during list operations. Default is normal.
|
||||
|
||||
``color_search_match``
|
||||
:ref:`color <color-label>`
|
||||
|
||||
- Color of patterns matched in search output.
|
||||
+ Color of patterns matched in search output. Default is bold.
|
||||
|
||||
``color_update_installed``
|
||||
:ref:`color <color-label>`
|
||||
|
||||
- Color of removed packages.
|
||||
+ Color of removed packages. Default is normal.
|
||||
This option is used during displaying transactions.
|
||||
|
||||
``color_update_local``
|
||||
:ref:`color <color-label>`
|
||||
|
||||
Color of local packages that are installed from the @commandline repository.
|
||||
- This option is used during displaying transactions.
|
||||
+ This option is used during displaying transactions. Default is bold.
|
||||
|
||||
``color_update_remote``
|
||||
:ref:`color <color-label>`
|
||||
|
||||
Color of packages that are installed/upgraded/downgraded from remote repositories.
|
||||
- This option is used during displaying transactions.
|
||||
+ This option is used during displaying transactions. Default is normal.
|
||||
|
||||
|
||||
==============
|
||||
--
|
||||
2.35.1
|
||||
|
252
SOURCES/0007-Add-reboot-option-to-DNF-Automatic.patch
Normal file
252
SOURCES/0007-Add-reboot-option-to-DNF-Automatic.patch
Normal file
@ -0,0 +1,252 @@
|
||||
From 56d3e10ecb666da53a77d17e9ac7524f3e1341d8 Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Tue, 24 Jan 2023 09:53:47 -0500
|
||||
Subject: [PATCH 1/4] Add reboot option to DNF Automatic (RhBug:2124793)
|
||||
|
||||
Add ability in DNF Automatic to automatically trigger a reboot after an
|
||||
upgrade. The `reboot` option supports three settings: ``never`` does not
|
||||
reboot the system (current behavior). ``when-changed`` triggers a reboot
|
||||
after any upgrade. ``when-needed`` triggers a reboot only when rebooting
|
||||
is necessary to apply changes, such as when systemd or the kernel is
|
||||
upgraded. The `reboot_command` option allows customizing the command
|
||||
used to reboot (default is `shutdown -r`).
|
||||
|
||||
= changelog =
|
||||
msg: Add `reboot` option to DNF Automatic
|
||||
type: enhancement
|
||||
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2124793
|
||||
---
|
||||
dnf/automatic/main.py | 9 +++++++++
|
||||
dnf/base.py | 14 ++++++++++++++
|
||||
doc/automatic.rst | 12 ++++++++++++
|
||||
etc/dnf/automatic.conf | 9 +++++++++
|
||||
tests/automatic/test_main.py | 4 ++++
|
||||
5 files changed, 48 insertions(+)
|
||||
|
||||
diff --git a/dnf/automatic/main.py b/dnf/automatic/main.py
|
||||
index b53d9c00..b68962c2 100644
|
||||
--- a/dnf/automatic/main.py
|
||||
+++ b/dnf/automatic/main.py
|
||||
@@ -24,6 +24,7 @@ from __future__ import unicode_literals
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
+import os
|
||||
import random
|
||||
import socket
|
||||
import time
|
||||
@@ -179,6 +180,9 @@ class CommandsConfig(Config):
|
||||
libdnf.conf.VectorString(['default', 'security'])))
|
||||
self.add_option('random_sleep', libdnf.conf.OptionNumberInt32(300))
|
||||
self.add_option('network_online_timeout', libdnf.conf.OptionNumberInt32(60))
|
||||
+ self.add_option('reboot', libdnf.conf.OptionEnumString('never',
|
||||
+ libdnf.conf.VectorString(['never', 'when-changed', 'when-needed'])))
|
||||
+ self.add_option('reboot_command', libdnf.conf.OptionString('shutdown -r'))
|
||||
|
||||
def imply(self):
|
||||
if self.apply_updates:
|
||||
@@ -340,6 +344,11 @@ def main(args):
|
||||
base.do_transaction()
|
||||
emitters.notify_applied()
|
||||
emitters.commit()
|
||||
+
|
||||
+ if (conf.commands.reboot == 'when-changed' or
|
||||
+ (conf.commands.reboot == 'when-needed' and base.reboot_needed())):
|
||||
+ if os.waitstatus_to_exitcode(os.system(conf.commands.reboot_command)) != 0:
|
||||
+ return 1
|
||||
except dnf.exceptions.Error as exc:
|
||||
logger.error(_('Error: %s'), ucd(exc))
|
||||
return 1
|
||||
diff --git a/dnf/base.py b/dnf/base.py
|
||||
index 154eb4e3..24c5a444 100644
|
||||
--- a/dnf/base.py
|
||||
+++ b/dnf/base.py
|
||||
@@ -2790,6 +2790,20 @@ class Base(object):
|
||||
|
||||
return skipped_conflicts, skipped_dependency
|
||||
|
||||
+ def reboot_needed(self):
|
||||
+ """Check whether a system reboot is recommended following the transaction
|
||||
+
|
||||
+ :return: bool
|
||||
+ """
|
||||
+ if not self.transaction:
|
||||
+ return False
|
||||
+
|
||||
+ # List taken from DNF needs-restarting
|
||||
+ need_reboot = frozenset(('kernel', 'kernel-rt', 'glibc',
|
||||
+ 'linux-firmware', 'systemd', 'dbus',
|
||||
+ 'dbus-broker', 'dbus-daemon'))
|
||||
+ changed_pkgs = self.transaction.install_set | self.transaction.remove_set
|
||||
+ return any(pkg.name in need_reboot for pkg in changed_pkgs)
|
||||
|
||||
def _msg_installed(pkg):
|
||||
name = ucd(pkg)
|
||||
diff --git a/doc/automatic.rst b/doc/automatic.rst
|
||||
index b8e47ad1..ade0ca1a 100644
|
||||
--- a/doc/automatic.rst
|
||||
+++ b/doc/automatic.rst
|
||||
@@ -90,6 +90,18 @@ Setting the mode of operation of the program.
|
||||
|
||||
What kind of upgrades to look at. ``default`` signals looking for all available updates, ``security`` only those with an issued security advisory.
|
||||
|
||||
+``reboot``
|
||||
+ either one of ``never``, ``when-changed``, ``when-needed``, default: ``never``
|
||||
+
|
||||
+ When the system should reboot following upgrades. ``never`` does not reboot the system. ``when-changed`` triggers a reboot after any upgrade. ``when-needed`` triggers a reboot only when rebooting is necessary to apply changes, such as when systemd or the kernel is upgraded.
|
||||
+
|
||||
+``reboot_command``
|
||||
+ string, default: ``shutdown -r``
|
||||
+
|
||||
+ Specify the command to run to trigger a reboot of the system. For example, add a 5-minute delay and a wall message by using ``shutdown -r +5 'Rebooting after upgrading packages'``
|
||||
+
|
||||
+
|
||||
+
|
||||
----------------------
|
||||
``[emitters]`` section
|
||||
----------------------
|
||||
diff --git a/etc/dnf/automatic.conf b/etc/dnf/automatic.conf
|
||||
index 1f7e9402..9735447f 100644
|
||||
--- a/etc/dnf/automatic.conf
|
||||
+++ b/etc/dnf/automatic.conf
|
||||
@@ -21,6 +21,15 @@ download_updates = yes
|
||||
# install.timer override this setting.
|
||||
apply_updates = no
|
||||
|
||||
+# When the system should reboot following upgrades:
|
||||
+# never = don't reboot after upgrades
|
||||
+# when-changed = reboot after any changes
|
||||
+# when-needed = reboot when necessary to apply changes
|
||||
+reboot = never
|
||||
+
|
||||
+# The command that is run to trigger a system reboot.
|
||||
+reboot_command = "shutdown -r"
|
||||
+
|
||||
|
||||
[emitters]
|
||||
# Name to use for this system in messages that are emitted. Default is the
|
||||
diff --git a/tests/automatic/test_main.py b/tests/automatic/test_main.py
|
||||
index 27ffa407..dc4acd52 100644
|
||||
--- a/tests/automatic/test_main.py
|
||||
+++ b/tests/automatic/test_main.py
|
||||
@@ -49,3 +49,7 @@ class TestConfig(tests.support.TestCase):
|
||||
conf = dnf.automatic.main.AutomaticConfig(FILE, downloadupdates=True, installupdates=False)
|
||||
self.assertTrue(conf.commands.download_updates)
|
||||
self.assertFalse(conf.commands.apply_updates)
|
||||
+
|
||||
+ # test that reboot is "never" by default
|
||||
+ conf = dnf.automatic.main.AutomaticConfig(FILE)
|
||||
+ self.assertEqual(conf.commands.reboot, 'never')
|
||||
--
|
||||
2.40.0
|
||||
|
||||
|
||||
From 8d7608f3462deddf36d5a75ff66f847a30b78026 Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Tue, 24 Jan 2023 09:59:22 -0500
|
||||
Subject: [PATCH 2/4] Add Evan Goode to AUTHORS
|
||||
|
||||
---
|
||||
AUTHORS | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/AUTHORS b/AUTHORS
|
||||
index 50bff95b..e802a51e 100644
|
||||
--- a/AUTHORS
|
||||
+++ b/AUTHORS
|
||||
@@ -69,6 +69,7 @@ DNF CONTRIBUTORS
|
||||
Dave Johansen <davejohansen@gmail.com>
|
||||
Dylan Pindur <dylanpindur@gmail.com>
|
||||
Eduard Cuba <ecuba@redhat.com>
|
||||
+ Evan Goode <egoode@redhat.com>
|
||||
Filipe Brandenburger <filbranden@gmail.com>
|
||||
Frank Dana <ferdnyc@gmail.com>
|
||||
George Machitidze <giomac@gmail.com>
|
||||
--
|
||||
2.40.0
|
||||
|
||||
|
||||
From 9deed331cb7a1890e1f11a57c989c300b1641a88 Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Tue, 24 Jan 2023 17:12:46 -0500
|
||||
Subject: [PATCH 3/4] DNF Automatic reboot: 5-minute delay and wall by default
|
||||
|
||||
---
|
||||
dnf/automatic/main.py | 2 +-
|
||||
doc/automatic.rst | 4 ++--
|
||||
etc/dnf/automatic.conf | 2 +-
|
||||
3 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dnf/automatic/main.py b/dnf/automatic/main.py
|
||||
index b68962c2..a03c359f 100644
|
||||
--- a/dnf/automatic/main.py
|
||||
+++ b/dnf/automatic/main.py
|
||||
@@ -182,7 +182,7 @@ class CommandsConfig(Config):
|
||||
self.add_option('network_online_timeout', libdnf.conf.OptionNumberInt32(60))
|
||||
self.add_option('reboot', libdnf.conf.OptionEnumString('never',
|
||||
libdnf.conf.VectorString(['never', 'when-changed', 'when-needed'])))
|
||||
- self.add_option('reboot_command', libdnf.conf.OptionString('shutdown -r'))
|
||||
+ self.add_option('reboot_command', libdnf.conf.OptionString('shutdown -r +5 \'Rebooting after applying package updates\''))
|
||||
|
||||
def imply(self):
|
||||
if self.apply_updates:
|
||||
diff --git a/doc/automatic.rst b/doc/automatic.rst
|
||||
index ade0ca1a..329c2f46 100644
|
||||
--- a/doc/automatic.rst
|
||||
+++ b/doc/automatic.rst
|
||||
@@ -96,9 +96,9 @@ Setting the mode of operation of the program.
|
||||
When the system should reboot following upgrades. ``never`` does not reboot the system. ``when-changed`` triggers a reboot after any upgrade. ``when-needed`` triggers a reboot only when rebooting is necessary to apply changes, such as when systemd or the kernel is upgraded.
|
||||
|
||||
``reboot_command``
|
||||
- string, default: ``shutdown -r``
|
||||
+ string, default: ``shutdown -r +5 'Rebooting after applying package updates'``
|
||||
|
||||
- Specify the command to run to trigger a reboot of the system. For example, add a 5-minute delay and a wall message by using ``shutdown -r +5 'Rebooting after upgrading packages'``
|
||||
+ Specify the command to run to trigger a reboot of the system. For example, to skip the 5-minute delay and wall message, use ``shutdown -r``
|
||||
|
||||
|
||||
|
||||
diff --git a/etc/dnf/automatic.conf b/etc/dnf/automatic.conf
|
||||
index 9735447f..e61b12af 100644
|
||||
--- a/etc/dnf/automatic.conf
|
||||
+++ b/etc/dnf/automatic.conf
|
||||
@@ -28,7 +28,7 @@ apply_updates = no
|
||||
reboot = never
|
||||
|
||||
# The command that is run to trigger a system reboot.
|
||||
-reboot_command = "shutdown -r"
|
||||
+reboot_command = "shutdown -r +5 'Rebooting after applying package updates'"
|
||||
|
||||
|
||||
[emitters]
|
||||
--
|
||||
2.40.0
|
||||
|
||||
|
||||
From b002f47a763e442277913a06df963b0ca91deb54 Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Wed, 25 Jan 2023 09:47:59 -0500
|
||||
Subject: [PATCH 4/4] DNF Automatic: error message for failed reboot command
|
||||
|
||||
---
|
||||
dnf/automatic/main.py | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dnf/automatic/main.py b/dnf/automatic/main.py
|
||||
index a03c359f..11c35ecf 100644
|
||||
--- a/dnf/automatic/main.py
|
||||
+++ b/dnf/automatic/main.py
|
||||
@@ -347,7 +347,9 @@ def main(args):
|
||||
|
||||
if (conf.commands.reboot == 'when-changed' or
|
||||
(conf.commands.reboot == 'when-needed' and base.reboot_needed())):
|
||||
- if os.waitstatus_to_exitcode(os.system(conf.commands.reboot_command)) != 0:
|
||||
+ 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)
|
||||
return 1
|
||||
except dnf.exceptions.Error as exc:
|
||||
logger.error(_('Error: %s'), ucd(exc))
|
||||
--
|
||||
2.40.0
|
||||
|
@ -1,21 +0,0 @@
|
||||
From 276e3b1d19bfad2a72f75ecbcce478e4f1e575db Mon Sep 17 00:00:00 2001
|
||||
From: Gary Leydon <gary.leydon@yale.edu>
|
||||
Date: Fri, 21 May 2021 14:16:21 -0400
|
||||
Subject: [PATCH] add author
|
||||
|
||||
---
|
||||
AUTHORS | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/AUTHORS b/AUTHORS
|
||||
index 1981dc4e..f8c9eb83 100644
|
||||
--- a/AUTHORS
|
||||
+++ b/AUTHORS
|
||||
@@ -95,3 +95,4 @@ DNF CONTRIBUTORS
|
||||
Vladan Kudlac <vladankudlac@gmail.com>
|
||||
Will Woods <wwoods@redhat.com>
|
||||
Furkan Karcıoğlu <krc440002@gmail.com>
|
||||
+ Gary Leydon <gary.leydon@yale.edu>
|
||||
--
|
||||
2.35.1
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 33c354ed52be8f8fa2d43aff8ba1fe1540e1744c Mon Sep 17 00:00:00 2001
|
||||
From b0caa16589763699174f47a3e36a703e1af32ed4 Mon Sep 17 00:00:00 2001
|
||||
From: Kyle Walker <kwalker@redhat.com>
|
||||
Date: Tue, 20 Dec 2022 08:42:03 -0500
|
||||
Subject: [PATCH] Omit src RPMs from check-update (RhBug: 2151910)
|
||||
@ -19,10 +19,10 @@ resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2151910
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/dnf/base.py b/dnf/base.py
|
||||
index aba411e..8c19276 100644
|
||||
index 24c5a44..7e97e21 100644
|
||||
--- a/dnf/base.py
|
||||
+++ b/dnf/base.py
|
||||
@@ -1519,6 +1519,8 @@ class Base(object):
|
||||
@@ -1543,6 +1543,8 @@ class Base(object):
|
||||
updates = query_for_repo(q).filterm(upgrades_by_priority=True)
|
||||
# reduce a query to security upgrades if they are specified
|
||||
updates = self._merge_update_filters(updates, upgrade=True)
|
||||
@ -31,7 +31,7 @@ index aba411e..8c19276 100644
|
||||
# reduce a query to latest packages
|
||||
updates = updates.latest().run()
|
||||
|
||||
@@ -1571,6 +1573,8 @@ class Base(object):
|
||||
@@ -1595,6 +1597,8 @@ class Base(object):
|
||||
self.sack.query()).filter(obsoletes_by_priority=inst)
|
||||
# reduce a query to security upgrades if they are specified
|
||||
obsoletes = self._merge_update_filters(obsoletes, warning=False, upgrade=True)
|
@ -1,75 +0,0 @@
|
||||
From 5cfe87de2ecd645c2aa8b210bd98171e8dd72fe5 Mon Sep 17 00:00:00 2001
|
||||
From: Gary Leydon <gary.leydon@yale.edu>
|
||||
Date: Thu, 27 May 2021 11:52:42 -0400
|
||||
Subject: [PATCH] update colors according to libdnf/libdnf/conf/ConfigMain.cpp
|
||||
|
||||
---
|
||||
doc/conf_ref.rst | 16 ++++++++--------
|
||||
1 file changed, 8 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/doc/conf_ref.rst b/doc/conf_ref.rst
|
||||
index fcaa0319..016bd00c 100644
|
||||
--- a/doc/conf_ref.rst
|
||||
+++ b/doc/conf_ref.rst
|
||||
@@ -498,13 +498,13 @@ configuration file by your distribution to override the DNF defaults.
|
||||
:ref:`color <color-label>`
|
||||
|
||||
Color of available packages that are older than installed packages.
|
||||
- The option is used during list operations. Default is dim,cyan.
|
||||
+ The option is used during list operations. Default is magenta.
|
||||
|
||||
``color_list_available_install``
|
||||
:ref:`color <color-label>`
|
||||
|
||||
Color of packages that are available for installation and none of their versions in installed.
|
||||
- The option is used during list operations. Default is normal.
|
||||
+ The option is used during list operations. Default is bold,cyan.
|
||||
|
||||
``color_list_available_reinstall``
|
||||
:ref:`color <color-label>`
|
||||
@@ -534,36 +534,36 @@ configuration file by your distribution to override the DNF defaults.
|
||||
:ref:`color <color-label>`
|
||||
|
||||
Color of installed packages that are older than any version among available packages.
|
||||
- The option is used during list operations. Default is bold.
|
||||
+ The option is used during list operations. Default is yellow.
|
||||
|
||||
``color_list_installed_reinstall``
|
||||
:ref:`color <color-label>`
|
||||
|
||||
Color of installed packages that are among available packages and can be reinstalled.
|
||||
- The option is used during list operations. Default is normal.
|
||||
+ The option is used during list operations. Default is cyan.
|
||||
|
||||
``color_search_match``
|
||||
:ref:`color <color-label>`
|
||||
|
||||
- Color of patterns matched in search output. Default is bold.
|
||||
+ Color of patterns matched in search output. Default is bold,magenta.
|
||||
|
||||
``color_update_installed``
|
||||
:ref:`color <color-label>`
|
||||
|
||||
- Color of removed packages. Default is normal.
|
||||
+ Color of removed packages. Default is red.
|
||||
This option is used during displaying transactions.
|
||||
|
||||
``color_update_local``
|
||||
:ref:`color <color-label>`
|
||||
|
||||
Color of local packages that are installed from the @commandline repository.
|
||||
- This option is used during displaying transactions. Default is bold.
|
||||
+ This option is used during displaying transactions. Default is green.
|
||||
|
||||
``color_update_remote``
|
||||
:ref:`color <color-label>`
|
||||
|
||||
Color of packages that are installed/upgraded/downgraded from remote repositories.
|
||||
- This option is used during displaying transactions. Default is normal.
|
||||
+ This option is used during displaying transactions. Default is bold,green.
|
||||
|
||||
|
||||
==============
|
||||
--
|
||||
2.35.1
|
||||
|
@ -1,81 +0,0 @@
|
||||
From f5cb86b83aedaa18fd784d06d8f1479b9127c6f5 Mon Sep 17 00:00:00 2001
|
||||
From: Marek Blaha <mblaha@redhat.com>
|
||||
Date: Wed, 6 Oct 2021 09:43:37 +0200
|
||||
Subject: [PATCH] Fix reporting irrecoverable errors on packages download
|
||||
|
||||
The original _irrecoverable property returns random dictionary - either
|
||||
packages irrecoverable errors, or global fatal error or even new empty
|
||||
dictionary. This makes it prone to programmer errors like:
|
||||
|
||||
errs._irrecoverable[pkg] = [err]
|
||||
|
||||
which may lead to setting the error into the newly created empty
|
||||
dictionary instead of packages errors dictionary as intended.
|
||||
|
||||
I turned the property to method which I consider more clear.
|
||||
---
|
||||
dnf/base.py | 8 ++++----
|
||||
dnf/repo.py | 9 ++++-----
|
||||
2 files changed, 8 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/dnf/base.py b/dnf/base.py
|
||||
index 0949ddf8..b0a378c2 100644
|
||||
--- a/dnf/base.py
|
||||
+++ b/dnf/base.py
|
||||
@@ -1165,8 +1165,8 @@ class Base(object):
|
||||
progress.start(len(payloads), est_remote_size)
|
||||
errors = dnf.repo._download_payloads(payloads, drpm)
|
||||
|
||||
- if errors._irrecoverable:
|
||||
- raise dnf.exceptions.DownloadError(errors._irrecoverable)
|
||||
+ if errors._irrecoverable():
|
||||
+ raise dnf.exceptions.DownloadError(errors._irrecoverable())
|
||||
|
||||
remote_size = sum(errors._bandwidth_used(pload)
|
||||
for pload in payloads)
|
||||
@@ -1191,8 +1191,8 @@ class Base(object):
|
||||
progress.start(len(payloads), est_remote_size)
|
||||
errors = dnf.repo._download_payloads(payloads, drpm)
|
||||
|
||||
- if errors._irrecoverable:
|
||||
- raise dnf.exceptions.DownloadError(errors._irrecoverable)
|
||||
+ if errors._irrecoverable():
|
||||
+ raise dnf.exceptions.DownloadError(errors._irrecoverable())
|
||||
|
||||
remote_size += \
|
||||
sum(errors._bandwidth_used(pload) for pload in payloads)
|
||||
diff --git a/dnf/repo.py b/dnf/repo.py
|
||||
index b5c9849e..b454e981 100644
|
||||
--- a/dnf/repo.py
|
||||
+++ b/dnf/repo.py
|
||||
@@ -112,7 +112,7 @@ def _download_payloads(payloads, drpm):
|
||||
errs._skipped.add(pkg)
|
||||
continue
|
||||
pkg.repo._repo.expire()
|
||||
- errs._irrecoverable[pkg] = [err]
|
||||
+ errs._pkg_irrecoverable[pkg] = [err]
|
||||
|
||||
return errs
|
||||
|
||||
@@ -131,15 +131,14 @@ def _update_saving(saving, payloads, errs):
|
||||
|
||||
class _DownloadErrors(object):
|
||||
def __init__(self):
|
||||
- self._val_irrecoverable = {}
|
||||
+ self._pkg_irrecoverable = {}
|
||||
self._val_recoverable = {}
|
||||
self._fatal = None
|
||||
self._skipped = set()
|
||||
|
||||
- @property
|
||||
def _irrecoverable(self):
|
||||
- if self._val_irrecoverable:
|
||||
- return self._val_irrecoverable
|
||||
+ if self._pkg_irrecoverable:
|
||||
+ return self._pkg_irrecoverable
|
||||
if self._fatal:
|
||||
return {'': [self._fatal]}
|
||||
return {}
|
||||
--
|
||||
2.35.1
|
||||
|
@ -1,21 +1,31 @@
|
||||
From 2658062d4c176201d0decf03929a89b44761c072 Mon Sep 17 00:00:00 2001
|
||||
From fcc21cf217a7dfaaf79ca36b5afab6344380eae1 Mon Sep 17 00:00:00 2001
|
||||
From: Marek Blaha <mblaha@redhat.com>
|
||||
Date: Mon, 3 Apr 2023 12:19:40 +0200
|
||||
Subject: [PATCH] Backport: automatic: Fix online detection with proxy (RhBz:2022440)
|
||||
Subject: [PATCH] automatic: Fix online detection with proxy (RhBz:2022440)
|
||||
|
||||
In case the proxy is configured (either for a repo of globally) it is
|
||||
used also for detecting whether the system is online.
|
||||
|
||||
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2022440
|
||||
---
|
||||
dnf/automatic/main.py | 20 ++++++++++++++------
|
||||
1 file changed, 14 insertions(+), 6 deletions(-)
|
||||
dnf/automatic/main.py | 23 ++++++++++++++++-------
|
||||
1 file changed, 16 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/dnf/automatic/main.py b/dnf/automatic/main.py
|
||||
index b53d9c0..93ce13c 100644
|
||||
index 11c35ec..756531e 100644
|
||||
--- a/dnf/automatic/main.py
|
||||
+++ b/dnf/automatic/main.py
|
||||
@@ -251,21 +251,29 @@ def wait_for_network(repos, timeout):
|
||||
@@ -182,7 +182,8 @@ class CommandsConfig(Config):
|
||||
self.add_option('network_online_timeout', libdnf.conf.OptionNumberInt32(60))
|
||||
self.add_option('reboot', libdnf.conf.OptionEnumString('never',
|
||||
libdnf.conf.VectorString(['never', 'when-changed', 'when-needed'])))
|
||||
- self.add_option('reboot_command', libdnf.conf.OptionString('shutdown -r +5 \'Rebooting after applying package updates\''))
|
||||
+ self.add_option('reboot_command', libdnf.conf.OptionString(
|
||||
+ 'shutdown -r +5 \'Rebooting after applying package updates\''))
|
||||
|
||||
def imply(self):
|
||||
if self.apply_updates:
|
||||
@@ -255,21 +256,29 @@ def wait_for_network(repos, timeout):
|
||||
'http': 80,
|
||||
'https': 443,
|
||||
'ftp': 21,
|
@ -1,68 +0,0 @@
|
||||
From ca3d7f06c8f4c1c901dc853ac33c06976b46c61e Mon Sep 17 00:00:00 2001
|
||||
From: Marek Blaha <mblaha@redhat.com>
|
||||
Date: Wed, 6 Oct 2021 09:56:05 +0200
|
||||
Subject: [PATCH] Add fail_fast parameter to download_payloads methods
|
||||
|
||||
Unlike in the rpm transaction, reposync needs to switch the fail_fast
|
||||
off to download as much packages from repository as possible.
|
||||
---
|
||||
dnf/base.py | 6 +++---
|
||||
dnf/repo.py | 4 ++--
|
||||
2 files changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/dnf/base.py b/dnf/base.py
|
||||
index b0a378c2..c258a5a7 100644
|
||||
--- a/dnf/base.py
|
||||
+++ b/dnf/base.py
|
||||
@@ -1151,7 +1151,7 @@ class Base(object):
|
||||
timer()
|
||||
self._trans_success = True
|
||||
|
||||
- def _download_remote_payloads(self, payloads, drpm, progress, callback_total):
|
||||
+ def _download_remote_payloads(self, payloads, drpm, progress, callback_total, fail_fast=True):
|
||||
lock = dnf.lock.build_download_lock(self.conf.cachedir, self.conf.exit_on_lock)
|
||||
with lock:
|
||||
beg_download = time.time()
|
||||
@@ -1163,7 +1163,7 @@ class Base(object):
|
||||
progress.start(len(payloads), est_remote_size, total_drpms=total_drpm)
|
||||
else:
|
||||
progress.start(len(payloads), est_remote_size)
|
||||
- errors = dnf.repo._download_payloads(payloads, drpm)
|
||||
+ errors = dnf.repo._download_payloads(payloads, drpm, fail_fast)
|
||||
|
||||
if errors._irrecoverable():
|
||||
raise dnf.exceptions.DownloadError(errors._irrecoverable())
|
||||
@@ -1189,7 +1189,7 @@ class Base(object):
|
||||
est_remote_size = sum(pload.download_size
|
||||
for pload in payloads)
|
||||
progress.start(len(payloads), est_remote_size)
|
||||
- errors = dnf.repo._download_payloads(payloads, drpm)
|
||||
+ errors = dnf.repo._download_payloads(payloads, drpm, fail_fast)
|
||||
|
||||
if errors._irrecoverable():
|
||||
raise dnf.exceptions.DownloadError(errors._irrecoverable())
|
||||
diff --git a/dnf/repo.py b/dnf/repo.py
|
||||
index b454e981..bb422309 100644
|
||||
--- a/dnf/repo.py
|
||||
+++ b/dnf/repo.py
|
||||
@@ -84,7 +84,7 @@ def _pkg2payload(pkg, progress, *factories):
|
||||
raise ValueError(_('no matching payload factory for %s') % pkg)
|
||||
|
||||
|
||||
-def _download_payloads(payloads, drpm):
|
||||
+def _download_payloads(payloads, drpm, fail_fast=True):
|
||||
# download packages
|
||||
def _download_sort_key(payload):
|
||||
return not hasattr(payload, 'delta')
|
||||
@@ -94,7 +94,7 @@ def _download_payloads(payloads, drpm):
|
||||
for pload in sorted(payloads, key=_download_sort_key)]
|
||||
errs = _DownloadErrors()
|
||||
try:
|
||||
- libdnf.repo.PackageTarget.downloadPackages(libdnf.repo.VectorPPackageTarget(targets), True)
|
||||
+ libdnf.repo.PackageTarget.downloadPackages(libdnf.repo.VectorPPackageTarget(targets), fail_fast)
|
||||
except RuntimeError as e:
|
||||
errs._fatal = str(e)
|
||||
drpm.wait()
|
||||
--
|
||||
2.35.1
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 46aeabda1980621ca0f87528e0a81b4f59d886f0 Mon Sep 17 00:00:00 2001
|
||||
From e62164e450c05d626e4ca2b5dc2728939686b423 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kolarik <jkolarik@redhat.com>
|
||||
Date: Thu, 20 Apr 2023 10:10:14 +0000
|
||||
Subject: [PATCH] automatic: Return an error when transaction fails
|
||||
@ -17,10 +17,10 @@ resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2170093
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/dnf/automatic/main.py b/dnf/automatic/main.py
|
||||
index 93ce13cc..ccd9ab64 100644
|
||||
index 756531e7..f6f4049b 100644
|
||||
--- a/dnf/automatic/main.py
|
||||
+++ b/dnf/automatic/main.py
|
||||
@@ -346,6 +346,13 @@ def main(args):
|
||||
@@ -351,6 +351,13 @@ def main(args):
|
||||
|
||||
gpgsigcheck(base, trans.install_set)
|
||||
base.do_transaction()
|
||||
@ -33,7 +33,7 @@ index 93ce13cc..ccd9ab64 100644
|
||||
+
|
||||
emitters.notify_applied()
|
||||
emitters.commit()
|
||||
except dnf.exceptions.Error as exc:
|
||||
|
||||
--
|
||||
2.40.1
|
||||
|
@ -1,4 +1,4 @@
|
||||
From a74209ff53c9a51293b45434196dff49002c5691 Mon Sep 17 00:00:00 2001
|
||||
From 0f979bd00d22d52f4970897207bd43a74db90bcc Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Tue, 30 May 2023 20:48:54 +0000
|
||||
Subject: [PATCH] Document symbols in `dnf history list` output
|
||||
@ -30,10 +30,10 @@ resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2172067
|
||||
1 file changed, 18 insertions(+)
|
||||
|
||||
diff --git a/doc/command_ref.rst b/doc/command_ref.rst
|
||||
index 7279b3a4..f8149e86 100644
|
||||
index 3ee66bac..0e6cea01 100644
|
||||
--- a/doc/command_ref.rst
|
||||
+++ b/doc/command_ref.rst
|
||||
@@ -701,6 +701,24 @@ transactions and act according to this information (assuming the
|
||||
@@ -710,6 +710,24 @@ 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.
|
||||
|
@ -1,139 +0,0 @@
|
||||
From f0f037db8219b1e74be4ed86f5eea53b63ca1d88 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hr=C3=A1zk=C3=BD?= <lhrazky@redhat.com>
|
||||
Date: Tue, 20 Jul 2021 15:29:59 +0200
|
||||
Subject: [PATCH] comps: Make the install_or_skip() method not catch CompsError
|
||||
anymore
|
||||
|
||||
According to its docstring, the original intention of the method was to
|
||||
not fail on installing an already installed group/environment.
|
||||
|
||||
However, the CompsError is no longer thrown when attempting to install
|
||||
an already installed group or environment. It was changed to logging a
|
||||
warning directly in 5210b9dc and then the check was removed completely
|
||||
in 217ca0fa.
|
||||
|
||||
For the other case for which an instance of CompsError can be thrown
|
||||
from the install_group() and install_environment() methods, which is
|
||||
when a group or environment is not found, we certainly want to throw an
|
||||
error (see the linked bugs), therefore there's no reason to catch the
|
||||
exception anymore.
|
||||
|
||||
The install_or_skip() method is preserved as part of the API so as not
|
||||
to break compatibility any more than necessary.
|
||||
|
||||
msg: API: Raise CompsError when group/env not found in install_group and install_environment
|
||||
type: bugfix
|
||||
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1947958
|
||||
related: https://bugzilla.redhat.com/show_bug.cgi?id=1943206
|
||||
---
|
||||
dnf/base.py | 8 ++------
|
||||
dnf/cli/commands/group.py | 4 ++--
|
||||
dnf/comps.py | 20 ++++++++++----------
|
||||
doc/api_base.rst | 4 ++--
|
||||
4 files changed, 16 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/dnf/base.py b/dnf/base.py
|
||||
index c258a5a7..babca31d 100644
|
||||
--- a/dnf/base.py
|
||||
+++ b/dnf/base.py
|
||||
@@ -1668,9 +1668,7 @@ class Base(object):
|
||||
if not isinstance(types, int):
|
||||
types = libdnf.transaction.listToCompsPackageType(types)
|
||||
|
||||
- trans = dnf.comps.install_or_skip(solver._environment_install,
|
||||
- env_id, types, exclude or set(),
|
||||
- strict, exclude_groups)
|
||||
+ trans = solver._environment_install(env_id, types, exclude or set(), strict, exclude_groups)
|
||||
if not trans:
|
||||
return 0
|
||||
return self._add_comps_trans(trans)
|
||||
@@ -1713,9 +1711,7 @@ class Base(object):
|
||||
if not isinstance(pkg_types, int):
|
||||
pkg_types = libdnf.transaction.listToCompsPackageType(pkg_types)
|
||||
|
||||
- trans = dnf.comps.install_or_skip(solver._group_install,
|
||||
- grp_id, pkg_types, exclude_pkgnames,
|
||||
- strict)
|
||||
+ trans = solver._group_install(grp_id, pkg_types, exclude_pkgnames, strict)
|
||||
if not trans:
|
||||
return 0
|
||||
if strict:
|
||||
diff --git a/dnf/cli/commands/group.py b/dnf/cli/commands/group.py
|
||||
index cf542799..fd723c48 100644
|
||||
--- a/dnf/cli/commands/group.py
|
||||
+++ b/dnf/cli/commands/group.py
|
||||
@@ -244,9 +244,9 @@ class GroupCommand(commands.Command):
|
||||
types = tuple(self.base.conf.group_package_types)
|
||||
pkg_types = libdnf.transaction.listToCompsPackageType(types)
|
||||
for env_id in res.environments:
|
||||
- dnf.comps.install_or_skip(solver._environment_install, env_id, pkg_types)
|
||||
+ solver._environment_install(env_id, pkg_types)
|
||||
for group_id in res.groups:
|
||||
- dnf.comps.install_or_skip(solver._group_install, group_id, pkg_types)
|
||||
+ solver._group_install(group_id, pkg_types)
|
||||
|
||||
def _mark_remove(self, patterns):
|
||||
q = CompsQuery(self.base.comps, self.base.history,
|
||||
diff --git a/dnf/comps.py b/dnf/comps.py
|
||||
index 89765337..461eb274 100644
|
||||
--- a/dnf/comps.py
|
||||
+++ b/dnf/comps.py
|
||||
@@ -93,15 +93,15 @@ def _fn_display_order(group):
|
||||
|
||||
def install_or_skip(install_fnc, grp_or_env_id, types, exclude=None,
|
||||
strict=True, exclude_groups=None):
|
||||
- """Either mark in persistor as installed given `grp_or_env` (group
|
||||
- or environment) or skip it (if it's already installed).
|
||||
- `install_fnc` has to be Solver._group_install
|
||||
- or Solver._environment_install.
|
||||
- """
|
||||
- try:
|
||||
- return install_fnc(grp_or_env_id, types, exclude, strict, exclude_groups)
|
||||
- except dnf.comps.CompsError as e:
|
||||
- logger.warning("%s, %s", ucd(e)[:-1], _("skipping."))
|
||||
+ """
|
||||
+ Installs a group or an environment identified by grp_or_env_id.
|
||||
+ This method is preserved for API compatibility. It used to catch an
|
||||
+ exception thrown when a gorup or env was already installed, which is no
|
||||
+ longer thrown.
|
||||
+ `install_fnc` has to be Solver._group_install or
|
||||
+ Solver._environment_install.
|
||||
+ """
|
||||
+ return install_fnc(grp_or_env_id, types, exclude, strict, exclude_groups)
|
||||
|
||||
|
||||
class _Langs(object):
|
||||
@@ -592,7 +592,7 @@ class Solver(object):
|
||||
assert dnf.util.is_string_type(group_id)
|
||||
return self.history.env.is_removable_group(group_id)
|
||||
|
||||
- def _environment_install(self, env_id, pkg_types, exclude, strict=True, exclude_groups=None):
|
||||
+ def _environment_install(self, env_id, pkg_types, exclude=None, strict=True, exclude_groups=None):
|
||||
assert dnf.util.is_string_type(env_id)
|
||||
comps_env = self.comps._environment_by_id(env_id)
|
||||
if not comps_env:
|
||||
diff --git a/doc/api_base.rst b/doc/api_base.rst
|
||||
index 20d7945e..03396b69 100644
|
||||
--- a/doc/api_base.rst
|
||||
+++ b/doc/api_base.rst
|
||||
@@ -179,7 +179,7 @@
|
||||
|
||||
.. method:: group_install(group_id, pkg_types, exclude=None, strict=True)
|
||||
|
||||
- Mark group with corresponding `group_id` installed and mark the packages in the group for installation. Return the number of packages that the operation has marked for installation. `pkg_types` is a sequence of strings determining the kinds of packages to be installed, where the respective groups can be selected by including ``"mandatory"``, ``"default"`` or ``"optional"`` in it. If `exclude` is given, it has to be an iterable of package name glob patterns: :meth:`.group_install` will then not mark the respective packages for installation whenever possible. Parameter `strict` is a boolean indicating whether group packages that exist but are non-installable due to e.g. dependency issues should be skipped (False) or cause transaction to fail to resolve (True).
|
||||
+ Mark group with corresponding `group_id` installed and mark the packages in the group for installation. Return the number of packages that the operation has marked for installation. `pkg_types` is a sequence of strings determining the kinds of packages to be installed, where the respective groups can be selected by including ``"mandatory"``, ``"default"`` or ``"optional"`` in it. If `exclude` is given, it has to be an iterable of package name glob patterns: :meth:`.group_install` will then not mark the respective packages for installation whenever possible. Parameter `strict` is a boolean indicating whether group packages that exist but are non-installable due to e.g. dependency issues should be skipped (False) or cause transaction to fail to resolve (True). Raises :exc:`dnf.exceptions.CompsError` in case the group doesn't exist.
|
||||
|
||||
.. method:: group_remove(group_id)
|
||||
|
||||
@@ -191,7 +191,7 @@
|
||||
|
||||
.. method:: environment_install(env_id, types, exclude=None, strict=True, exclude_groups=None)
|
||||
|
||||
- Similar to :meth:`.group_install` but operates on environmental groups. `exclude_groups` is an iterable of group IDs that will not be marked as installed.
|
||||
+ Similar to :meth:`.group_install` but operates on environmental groups. `exclude_groups` is an iterable of group IDs that will not be marked as installed. Raises :exc:`dnf.exceptions.CompsError` in case the group doesn't exist.
|
||||
|
||||
.. method:: environment_remove(env_id)
|
||||
|
||||
--
|
||||
2.35.1
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,30 +0,0 @@
|
||||
From 683b92811abcb6cbbc00353010ec18e2cf655912 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Mracek <jmracek@redhat.com>
|
||||
Date: Mon, 6 Sep 2021 12:40:59 +0200
|
||||
Subject: [PATCH] [doc] Improve description of multilib_policy=all
|
||||
(RhBug:1996681,1995630)
|
||||
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=1996681
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=1995630
|
||||
---
|
||||
doc/conf_ref.rst | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/doc/conf_ref.rst b/doc/conf_ref.rst
|
||||
index 016bd00c..83b14ecd 100644
|
||||
--- a/doc/conf_ref.rst
|
||||
+++ b/doc/conf_ref.rst
|
||||
@@ -351,7 +351,9 @@ configuration file by your distribution to override the DNF defaults.
|
||||
``multilib_policy``
|
||||
:ref:`string <string-label>`
|
||||
|
||||
- Controls how multilib packages are treated during install operations. Can either be ``"best"`` (the default) for the depsolver to prefer packages which best match the system's architecture, or ``"all"`` to install all available packages with compatible architectures.
|
||||
+ Controls how multilib packages are treated during install operations. Can either be ``"best"`` (the default) for
|
||||
+ the depsolver to prefer packages which best match the system's architecture, or ``"all"`` to install packages for
|
||||
+ all available architectures.
|
||||
|
||||
.. _obsoletes_conf_option-label:
|
||||
|
||||
--
|
||||
2.35.1
|
||||
|
@ -1,34 +0,0 @@
|
||||
From db52d259645daf8ca0ae06e829787d36171f2d5b Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Rohel <jrohel@redhat.com>
|
||||
Date: Wed, 20 Oct 2021 09:20:03 +0200
|
||||
Subject: [PATCH] Fix: Python dnf API does not respect cacheonly
|
||||
(RhBug:1862970)
|
||||
|
||||
`Repo` object has always been constructed with default synchronization
|
||||
strategy. The configuration option `cacheonly` was ignored. DNF
|
||||
application set synchronization strategy later in the `Cli` object
|
||||
during processing demands.
|
||||
|
||||
The fix takes into account the `cacheonly` option during the construction
|
||||
of the `Repo` object. Synchronization strategy may still be overriden
|
||||
during demand processing.
|
||||
---
|
||||
dnf/repo.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dnf/repo.py b/dnf/repo.py
|
||||
index bb422309..1822cf01 100644
|
||||
--- a/dnf/repo.py
|
||||
+++ b/dnf/repo.py
|
||||
@@ -434,7 +434,7 @@ class Repo(dnf.conf.RepoConf):
|
||||
self._pkgdir = None
|
||||
self._key_import = _NullKeyImport()
|
||||
self.metadata = None # :api
|
||||
- self._repo.setSyncStrategy(self.DEFAULT_SYNC)
|
||||
+ self._repo.setSyncStrategy(SYNC_ONLY_CACHE if parent_conf and parent_conf.cacheonly else self.DEFAULT_SYNC)
|
||||
if parent_conf:
|
||||
self._repo.setSubstitutions(parent_conf.substitutions)
|
||||
self._substitutions = dnf.conf.substitutions.Substitutions()
|
||||
--
|
||||
2.35.1
|
||||
|
@ -1,4 +1,4 @@
|
||||
From 8bc3b7a217de41c0a9bc52cd9cac50cde9e9ee65 Mon Sep 17 00:00:00 2001
|
||||
From 422794199b7b8a5f7426effc04979804cf31b6f7 Mon Sep 17 00:00:00 2001
|
||||
From: Anish Bhatt <anish.bhatt@salesforce.com>
|
||||
Date: Mon, 10 Jul 2023 10:09:17 -0700
|
||||
Subject: [PATCH] When parsing over a KVP list, do not return till the whole
|
||||
@ -27,7 +27,7 @@ index ffa0f8ed..82c05ac0 100644
|
||||
2.41.0
|
||||
|
||||
|
||||
From 89c6f3633f55acd31d44a487ce76dd89c12d795c Mon Sep 17 00:00:00 2001
|
||||
From d750fcb27686f73e352ae4575db150aa954aeb10 Mon Sep 17 00:00:00 2001
|
||||
From: Anish Bhatt <anish.bhatt@salesforce.com>
|
||||
Date: Mon, 10 Jul 2023 10:10:30 -0700
|
||||
Subject: [PATCH] Add to authors
|
||||
@ -37,7 +37,7 @@ Subject: [PATCH] Add to authors
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/AUTHORS b/AUTHORS
|
||||
index 0077c7ea..eb1e0121 100644
|
||||
index e802a51e..699a92c4 100644
|
||||
--- a/AUTHORS
|
||||
+++ b/AUTHORS
|
||||
@@ -63,6 +63,7 @@ DNF CONTRIBUTORS
|
@ -1,26 +0,0 @@
|
||||
From f8025df597685a0bd0c347b1a60c280f03bdca6f Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Rohel <jrohel@redhat.com>
|
||||
Date: Fri, 5 Nov 2021 08:52:56 +0100
|
||||
Subject: [PATCH] Documentation: API notes for cacheonly
|
||||
|
||||
---
|
||||
doc/conf_ref.rst | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/doc/conf_ref.rst b/doc/conf_ref.rst
|
||||
index 83b14ecd..75bcdf75 100644
|
||||
--- a/doc/conf_ref.rst
|
||||
+++ b/doc/conf_ref.rst
|
||||
@@ -129,6 +129,9 @@ configuration file by your distribution to override the DNF defaults.
|
||||
If set to ``True`` DNF will run entirely from system cache, will not update
|
||||
the cache and will use it even in case it is expired. Default is ``False``.
|
||||
|
||||
+ API Notes: Must be set before repository objects are created. Plugins must set
|
||||
+ this in the pre_config hook. Later changes are ignored.
|
||||
+
|
||||
.. _check_config_file_age-label:
|
||||
|
||||
``check_config_file_age``
|
||||
--
|
||||
2.35.1
|
||||
|
@ -0,0 +1,55 @@
|
||||
From cbc552f3f2ef72c8cb46e068aef841eee9206e30 Mon Sep 17 00:00:00 2001
|
||||
From: Marek Blaha <mblaha@redhat.com>
|
||||
Date: Wed, 20 Sep 2023 09:15:03 +0200
|
||||
Subject: [PATCH] base: Add obsoleters of only latest versions
|
||||
|
||||
Resolves situations where a package is in older version obsoleted, but
|
||||
there is newer (not obsoleted) version available.
|
||||
This patch covers installation of group packages and arch specific
|
||||
packages. The rest is in hawkey library.
|
||||
|
||||
Relevant bugs:
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=2183279
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=2176263
|
||||
---
|
||||
dnf/base.py | 17 +++++++++++++++--
|
||||
1 file changed, 15 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dnf/base.py b/dnf/base.py
|
||||
index 7e97e21..50869ec 100644
|
||||
--- a/dnf/base.py
|
||||
+++ b/dnf/base.py
|
||||
@@ -1684,7 +1684,16 @@ class Base(object):
|
||||
sltr.set(provides="({} if {})".format(comps_pkg.name, comps_pkg.requires))
|
||||
else:
|
||||
if self.conf.obsoletes:
|
||||
- query = query.union(self.sack.query().filterm(obsoletes=query))
|
||||
+ # If there is no installed package in the pkgs_list, add only
|
||||
+ # obsoleters of the latest versions. Otherwise behave
|
||||
+ # consistently with upgrade and add all obsoleters.
|
||||
+ # See https://bugzilla.redhat.com/show_bug.cgi?id=2176263
|
||||
+ # for details of the problem.
|
||||
+ if query.installed():
|
||||
+ query = query.union(self.sack.query().filterm(obsoletes=query))
|
||||
+ else:
|
||||
+ query = query.union(self.sack.query().filterm(
|
||||
+ obsoletes=query.filter(latest_per_arch_by_priority=True)))
|
||||
sltr.set(pkg=query)
|
||||
self._goal.install(select=sltr, optional=not strict)
|
||||
return remove_query
|
||||
@@ -1921,7 +1930,11 @@ class Base(object):
|
||||
sltr = dnf.selector.Selector(self.sack)
|
||||
q = self.sack.query().filterm(pkg=packages)
|
||||
if self.conf.obsoletes:
|
||||
- q = q.union(self.sack.query().filterm(obsoletes=q))
|
||||
+ # use only obsoletes of the latest versions
|
||||
+ # See https://bugzilla.redhat.com/show_bug.cgi?id=2176263
|
||||
+ # for details of the problem.
|
||||
+ q = q.union(self.sack.query().filterm(
|
||||
+ obsoletes=q.filter(latest_per_arch_by_priority=True)))
|
||||
sltr = sltr.set(pkg=q)
|
||||
if reponame is not None:
|
||||
sltr = sltr.set(reponame=reponame)
|
||||
--
|
||||
libgit2 1.6.4
|
||||
|
@ -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
|
||||
|
@ -1,39 +0,0 @@
|
||||
From 6af9938c87cf409f886f21b59ec45c54eda6c8b2 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Mracek <jmracek@redhat.com>
|
||||
Date: Tue, 2 Nov 2021 14:23:22 +0100
|
||||
Subject: [PATCH] Allow destdir option with modulesync command
|
||||
|
||||
---
|
||||
dnf/cli/cli.py | 2 +-
|
||||
doc/command_ref.rst | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py
|
||||
index 65769978..a315201c 100644
|
||||
--- a/dnf/cli/cli.py
|
||||
+++ b/dnf/cli/cli.py
|
||||
@@ -810,7 +810,7 @@ class Cli(object):
|
||||
if opts.destdir is not None:
|
||||
self.base.conf.destdir = opts.destdir
|
||||
if not self.base.conf.downloadonly and opts.command not in (
|
||||
- 'download', 'system-upgrade', 'reposync'):
|
||||
+ 'download', 'system-upgrade', 'reposync', 'modulesync'):
|
||||
logger.critical(_('--destdir or --downloaddir must be used with --downloadonly '
|
||||
'or download or system-upgrade command.')
|
||||
)
|
||||
diff --git a/doc/command_ref.rst b/doc/command_ref.rst
|
||||
index f96c0eac..42aec72c 100644
|
||||
--- a/doc/command_ref.rst
|
||||
+++ b/doc/command_ref.rst
|
||||
@@ -182,7 +182,7 @@ Options
|
||||
``--downloaddir=<path>, --destdir=<path>``
|
||||
Redirect downloaded packages to provided directory. The option has to be used together with the \-\
|
||||
:ref:`-downloadonly <downloadonly-label>` command line option, with the
|
||||
- ``download`` command (dnf-plugins-core) or with the ``system-upgrade`` command
|
||||
+ ``download``, ``modulesync`` or ``reposync`` commands (dnf-plugins-core) or with the ``system-upgrade`` command
|
||||
(dnf-plugins-extras).
|
||||
|
||||
.. _downloadonly-label:
|
||||
--
|
||||
2.35.1
|
||||
|
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
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,57 +0,0 @@
|
||||
From 27f26c607c44b8331b23c861241a8509c2452531 Mon Sep 17 00:00:00 2001
|
||||
From: sbluhm <stefan.bluhm@clacee.eu>
|
||||
Date: Sun, 9 Jan 2022 14:30:19 +0100
|
||||
Subject: [PATCH] Add documentation for query api flags
|
||||
|
||||
= changelog =
|
||||
msg: Add documentation for query api flags
|
||||
type: enhancement
|
||||
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2035577
|
||||
---
|
||||
AUTHORS | 1 +
|
||||
doc/api_sack.rst | 14 +++++++++++++-
|
||||
2 files changed, 14 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/AUTHORS b/AUTHORS
|
||||
index f8c9eb83..0077c7ea 100644
|
||||
--- a/AUTHORS
|
||||
+++ b/AUTHORS
|
||||
@@ -91,6 +91,7 @@ DNF CONTRIBUTORS
|
||||
Petr Spacek <pspacek@redhat.com>
|
||||
Rob Cutmore <robcutmore@gmail.com>
|
||||
Satoshi Matsumoto <kaorimatz@gmail.com>
|
||||
+ Stefan Bluhm <stefan.bluhm@clacee.eu>
|
||||
Tomas Kasparek <tkasparek@redhat.com>
|
||||
Vladan Kudlac <vladankudlac@gmail.com>
|
||||
Will Woods <wwoods@redhat.com>
|
||||
diff --git a/doc/api_sack.rst b/doc/api_sack.rst
|
||||
index 79719878..ac843fc9 100644
|
||||
--- a/doc/api_sack.rst
|
||||
+++ b/doc/api_sack.rst
|
||||
@@ -25,10 +25,22 @@
|
||||
|
||||
The package sack. Contains metadata information about all known packages, installed and available.
|
||||
|
||||
- .. method:: query()
|
||||
+ .. method:: query(flags=hawkey.APPLY_EXCLUDES)
|
||||
|
||||
Return a :class:`Query<dnf.query.Query>` for querying packages contained in this sack.
|
||||
|
||||
+ :ref:`Package filtering <excluded_packages-label>` is applied when creating the query object. The behavior can be adapted using flags. Possible flags:
|
||||
+
|
||||
+
|
||||
+ ============================== ===========================================================================
|
||||
+ Flag Value meaning
|
||||
+ ============================== ===========================================================================
|
||||
+ hawkey.APPLY_EXCLUDES Apply all package filtering.
|
||||
+ hawkey.IGNORE_EXCLUDES Ignore all package filtering.
|
||||
+ hawkey.IGNORE_REGULAR_EXCLUDES Ignore regular excludes defined by configuration files or the command line.
|
||||
+ hawkey.IGNORE_MODULAR_EXCLUDES Ignore modular filtering.
|
||||
+ ============================== ===========================================================================
|
||||
+
|
||||
.. function:: rpmdb_sack(base)
|
||||
|
||||
Returns a new instance of sack containing only installed packages (@System repo). Useful to get list of the installed RPMs after transaction.
|
||||
--
|
||||
2.35.1
|
||||
|
@ -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
|
||||
|
@ -1,37 +0,0 @@
|
||||
From 9bd0423e1e543ed5f83924ec61aa253eced24cf8 Mon Sep 17 00:00:00 2001
|
||||
From: Marek Blaha <mblaha@redhat.com>
|
||||
Date: Mon, 14 Mar 2022 09:49:52 +0100
|
||||
Subject: [PATCH] Fix processing of download errors (RhBug: 2024527)
|
||||
|
||||
Users with different than english locale are not able to update their
|
||||
systems in case that some of updates are already downloaded in the dnf
|
||||
cache (e.g. using dnf-automatic).
|
||||
|
||||
The error string is taken from librepo target where it is stored
|
||||
untranslated. Therefore we need to compare untranslated versions of the
|
||||
string.
|
||||
|
||||
= changelog =
|
||||
msg: Fix download errors handling in non-english locales
|
||||
type: bugfix
|
||||
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2024527
|
||||
---
|
||||
dnf/repo.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dnf/repo.py b/dnf/repo.py
|
||||
index 1822cf01..ec1a2537 100644
|
||||
--- a/dnf/repo.py
|
||||
+++ b/dnf/repo.py
|
||||
@@ -108,7 +108,7 @@ def _download_payloads(payloads, drpm, fail_fast=True):
|
||||
callbacks = tgt.getCallbacks()
|
||||
payload = callbacks.package_pload
|
||||
pkg = payload.pkg
|
||||
- if err == _('Already downloaded'):
|
||||
+ if err == 'Already downloaded':
|
||||
errs._skipped.add(pkg)
|
||||
continue
|
||||
pkg.repo._repo.expire()
|
||||
--
|
||||
2.35.1
|
||||
|
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
|
||||
|
@ -1,81 +0,0 @@
|
||||
From 0da73ea1304005b796842d96679d6ea31cdeea3c Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
|
||||
Date: Tue, 1 Mar 2022 12:42:23 +0100
|
||||
Subject: [PATCH] Fix unittests that relied on checksum being at the end of
|
||||
solvfiles
|
||||
|
||||
---
|
||||
tests/test_fill_sack_from_repos_in_cache.py | 26 +++++++++++----------
|
||||
1 file changed, 14 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/tests/test_fill_sack_from_repos_in_cache.py b/tests/test_fill_sack_from_repos_in_cache.py
|
||||
index a8de287c..30d02cfe 100644
|
||||
--- a/tests/test_fill_sack_from_repos_in_cache.py
|
||||
+++ b/tests/test_fill_sack_from_repos_in_cache.py
|
||||
@@ -39,7 +39,7 @@ TEST_REPO_NAME = "test-repo"
|
||||
|
||||
|
||||
class FillSackFromReposInCacheTest(unittest.TestCase):
|
||||
- def _create_cache_for_repo(self, repopath, tmpdir):
|
||||
+ def _create_cache_for_repo(self, repopath, tmpdir, repo_name=TEST_REPO_NAME):
|
||||
conf = dnf.conf.MainConf()
|
||||
conf.cachedir = os.path.join(tmpdir, "cache")
|
||||
conf.installroot = tmpdir
|
||||
@@ -49,7 +49,7 @@ class FillSackFromReposInCacheTest(unittest.TestCase):
|
||||
|
||||
base = dnf.Base(conf=conf)
|
||||
|
||||
- repoconf = dnf.repo.Repo(TEST_REPO_NAME, base.conf)
|
||||
+ repoconf = dnf.repo.Repo(repo_name, base.conf)
|
||||
repoconf.baseurl = repopath
|
||||
repoconf.enable()
|
||||
|
||||
@@ -194,6 +194,8 @@ class FillSackFromReposInCacheTest(unittest.TestCase):
|
||||
|
||||
def test_exception_with_checksum_mismatch_and_only_repomd(self):
|
||||
self._setUp_from_repo_path(os.path.join(os.path.abspath(os.path.dirname(__file__)), "repos/rpm"))
|
||||
+ self._create_cache_for_repo(os.path.join(os.path.abspath(os.path.dirname(__file__)), "repos/drpm"),
|
||||
+ self.tmpdir, "drpm-repo")
|
||||
|
||||
# Remove xml metadata except repomd
|
||||
# repomd.xml is not compressed and doesn't end with .gz
|
||||
@@ -201,12 +203,11 @@ class FillSackFromReposInCacheTest(unittest.TestCase):
|
||||
for f in repodata_without_repomd:
|
||||
os.remove(f)
|
||||
|
||||
- # Modify checksum of solv file so it doesn't match with repomd
|
||||
- solv = glob.glob(os.path.join(self.tmpdir, "cache/*.solv"))[0]
|
||||
- with open(solv, "a") as opensolv:
|
||||
- opensolv.write("appended text to change checksum")
|
||||
+ # Replace solvfile of test-repo with solvfile from drpm-repo which has different data (different checksum)
|
||||
+ shutil.move(os.path.join(self.tmpdir, "cache/drpm-repo.solv"),
|
||||
+ os.path.join(self.tmpdir, "cache/test-repo.solv"))
|
||||
|
||||
- # Now we only have cache with solvx, modified solv file and just repomd
|
||||
+ # Now we only have cache with solvx, mismatching solv file and just repomd
|
||||
# Since we don't have original xml metadata we cannot regenerate solv -> fail (exception)
|
||||
|
||||
self.assertRaises(dnf.exceptions.RepoError,
|
||||
@@ -214,13 +215,14 @@ class FillSackFromReposInCacheTest(unittest.TestCase):
|
||||
|
||||
def test_checksum_mistmatch_regenerates_solv(self):
|
||||
self._setUp_from_repo_path(os.path.join(os.path.abspath(os.path.dirname(__file__)), "repos/rpm"))
|
||||
+ self._create_cache_for_repo(os.path.join(os.path.abspath(os.path.dirname(__file__)), "repos/drpm"),
|
||||
+ self.tmpdir, "drpm-repo")
|
||||
|
||||
- # Modify checksum of solv file so it doesn't match with repomd
|
||||
- solv = glob.glob(os.path.join(self.tmpdir, "cache/*.solv"))[0]
|
||||
- with open(solv, "a") as opensolv:
|
||||
- opensolv.write("appended text to change checksum")
|
||||
+ # Replace solvfile of test-repo with solvfile from drpm-repo which has different data (different checksum)
|
||||
+ shutil.move(os.path.join(self.tmpdir, "cache/drpm-repo.solv"),
|
||||
+ os.path.join(self.tmpdir, "cache/test-repo.solv"))
|
||||
|
||||
- # Now we only have cache with solvx, modified solv file and xml metadata.
|
||||
+ # Now we only have cache with solvx, mismatching solv file and xml metadata.
|
||||
# Checksum mistmatch causes regeneration of solv file and repo works.
|
||||
|
||||
self.test_base.fill_sack_from_repos_in_cache(load_system_repo=False)
|
||||
--
|
||||
2.35.1
|
||||
|
@ -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
|
||||
|
@ -1,64 +0,0 @@
|
||||
From fe87499e6745795b1dc6225fa102a1242eb9ffc8 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hr=C3=A1zk=C3=BD?= <lhrazky@redhat.com>
|
||||
Date: Thu, 17 Feb 2022 18:46:22 +0100
|
||||
Subject: [PATCH] cli/commands/history: Fix history undo on a Reason Change
|
||||
|
||||
The previous reason needs to be fetched from the history db. It's
|
||||
inefficient to parse the nevra after it was serialized in a previous
|
||||
step, but that would need bigger code restructuring.
|
||||
|
||||
= changelog =
|
||||
msg: Fix history undo on a Reason Change
|
||||
type: bugfix
|
||||
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2053014
|
||||
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2010259
|
||||
---
|
||||
dnf.spec | 2 +-
|
||||
dnf/cli/commands/history.py | 11 +++++++++++
|
||||
2 files changed, 12 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dnf.spec b/dnf.spec
|
||||
index 02c8b577..36c3932e 100644
|
||||
--- a/dnf.spec
|
||||
+++ b/dnf.spec
|
||||
@@ -2,7 +2,7 @@
|
||||
%define __cmake_in_source_build 1
|
||||
|
||||
# default dependencies
|
||||
-%global hawkey_version 0.61.1
|
||||
+%global hawkey_version 0.66.0
|
||||
%global libcomps_version 0.1.8
|
||||
%global libmodulemd_version 2.9.3
|
||||
%global rpm_version 4.14.0
|
||||
diff --git a/dnf/cli/commands/history.py b/dnf/cli/commands/history.py
|
||||
index 293d93fc..21d04a1a 100644
|
||||
--- a/dnf/cli/commands/history.py
|
||||
+++ b/dnf/cli/commands/history.py
|
||||
@@ -223,6 +223,7 @@ class HistoryCommand(commands.Command):
|
||||
"Reinstall": "Reinstalled",
|
||||
"Obsoleted": "Install",
|
||||
"Obsolete": "Obsoleted",
|
||||
+ "Reason Change": "Reason Change",
|
||||
}
|
||||
|
||||
data = serialize_transaction(trans)
|
||||
@@ -235,6 +236,16 @@ class HistoryCommand(commands.Command):
|
||||
if ti["action"] == "Install" and ti.get("reason", None) == "clean":
|
||||
ti["reason"] = "dependency"
|
||||
|
||||
+ if ti["action"] == "Reason Change" and "nevra" in ti:
|
||||
+ subj = hawkey.Subject(ti["nevra"])
|
||||
+ nevra = subj.get_nevra_possibilities(forms=[hawkey.FORM_NEVRA])[0]
|
||||
+ reason = self.output.history.swdb.resolveRPMTransactionItemReason(
|
||||
+ nevra.name,
|
||||
+ nevra.arch,
|
||||
+ trans.tids()[0] - 1
|
||||
+ )
|
||||
+ ti["reason"] = libdnf.transaction.TransactionItemReasonToString(reason)
|
||||
+
|
||||
if ti.get("repo_id") == hawkey.SYSTEM_REPO_NAME:
|
||||
# erase repo_id, because it's not possible to perform forward actions from the @System repo
|
||||
ti["repo_id"] = None
|
||||
--
|
||||
2.35.1
|
||||
|
@ -1,30 +0,0 @@
|
||||
From 55f6691d5663c59b675064b04e19288365e92d24 Mon Sep 17 00:00:00 2001
|
||||
From: Nicola Sella <nsella@redhat.com>
|
||||
Date: Tue, 15 Mar 2022 16:26:10 +0100
|
||||
Subject: [PATCH] Fix remove when no repos are enabled (RhBz:2064341)
|
||||
|
||||
msg: When no repositories are enabled, dnf group exits and does not
|
||||
remove an installed group.
|
||||
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2064341
|
||||
type: bugfix
|
||||
---
|
||||
dnf/cli/commands/group.py | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dnf/cli/commands/group.py b/dnf/cli/commands/group.py
|
||||
index fd723c48..c5c23230 100644
|
||||
--- a/dnf/cli/commands/group.py
|
||||
+++ b/dnf/cli/commands/group.py
|
||||
@@ -358,7 +358,8 @@ class GroupCommand(commands.Command):
|
||||
else:
|
||||
demands.available_repos = True
|
||||
|
||||
- commands._checkEnabledRepo(self.base)
|
||||
+ if cmd not in ('remove'):
|
||||
+ commands._checkEnabledRepo(self.base)
|
||||
|
||||
if cmd in ('install', 'upgrade'):
|
||||
commands._checkGPGKey(self.base, self.cli)
|
||||
--
|
||||
2.35.1
|
||||
|
@ -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
|
||||
|
@ -1,30 +0,0 @@
|
||||
From 8f05ee29b7398fa6d18c7113a533f1d8726239df Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Rohel <jrohel@redhat.com>
|
||||
Date: Tue, 12 Apr 2022 12:25:05 +0200
|
||||
Subject: [PATCH] [doc] Improve "proxy" configuration option documentation
|
||||
(RhBug:2072332)
|
||||
|
||||
---
|
||||
doc/conf_ref.rst | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/doc/conf_ref.rst b/doc/conf_ref.rst
|
||||
index 75bcdf75..885a4560 100644
|
||||
--- a/doc/conf_ref.rst
|
||||
+++ b/doc/conf_ref.rst
|
||||
@@ -833,10 +833,10 @@ configuration.
|
||||
``proxy``
|
||||
:ref:`string <string-label>`
|
||||
|
||||
- URL of a proxy server to connect through. Set to an empty string to disable the proxy setting inherited from the main section and use direct connection instead. The expected format of this option is ``<scheme>://<ip-or-hostname>[:port]``.
|
||||
+ URL of a proxy server to connect through. Set to an empty string in the repository configuration to disable proxy setting inherited from the main section. The expected format of this option is ``<scheme>://<ip-or-hostname>[:port]``.
|
||||
(For backward compatibility, '_none_' can be used instead of the empty string.)
|
||||
|
||||
- Note: The curl environment variables (such as ``http_proxy``) are effective if this option is unset. See the ``curl`` man page for details.
|
||||
+ Note: The curl environment variables (such as ``http_proxy``) are effective if this option is unset (or '_none_' is set in the repository configuration). See the ``curl`` man page for details.
|
||||
|
||||
``proxy_username``
|
||||
:ref:`string <string-label>`
|
||||
--
|
||||
2.35.1
|
||||
|
@ -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
|
||||
|
@ -1,318 +0,0 @@
|
||||
From 88a6289a4f72b11253c01a5a5d834b74d5abb6c3 Mon Sep 17 00:00:00 2001
|
||||
From: Laszlo Ersek <lersek@redhat.com>
|
||||
Date: Sun, 24 Apr 2022 09:08:28 +0200
|
||||
Subject: [PATCH] Base.reset: plug (temporary) leak of libsolv's page file
|
||||
descriptors
|
||||
|
||||
Consider the following call paths (mixed Python and C), extending from
|
||||
livecd-creator down to libsolv:
|
||||
|
||||
main [livecd-tools/tools/livecd-creator]
|
||||
install() [livecd-tools/imgcreate/creator.py]
|
||||
fill_sack() [dnf/dnf/base.py]
|
||||
_add_repo_to_sack() [dnf/dnf/base.py]
|
||||
load_repo() [libdnf/python/hawkey/sack-py.cpp]
|
||||
dnf_sack_load_repo() [libdnf/libdnf/dnf-sack.cpp]
|
||||
write_main() [libdnf/libdnf/dnf-sack.cpp]
|
||||
repo_add_solv() [libsolv/src/repo_solv.c]
|
||||
repopagestore_read_or_setup_pages() [libsolv/src/repopage.c]
|
||||
dup()
|
||||
write_ext() [libdnf/libdnf/dnf-sack.cpp]
|
||||
repo_add_solv() [libsolv/src/repo_solv.c]
|
||||
repopagestore_read_or_setup_pages() [libsolv/src/repopage.c]
|
||||
dup()
|
||||
|
||||
The dup() calls create the following file descriptors (output from
|
||||
"lsof"):
|
||||
|
||||
> COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
|
||||
> python3 6500 root 7r REG 8,1 25320727 395438 /var/tmp/imgcreate-mytcghah/install_root/var/cache/dnf/fedora.solv (deleted)
|
||||
> python3 6500 root 8r REG 8,1 52531426 395450 /var/tmp/imgcreate-mytcghah/install_root/var/cache/dnf/fedora-filenames.solvx
|
||||
|
||||
These file descriptors are *owned* by the DnfSack object (which is derived
|
||||
from GObject), as follows:
|
||||
|
||||
sack->priv->pool->repos[1]->repodata[1]->store.pagefd = 7
|
||||
sack->priv->pool->repos[1]->repodata[2]->store.pagefd = 8
|
||||
^ ^ ^ ^ ^ ^ ^
|
||||
| | | | | | |
|
||||
| | | | | | int
|
||||
| | | | | Repopagestore [libsolv/src/repopage.h]
|
||||
| | | | Repodata [libsolv/src/repodata.h]
|
||||
| | | struct s_Repo [libsolv/src/repo.h]
|
||||
| | struct s_Pool (aka Pool) [libsolv/src/pool.h]
|
||||
| DnfSackPrivate [libdnf/libdnf/dnf-sack.cpp]
|
||||
DnfSack [libdnf/libdnf/dnf-sack.h]
|
||||
|
||||
The file descriptors are *supposed* to be closed on the following call
|
||||
path:
|
||||
|
||||
main [livecd-tools/tools/livecd-creator]
|
||||
install() [livecd-tools/imgcreate/creator.py]
|
||||
close() [livecd-tools/imgcreate/dnfinst.py]
|
||||
close() [dnf/dnf/base.py]
|
||||
reset() [dnf/dnf/base.py]
|
||||
_sack = None
|
||||
_goal = None
|
||||
_transaction = None
|
||||
...
|
||||
dnf_sack_finalize() [libdnf/libdnf/dnf-sack.cpp]
|
||||
pool_free() [libsolv/src/pool.c]
|
||||
pool_freeallrepos() [libsolv/src/pool.c]
|
||||
repo_freedata() [libsolv/src/repo.c]
|
||||
repodata_freedata() [libsolv/src/repodata.c]
|
||||
repopagestore_free() [libsolv/src/repopage.c]
|
||||
close()
|
||||
|
||||
Namely, when dnf.Base.reset() [dnf/dnf/base.py] is called with (sack=True,
|
||||
goal=True), the reference counts of the objects pointed to by the "_sack",
|
||||
"_goal" and "_transaction" fields are supposed to reach zero, and then, as
|
||||
part of the DnfSack object's finalization, the libsolv file descriptors
|
||||
are supposed to be closed.
|
||||
|
||||
Now, while this *may* happen immediately in dnf.Base.reset(), it may as
|
||||
well not. The reason is that there is a multitude of *circular references*
|
||||
between DnfSack and the packages that it contains. When dnf.Base.reset()
|
||||
is entered, we have the following picture:
|
||||
|
||||
_sack _goal
|
||||
| |
|
||||
v v
|
||||
+----------------+ +-------------+
|
||||
| DnfSack object | <--- | Goal object |
|
||||
+----------------+ +-------------+
|
||||
|^ |^ |^
|
||||
|| || ||
|
||||
|| || ||
|
||||
+--||----||----||---+
|
||||
| v| v| v| | <-- _transaction
|
||||
| Pkg1 Pkg2 PkgN |
|
||||
| |
|
||||
| Transaction oject |
|
||||
+-------------------+
|
||||
|
||||
That is, the reference count of the DnfSack object is (1 + 1 + N), where N
|
||||
is the number of packages in the transaction. Details:
|
||||
|
||||
(a) The first reference comes from the "_sack" field, established like
|
||||
this:
|
||||
|
||||
main [livecd-tools/tools/livecd-creator]
|
||||
install() [livecd-tools/imgcreate/creator.py]
|
||||
fill_sack() [dnf/dnf/base.py]
|
||||
_build_sack() [dnf/dnf/sack.py]
|
||||
Sack()
|
||||
sack_init() [libdnf/python/hawkey/sack-py.cpp]
|
||||
dnf_sack_new() [libdnf/libdnf/dnf-sack.cpp]
|
||||
|
||||
(b) The second reference on the DnfSack object comes from "_goal":
|
||||
|
||||
main [livecd-tools/tools/livecd-creator]
|
||||
install() [livecd-tools/imgcreate/creator.py]
|
||||
fill_sack() [dnf/dnf/base.py]
|
||||
_goal = Goal(_sack)
|
||||
goal_init() [libdnf/python/hawkey/goal-py.cpp]
|
||||
Py_INCREF(_sack)
|
||||
|
||||
(c) Then there is one reference to "_sack" *per package* in the
|
||||
transaction:
|
||||
|
||||
main [livecd-tools/tools/livecd-creator]
|
||||
install() [livecd-tools/imgcreate/creator.py]
|
||||
runInstall() [livecd-tools/imgcreate/dnfinst.py]
|
||||
resolve() [dnf/dnf/base.py]
|
||||
_goal2transaction() [dnf/dnf/base.py]
|
||||
list_installs() [libdnf/python/hawkey/goal-py.cpp]
|
||||
list_generic() [libdnf/python/hawkey/goal-py.cpp]
|
||||
packagelist_to_pylist() [libdnf/python/hawkey/iutil-py.cpp]
|
||||
new_package() [libdnf/python/hawkey/sack-py.cpp]
|
||||
Py_BuildValue()
|
||||
ts.add_install()
|
||||
|
||||
list_installs() creates a list of packages that need to be installed
|
||||
by DNF. Inside the loop in packagelist_to_pylist(), which constructs
|
||||
the elements of that list, Py_BuildValue() is called with the "O"
|
||||
format specifier, and that increases the reference count on "_sack".
|
||||
|
||||
Subsequently, in the _goal2transaction() method, we iterate over the
|
||||
package list created by list_installs(), and add each package to the
|
||||
transaction (ts.add_install()). After _goal2transaction() returns,
|
||||
this transaction is assigned to "self._transaction" in resolve(). This
|
||||
is where the last N (back-)references on the DnfSack object come from.
|
||||
|
||||
(d) Now, to quote the defintion of the DnfSack object
|
||||
("libdnf/docs/hawkey/tutorial-py.rst"):
|
||||
|
||||
> *Sack* is an abstraction for a collection of packages.
|
||||
|
||||
That's why the DnfSack object references all the Pkg1 through PkgN
|
||||
packages.
|
||||
|
||||
So, when the dnf.Base.reset() method completes, the picture changes like
|
||||
this:
|
||||
|
||||
_sack _goal
|
||||
| |
|
||||
-- [CUT] -- -- [CUT] --
|
||||
| |
|
||||
v | v
|
||||
+----------------+ [C] +-------------+
|
||||
| DnfSack object | <-[U]- | Goal object |
|
||||
+----------------+ [T] +-------------+
|
||||
|^ |^ |^ |
|
||||
|| || ||
|
||||
|| || || |
|
||||
+--||----||----||---+ [C]
|
||||
| v| v| v| | <--[U]-- _transaction
|
||||
| Pkg1 Pkg2 PkgN | [T]
|
||||
| | |
|
||||
| Transaction oject |
|
||||
+-------------------+
|
||||
|
||||
and we are left with N reference cycles (one between each package and the
|
||||
same DnfSack object).
|
||||
|
||||
This set of cycles can only be cleaned up by Python's generational garbage
|
||||
collector <https://stackify.com/python-garbage-collection/>. The GC will
|
||||
collect the DnfSack object, and consequently close the libsolv page file
|
||||
descriptors via dnf_sack_finalize() -- but garbage collection will happen
|
||||
*only eventually*, unpredictably.
|
||||
|
||||
This means that the dnf.Base.reset() method breaks its interface contract:
|
||||
|
||||
> Make the Base object forget about various things.
|
||||
|
||||
because the libsolv file descriptors can (and frequently do, in practice)
|
||||
survive dnf.Base.reset().
|
||||
|
||||
In general, as long as the garbage collector only tracks process-private
|
||||
memory blocks, there's nothing wrong; however, file descriptors are
|
||||
visible to the kernel. When dnf.Base.reset() *temporarily* leaks file
|
||||
descriptors as explained above, then immediately subsequent operations
|
||||
that depend on those file descriptors having been closed, can fail.
|
||||
|
||||
An example is livecd-creator's unmounting of:
|
||||
|
||||
/var/tmp/imgcreate-mytcghah/install_root/var/cache/dnf
|
||||
|
||||
which the kernel refuses, due to libsolv's still open file descriptors
|
||||
pointing into that filesystem:
|
||||
|
||||
> umount: /var/tmp/imgcreate-mytcghah/install_root/var/cache/dnf: target
|
||||
> is busy.
|
||||
> Unable to unmount /var/tmp/imgcreate-mytcghah/install_root/var/cache/dnf
|
||||
> normally, using lazy unmount
|
||||
|
||||
(Unfortunately, the whole lazy umount idea is misguided in livecd-tools;
|
||||
it's a misfeature that should be removed, as it permits the corruption of
|
||||
the loop-backed filesystem. Now that the real bug is being fixed in DNF,
|
||||
lazy umount is not needed as a (broken) workaround in livecd-tools. But
|
||||
that's a separate patch for livecd-tools:
|
||||
<https://github.com/livecd-tools/livecd-tools/pull/227>.)
|
||||
|
||||
Plug the fd leak by forcing a garbage collection in dnf.Base.reset()
|
||||
whenever we cut the "_sack", "_goal" and "_transaction" links -- that is,
|
||||
when the "sack" and "goal" parameters are True.
|
||||
|
||||
Note that precisely due to the unpredictable behavior of the garbage
|
||||
collector, reproducing the bug may prove elusive. In order to reproduce it
|
||||
deterministically, through usage with livecd-creator, disabling automatic
|
||||
garbage collection with the following patch (for livecd-tools) is
|
||||
sufficient:
|
||||
|
||||
> diff --git a/tools/livecd-creator b/tools/livecd-creator
|
||||
> index 291de10cbbf9..8d2c740c238b 100755
|
||||
> --- a/tools/livecd-creator
|
||||
> +++ b/tools/livecd-creator
|
||||
> @@ -31,6 +31,8 @@ from dnf.exceptions import Error as DnfBaseError
|
||||
> import imgcreate
|
||||
> from imgcreate.errors import KickstartError
|
||||
>
|
||||
> +import gc
|
||||
> +
|
||||
> class Usage(Exception):
|
||||
> def __init__(self, msg = None, no_error = False):
|
||||
> Exception.__init__(self, msg, no_error)
|
||||
> @@ -261,5 +263,6 @@ def do_nss_libs_hack():
|
||||
> return hack
|
||||
>
|
||||
> if __name__ == "__main__":
|
||||
> + gc.disable()
|
||||
> hack = do_nss_libs_hack()
|
||||
> sys.exit(main())
|
||||
|
||||
Also note that you need to use livecd-tools at git commit 4afde9352e82 or
|
||||
later, for this fix to make any difference: said commit fixes a different
|
||||
(independent) bug in livecd-tools that produces identical symptoms, but
|
||||
from a different origin. In other words, if you don't have commit
|
||||
4afde9352e82 in your livecd-tools install, then said bug in livecd-tools
|
||||
will mask this DNF fix.
|
||||
|
||||
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
|
||||
(cherry picked from commit 5ce5ed1ea08ad6e198c1c1642c4d9ea2db6eab86)
|
||||
---
|
||||
dnf/base.py | 41 +++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 41 insertions(+)
|
||||
|
||||
diff --git a/dnf/base.py b/dnf/base.py
|
||||
index babca31d..852fcdd8 100644
|
||||
--- a/dnf/base.py
|
||||
+++ b/dnf/base.py
|
||||
@@ -72,6 +72,7 @@ import dnf.transaction
|
||||
import dnf.util
|
||||
import dnf.yum.rpmtrans
|
||||
import functools
|
||||
+import gc
|
||||
import hawkey
|
||||
import itertools
|
||||
import logging
|
||||
@@ -568,6 +569,46 @@ class Base(object):
|
||||
self._comps_trans = dnf.comps.TransactionBunch()
|
||||
self._transaction = None
|
||||
self._update_security_filters = []
|
||||
+ if sack and goal:
|
||||
+ # We've just done this, above:
|
||||
+ #
|
||||
+ # _sack _goal
|
||||
+ # | |
|
||||
+ # -- [CUT] -- -- [CUT] --
|
||||
+ # | |
|
||||
+ # v | v
|
||||
+ # +----------------+ [C] +-------------+
|
||||
+ # | DnfSack object | <-[U]- | Goal object |
|
||||
+ # +----------------+ [T] +-------------+
|
||||
+ # |^ |^ |^ |
|
||||
+ # || || ||
|
||||
+ # || || || |
|
||||
+ # +--||----||----||---+ [C]
|
||||
+ # | v| v| v| | <--[U]-- _transaction
|
||||
+ # | Pkg1 Pkg2 PkgN | [T]
|
||||
+ # | | |
|
||||
+ # | Transaction oject |
|
||||
+ # +-------------------+
|
||||
+ #
|
||||
+ # At this point, the DnfSack object would be released only
|
||||
+ # eventually, by Python's generational garbage collector, due to the
|
||||
+ # cyclic references DnfSack<->Pkg1 ... DnfSack<->PkgN.
|
||||
+ #
|
||||
+ # The delayed release is a problem: the DnfSack object may
|
||||
+ # (indirectly) own "page file" file descriptors in libsolv, via
|
||||
+ # libdnf. For example,
|
||||
+ #
|
||||
+ # sack->priv->pool->repos[1]->repodata[1]->store.pagefd = 7
|
||||
+ # sack->priv->pool->repos[1]->repodata[2]->store.pagefd = 8
|
||||
+ #
|
||||
+ # These file descriptors are closed when the DnfSack object is
|
||||
+ # eventually released, that is, when dnf_sack_finalize() (in libdnf)
|
||||
+ # calls pool_free() (in libsolv).
|
||||
+ #
|
||||
+ # We need that to happen right now, as callers may want to unmount
|
||||
+ # the filesystems which those file descriptors refer to immediately
|
||||
+ # after reset() returns. Therefore, force a garbage collection here.
|
||||
+ gc.collect()
|
||||
|
||||
def _closeRpmDB(self):
|
||||
"""Closes down the instances of rpmdb that could be open."""
|
||||
--
|
||||
2.35.1
|
||||
|
@ -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
|
||||
|
@ -1,31 +0,0 @@
|
||||
From 00f3016ec0d79186f08c2f0ebf450bdc3dab1311 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
|
||||
Date: Thu, 23 Jun 2022 09:33:45 +0200
|
||||
Subject: [PATCH] doc: Describe how gpg keys are stored for `repo_ggpcheck`
|
||||
(RhBug:2020678)
|
||||
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=2020678
|
||||
---
|
||||
doc/conf_ref.rst | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/doc/conf_ref.rst b/doc/conf_ref.rst
|
||||
index 885a4560..decb49ff 100644
|
||||
--- a/doc/conf_ref.rst
|
||||
+++ b/doc/conf_ref.rst
|
||||
@@ -906,6 +906,12 @@ configuration.
|
||||
:ref:`boolean <boolean-label>`
|
||||
|
||||
Whether to perform GPG signature check on this repository's metadata. The default is False.
|
||||
+ Note that GPG keys for this check are stored separately from GPG keys used in package signature
|
||||
+ verification. Furthermore, they are also stored separately for each repository.
|
||||
+
|
||||
+ This means that dnf may ask to import the same key multiple times. For example, when a key was
|
||||
+ already imported for package signature verification and this option is turned on, it may be needed
|
||||
+ to import it again for the repository.
|
||||
|
||||
``retries``
|
||||
:ref:`integer <integer-label>`
|
||||
--
|
||||
2.36.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
|
||||
|
@ -1,64 +0,0 @@
|
||||
From 25bc75cbe63289864c09ab25144ee4af232bd8f4 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
|
||||
Date: Mon, 4 Jul 2022 09:43:25 +0200
|
||||
Subject: [PATCH] Add only relevant pkgs to upgrade transaction (RhBug:2097757)
|
||||
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=2097757
|
||||
|
||||
Without this patch dnf can create the following transaction during dnf upgrade --security when there is an advisory for B-2-2:
|
||||
|
||||
```
|
||||
repo @System 0 testtags <inline>
|
||||
#>=Pkg: A 1 1 x86_64
|
||||
#>=Pkg: B 1 1 x86_64
|
||||
#>=Req: A = 1-1
|
||||
|
||||
repo available 0 testtags <inline>
|
||||
#>=Pkg: A 2 2 x86_64
|
||||
#>=Pkg: B 2 2 x86_64
|
||||
#>=Req: A = 2-2
|
||||
system x86_64 rpm @System
|
||||
job update oneof A-1-1.x86_64@@System B-2-2.x86_64@available [targeted,setevr,setarch]
|
||||
result transaction,problems
|
||||
```
|
||||
|
||||
Problem is that without forcebest nothing gets upgraded despite the available advisory and --security switch.
|
||||
|
||||
This can also be seen in CI test case: rpm-software-management/ci-dnf-stack#1130
|
||||
---
|
||||
dnf/base.py | 19 ++++++++++++++++++-
|
||||
1 file changed, 18 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dnf/base.py b/dnf/base.py
|
||||
index 852fcdd8..82466831 100644
|
||||
--- a/dnf/base.py
|
||||
+++ b/dnf/base.py
|
||||
@@ -2135,7 +2135,24 @@ class Base(object):
|
||||
query.filterm(reponame=reponame)
|
||||
query = self._merge_update_filters(query, pkg_spec=pkg_spec, upgrade=True)
|
||||
if query:
|
||||
- query = query.union(installed_query.latest())
|
||||
+ # Given that we use libsolv's targeted transactions, we need to ensure that the transaction contains both
|
||||
+ # the new targeted version and also the current installed version (for the upgraded package). This is
|
||||
+ # because if it only contained the new version, libsolv would decide to reinstall the package even if it
|
||||
+ # had just a different buildtime or vendor but the same version
|
||||
+ # (https://github.com/openSUSE/libsolv/issues/287)
|
||||
+ # - In general, the query already contains both the new and installed versions but not always.
|
||||
+ # If repository-packages command is used, the installed packages are filtered out because they are from
|
||||
+ # the @system repo. We need to add them back in.
|
||||
+ # - However we need to add installed versions of just the packages that are being upgraded. We don't want
|
||||
+ # to add all installed packages because it could increase the number of solutions for the transaction
|
||||
+ # (especially without --best) and since libsolv prefers the smallest possible upgrade it could result
|
||||
+ # in no upgrade even if there is one available. This is a problem in general but its critical with
|
||||
+ # --security transactions (https://bugzilla.redhat.com/show_bug.cgi?id=2097757)
|
||||
+ # - We want to add only the latest versions of installed packages, this is specifically for installonly
|
||||
+ # packages. Otherwise if for example kernel-1 and kernel-3 were installed and present in the
|
||||
+ # transaction libsolv could decide to install kernel-2 because it is an upgrade for kernel-1 even
|
||||
+ # though we don't want it because there already is a newer version present.
|
||||
+ query = query.union(installed_query.latest().filter(name=[pkg.name for pkg in query]))
|
||||
sltr = dnf.selector.Selector(self.sack)
|
||||
sltr.set(pkg=query)
|
||||
self._goal.upgrade(select=sltr)
|
||||
--
|
||||
2.36.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
|
||||
|
@ -1,37 +0,0 @@
|
||||
From fea1f456d3d5f3015ebcff4008959916bdaaf6d6 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
|
||||
Date: Mon, 4 Jul 2022 09:46:29 +0200
|
||||
Subject: [PATCH] Use `installed_all` because `installed_query` is filtered
|
||||
user input
|
||||
|
||||
`installed_query` could be missing packages. If we specify we want to
|
||||
upgrade a specific nevra that is not yet installed, then `installed_query`
|
||||
is empty because it is based on user input, but there could be other
|
||||
versions of the pkg installed.
|
||||
|
||||
Eg: if kernel-1 and kernel-3 are installed and we specify we want to
|
||||
upgrade kernel-2, nothing should be done because we already have higher
|
||||
version, but now `installed_query` would be empty and kernel-2 would be
|
||||
installed.
|
||||
|
||||
Therefore, we need to use `installed_all`.
|
||||
---
|
||||
dnf/base.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dnf/base.py b/dnf/base.py
|
||||
index 82466831..e606d9fa 100644
|
||||
--- a/dnf/base.py
|
||||
+++ b/dnf/base.py
|
||||
@@ -2152,7 +2152,7 @@ class Base(object):
|
||||
# packages. Otherwise if for example kernel-1 and kernel-3 were installed and present in the
|
||||
# transaction libsolv could decide to install kernel-2 because it is an upgrade for kernel-1 even
|
||||
# though we don't want it because there already is a newer version present.
|
||||
- query = query.union(installed_query.latest().filter(name=[pkg.name for pkg in query]))
|
||||
+ query = query.union(installed_all.latest().filter(name=[pkg.name for pkg in query]))
|
||||
sltr = dnf.selector.Selector(self.sack)
|
||||
sltr.set(pkg=query)
|
||||
self._goal.upgrade(select=sltr)
|
||||
--
|
||||
2.36.1
|
||||
|
@ -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
|
||||
|
@ -1,47 +0,0 @@
|
||||
From 66a37245e82c60b972ee35879f9c29c27466a27b Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
|
||||
Date: Mon, 25 Jul 2022 12:44:17 +0200
|
||||
Subject: [PATCH] Don't include resolved advisories for obsoletes with sec.
|
||||
filters (RhBug:2101421)
|
||||
|
||||
This makes the obsoletes security filters consistent with upgrade
|
||||
security filters.
|
||||
|
||||
This API is used from check-update and from Info and List commands.
|
||||
- For check-update we don't want to include resolved advisories to have
|
||||
identical result to the actual update. That is bz2101421 use case.
|
||||
- For Info and List commands the --obsoletes switch: "List packages
|
||||
installed on the system that are obsoleted by packages in any known
|
||||
repository." Given this specification in makes sense not to
|
||||
consider resolved advisories when we also use security filters.
|
||||
|
||||
There is still a general case when someone uses the API or any potential
|
||||
future use and I think it is best to have the behavior unified for
|
||||
"upgrades" and "obsoletes".
|
||||
|
||||
= changelog =
|
||||
msg: Don't include resolved advisories for obsoletes filtering with security filters
|
||||
type: bugfix
|
||||
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2101421
|
||||
|
||||
Tests: https://github.com/rpm-software-management/ci-dnf-stack/pull/1134
|
||||
---
|
||||
dnf/base.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dnf/base.py b/dnf/base.py
|
||||
index e606d9fa..e623d98e 100644
|
||||
--- a/dnf/base.py
|
||||
+++ b/dnf/base.py
|
||||
@@ -1565,7 +1565,7 @@ class Base(object):
|
||||
obsoletes = query_for_repo(
|
||||
self.sack.query()).filter(obsoletes_by_priority=inst)
|
||||
# reduce a query to security upgrades if they are specified
|
||||
- obsoletes = self._merge_update_filters(obsoletes, warning=False)
|
||||
+ obsoletes = self._merge_update_filters(obsoletes, warning=False, upgrade=True)
|
||||
obsoletesTuples = []
|
||||
for new in obsoletes:
|
||||
obsoleted_reldeps = new.obsoletes
|
||||
--
|
||||
2.37.1
|
||||
|
@ -1,35 +0,0 @@
|
||||
From 553a2c585db50599d5028ea6bb6462281bb88d02 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Mracek <jmracek@redhat.com>
|
||||
Date: Mon, 11 Jul 2022 12:27:14 +0200
|
||||
Subject: [PATCH] Set default value for variable to prevent crash
|
||||
(RhBug:2091636)
|
||||
|
||||
It ensure that read of file ended successfully.
|
||||
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=2091636
|
||||
---
|
||||
dnf/conf/substitutions.py | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dnf/conf/substitutions.py b/dnf/conf/substitutions.py
|
||||
index 703e4a4f..1281bdf0 100644
|
||||
--- a/dnf/conf/substitutions.py
|
||||
+++ b/dnf/conf/substitutions.py
|
||||
@@ -53,6 +53,7 @@ class Substitutions(dict):
|
||||
continue
|
||||
for fsvar in fsvars:
|
||||
filepath = os.path.join(dir_fsvars, fsvar)
|
||||
+ val = None
|
||||
if os.path.isfile(filepath):
|
||||
try:
|
||||
with open(filepath) as fp:
|
||||
@@ -61,4 +62,5 @@ class Substitutions(dict):
|
||||
val = val[:-1]
|
||||
except (OSError, IOError):
|
||||
continue
|
||||
- self[fsvar] = val
|
||||
+ if val is not None:
|
||||
+ self[fsvar] = val
|
||||
--
|
||||
2.37.1
|
||||
|
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
|
||||
|
@ -1,31 +0,0 @@
|
||||
From 96a5bd61ab3b35f00f0b52bcd6428c7aea7d1ca5 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kolarik <jkolarik@redhat.com>
|
||||
Date: Wed, 7 Sep 2022 14:27:07 +0200
|
||||
Subject: [PATCH] Add doc related to --destdir and --downloadonly options
|
||||
(RhBug:2100811)
|
||||
|
||||
= changelog =
|
||||
type: bugfix
|
||||
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2100811
|
||||
---
|
||||
doc/command_ref.rst | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/doc/command_ref.rst b/doc/command_ref.rst
|
||||
index 42aec72c..7a02448c 100644
|
||||
--- a/doc/command_ref.rst
|
||||
+++ b/doc/command_ref.rst
|
||||
@@ -190,6 +190,10 @@ Options
|
||||
``--downloadonly``
|
||||
Download the resolved package set without performing any rpm transaction (install/upgrade/erase).
|
||||
|
||||
+ Packages are removed after the next successful transaction. This applies also when used together
|
||||
+ with ``--destdir`` option as the directory is considered as a part of the DNF cache. To persist
|
||||
+ the packages, use the ``download`` command instead.
|
||||
+
|
||||
``-e <error level>, --errorlevel=<error level>``
|
||||
Error output level. This is an integer value between 0 (no error output) and
|
||||
10 (shows all error messages), default is 3. Deprecated, use ``-v`` instead.
|
||||
--
|
||||
2.37.1
|
||||
|
@ -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
|
||||
|
@ -1,79 +0,0 @@
|
||||
From aa724a639a641943ecf39038fd694abc2037e66d Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kolarik <jkolarik@redhat.com>
|
||||
Date: Mon, 22 Aug 2022 10:38:30 +0200
|
||||
Subject: [PATCH] Expose plugin unload method to API (RhBug:2047251)
|
||||
|
||||
= changelog =
|
||||
type: bugfix
|
||||
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2047251
|
||||
---
|
||||
dnf/base.py | 5 +++++
|
||||
dnf/plugin.py | 1 +
|
||||
doc/api_base.rst | 4 ++++
|
||||
tests/api/test_dnf_base.py | 7 +++++++
|
||||
4 files changed, 17 insertions(+)
|
||||
|
||||
diff --git a/dnf/base.py b/dnf/base.py
|
||||
index e623d98e..4ddfae15 100644
|
||||
--- a/dnf/base.py
|
||||
+++ b/dnf/base.py
|
||||
@@ -316,6 +316,11 @@ class Base(object):
|
||||
"""Run plugins configure() method."""
|
||||
self._plugins._run_config()
|
||||
|
||||
+ def unload_plugins(self):
|
||||
+ # :api
|
||||
+ """Run plugins unload() method."""
|
||||
+ self._plugins._unload()
|
||||
+
|
||||
def update_cache(self, timer=False):
|
||||
# :api
|
||||
|
||||
diff --git a/dnf/plugin.py b/dnf/plugin.py
|
||||
index 06066e79..87c1f08f 100644
|
||||
--- a/dnf/plugin.py
|
||||
+++ b/dnf/plugin.py
|
||||
@@ -164,6 +164,7 @@ class Plugins(object):
|
||||
self._caller('transaction')
|
||||
|
||||
def _unload(self):
|
||||
+ logger.debug(_('Plugins were unloaded'))
|
||||
del sys.modules[DYNAMIC_PACKAGE]
|
||||
|
||||
def unload_removed_plugins(self, transaction):
|
||||
diff --git a/doc/api_base.rst b/doc/api_base.rst
|
||||
index 03396b69..35cbeef5 100644
|
||||
--- a/doc/api_base.rst
|
||||
+++ b/doc/api_base.rst
|
||||
@@ -97,6 +97,10 @@
|
||||
|
||||
Configure plugins by running their configure() method.
|
||||
|
||||
+ .. method:: unload_plugins()
|
||||
+
|
||||
+ Unload all plugins.
|
||||
+
|
||||
.. method:: fill_sack([load_system_repo=True, load_available_repos=True])
|
||||
|
||||
Setup the package sack. If `load_system_repo` is ``True``, load information about packages in the local RPMDB into the sack. Else no package is considered installed during dependency solving. If `load_available_repos` is ``True``, load information about packages from the available repositories into the sack.
|
||||
diff --git a/tests/api/test_dnf_base.py b/tests/api/test_dnf_base.py
|
||||
index 33598189..e84e272b 100644
|
||||
--- a/tests/api/test_dnf_base.py
|
||||
+++ b/tests/api/test_dnf_base.py
|
||||
@@ -95,6 +95,13 @@ class DnfBaseApiTest(TestCase):
|
||||
|
||||
self.base.configure_plugins()
|
||||
|
||||
+ def test_unload_plugins(self):
|
||||
+ # Base.unload_plugins()
|
||||
+ self.assertHasAttr(self.base, "unload_plugins")
|
||||
+
|
||||
+ self.base.init_plugins()
|
||||
+ self.base.unload_plugins()
|
||||
+
|
||||
def test_update_cache(self):
|
||||
# Base.update_cache(self, timer=False)
|
||||
self.assertHasAttr(self.base, "update_cache")
|
||||
--
|
||||
2.37.1
|
||||
|
@ -1,105 +0,0 @@
|
||||
From 7ba2cd6a86945e0ec6f9ed866e2ef6b6759ee092 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kolarik <jkolarik@redhat.com>
|
||||
Date: Thu, 25 Aug 2022 08:06:34 +0200
|
||||
Subject: [PATCH] Add support for group upgrade rollback (RhBug:2016070)
|
||||
|
||||
= changelog =
|
||||
type: bugfix
|
||||
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2016070
|
||||
---
|
||||
dnf/db/group.py | 8 +++++++-
|
||||
dnf/transaction_sr.py | 24 ++++++++++++++++++++++++
|
||||
2 files changed, 31 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dnf/db/group.py b/dnf/db/group.py
|
||||
index 4dc8cb06..312e3b98 100644
|
||||
--- a/dnf/db/group.py
|
||||
+++ b/dnf/db/group.py
|
||||
@@ -34,14 +34,16 @@ class PersistorBase(object):
|
||||
self._installed = {}
|
||||
self._removed = {}
|
||||
self._upgraded = {}
|
||||
+ self._downgraded = {}
|
||||
|
||||
def __len__(self):
|
||||
- return len(self._installed) + len(self._removed) + len(self._upgraded)
|
||||
+ return len(self._installed) + len(self._removed) + len(self._upgraded) + len(self._downgraded)
|
||||
|
||||
def clean(self):
|
||||
self._installed = {}
|
||||
self._removed = {}
|
||||
self._upgraded = {}
|
||||
+ self._downgraded = {}
|
||||
|
||||
def _get_obj_id(self, obj):
|
||||
raise NotImplementedError
|
||||
@@ -62,6 +64,10 @@ class PersistorBase(object):
|
||||
self._upgraded[self._get_obj_id(obj)] = obj
|
||||
self._add_to_history(obj, libdnf.transaction.TransactionItemAction_UPGRADE)
|
||||
|
||||
+ def downgrade(self, obj):
|
||||
+ self._downgraded[self._get_obj_id(obj)] = obj
|
||||
+ self._add_to_history(obj, libdnf.transaction.TransactionItemAction_DOWNGRADE)
|
||||
+
|
||||
def new(self, obj_id, name, translated_name, pkg_types):
|
||||
raise NotImplementedError
|
||||
|
||||
diff --git a/dnf/transaction_sr.py b/dnf/transaction_sr.py
|
||||
index dae8d300..5d403a3e 100644
|
||||
--- a/dnf/transaction_sr.py
|
||||
+++ b/dnf/transaction_sr.py
|
||||
@@ -416,6 +416,16 @@ class TransactionReplay(object):
|
||||
if swdb_group is not None:
|
||||
self._base.history.group.upgrade(swdb_group)
|
||||
|
||||
+ def _swdb_group_downgrade(self, group_id, pkg_types, pkgs):
|
||||
+ if not self._base.history.group.get(group_id):
|
||||
+ self._raise_or_warn(self._ignore_installed, _("Group id '%s' is not installed.") % group_id)
|
||||
+ return
|
||||
+
|
||||
+ swdb_group = self._create_swdb_group(group_id, pkg_types, pkgs)
|
||||
+
|
||||
+ if swdb_group is not None:
|
||||
+ self._base.history.group.downgrade(swdb_group)
|
||||
+
|
||||
def _swdb_group_remove(self, group_id, pkg_types, pkgs):
|
||||
if not self._base.history.group.get(group_id):
|
||||
self._raise_or_warn(self._ignore_installed, _("Group id '%s' is not installed.") % group_id)
|
||||
@@ -482,6 +492,16 @@ class TransactionReplay(object):
|
||||
if swdb_env is not None:
|
||||
self._base.history.env.upgrade(swdb_env)
|
||||
|
||||
+ def _swdb_environment_downgrade(self, env_id, pkg_types, groups):
|
||||
+ if not self._base.history.env.get(env_id):
|
||||
+ self._raise_or_warn(self._ignore_installed, _("Environment id '%s' is not installed.") % env_id)
|
||||
+ return
|
||||
+
|
||||
+ swdb_env = self._create_swdb_environment(env_id, pkg_types, groups)
|
||||
+
|
||||
+ if swdb_env is not None:
|
||||
+ self._base.history.env.downgrade(swdb_env)
|
||||
+
|
||||
def _swdb_environment_remove(self, env_id, pkg_types, groups):
|
||||
if not self._base.history.env.get(env_id):
|
||||
self._raise_or_warn(self._ignore_installed, _("Environment id '%s' is not installed.") % env_id)
|
||||
@@ -535,6 +555,8 @@ class TransactionReplay(object):
|
||||
self._swdb_group_install(group_id, pkg_types, group_data["packages"])
|
||||
elif action == "Upgrade":
|
||||
self._swdb_group_upgrade(group_id, pkg_types, group_data["packages"])
|
||||
+ elif action == "Downgraded":
|
||||
+ self._swdb_group_downgrade(group_id, pkg_types, group_data["packages"])
|
||||
elif action == "Removed":
|
||||
self._swdb_group_remove(group_id, pkg_types, group_data["packages"])
|
||||
else:
|
||||
@@ -564,6 +586,8 @@ class TransactionReplay(object):
|
||||
self._swdb_environment_install(env_id, pkg_types, env_data["groups"])
|
||||
elif action == "Upgrade":
|
||||
self._swdb_environment_upgrade(env_id, pkg_types, env_data["groups"])
|
||||
+ elif action == "Downgraded":
|
||||
+ self._swdb_environment_downgrade(env_id, pkg_types, env_data["groups"])
|
||||
elif action == "Removed":
|
||||
self._swdb_environment_remove(env_id, pkg_types, env_data["groups"])
|
||||
else:
|
||||
--
|
||||
2.37.1
|
||||
|
@ -1,9 +1,7 @@
|
||||
From a1feaf8c26433325dd939a4bb0c47b50b44cfe2d Mon Sep 17 00:00:00 2001
|
||||
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 48/49] smtplib: catch OSError, not SMTPException
|
||||
|
||||
Upstream commit: aab7defca4fd827ede02336e5a0cf95e8691fb74
|
||||
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,
|
||||
@ -13,7 +11,6 @@ and are not caught.
|
||||
The more generic OSError should be caught here instead.
|
||||
|
||||
Resolves #1905
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-46030
|
||||
---
|
||||
dnf/automatic/emitter.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
@ -32,5 +29,5 @@ index 4aea4b02..648f1a1d 100644
|
||||
self._conf.email_host, exc)
|
||||
logger.error(msg)
|
||||
--
|
||||
2.48.1
|
||||
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
|
||||
|
@ -1,34 +0,0 @@
|
||||
From 46562dc76e50d86eed99a102af74a1187a4303e4 Mon Sep 17 00:00:00 2001
|
||||
From: Nicola Sella <nsella@redhat.com>
|
||||
Date: Thu, 11 Aug 2022 13:56:11 +0200
|
||||
Subject: [PATCH] Fix upgrade from file to noarch pkg (RhBug:2006018)
|
||||
|
||||
= changelog =
|
||||
msg: Fix upgrade pkg from file when installed pkg is noarch and upgrades
|
||||
to a different arch
|
||||
type: bugfix
|
||||
resolves: https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=2006018
|
||||
---
|
||||
dnf/base.py | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/dnf/base.py b/dnf/base.py
|
||||
index 4ddfae15..aba411ea 100644
|
||||
--- a/dnf/base.py
|
||||
+++ b/dnf/base.py
|
||||
@@ -2109,7 +2109,11 @@ class Base(object):
|
||||
sltr.set(pkg=[pkg])
|
||||
self._goal.upgrade(select=sltr)
|
||||
return 1
|
||||
- q = installed.filter(name=pkg.name, arch=[pkg.arch, "noarch"])
|
||||
+ # do not filter by arch if the package is noarch
|
||||
+ if pkg.arch == "noarch":
|
||||
+ q = installed.filter(name=pkg.name)
|
||||
+ else:
|
||||
+ q = installed.filter(name=pkg.name, arch=[pkg.arch, "noarch"])
|
||||
if not q:
|
||||
msg = _("Package %s not installed, cannot update it.")
|
||||
logger.warning(msg, pkg.name)
|
||||
--
|
||||
2.37.1
|
||||
|
@ -1,62 +0,0 @@
|
||||
From 7a265cf17fe3531e45dde8ae622c496bef1e17ae Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kolarik <jkolarik@redhat.com>
|
||||
Date: Wed, 10 Aug 2022 16:24:08 +0200
|
||||
Subject: [PATCH] Allow passing plugin parameters with dashes in names
|
||||
(RhBug:1980712)
|
||||
|
||||
= changelog =
|
||||
type: bugfix
|
||||
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1980712
|
||||
---
|
||||
dnf/plugin.py | 20 +++++++++++++++++---
|
||||
1 file changed, 17 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dnf/plugin.py b/dnf/plugin.py
|
||||
index 87c1f08f..b083727d 100644
|
||||
--- a/dnf/plugin.py
|
||||
+++ b/dnf/plugin.py
|
||||
@@ -225,17 +225,17 @@ def _get_plugins_files(paths, disable_plugins, enable_plugins):
|
||||
matched = True
|
||||
enable_pattern_tested = False
|
||||
for pattern_skip in disable_plugins:
|
||||
- if fnmatch.fnmatch(plugin_name, pattern_skip):
|
||||
+ if _plugin_name_matches_pattern(plugin_name, pattern_skip):
|
||||
pattern_disable_found.add(pattern_skip)
|
||||
matched = False
|
||||
for pattern_enable in enable_plugins:
|
||||
- if fnmatch.fnmatch(plugin_name, pattern_enable):
|
||||
+ if _plugin_name_matches_pattern(plugin_name, pattern_enable):
|
||||
matched = True
|
||||
pattern_enable_found.add(pattern_enable)
|
||||
enable_pattern_tested = True
|
||||
if not enable_pattern_tested:
|
||||
for pattern_enable in enable_plugins:
|
||||
- if fnmatch.fnmatch(plugin_name, pattern_enable):
|
||||
+ if _plugin_name_matches_pattern(plugin_name, pattern_enable):
|
||||
pattern_enable_found.add(pattern_enable)
|
||||
if matched:
|
||||
plugins.append(fn)
|
||||
@@ -250,6 +250,20 @@ def _get_plugins_files(paths, disable_plugins, enable_plugins):
|
||||
return plugins
|
||||
|
||||
|
||||
+def _plugin_name_matches_pattern(plugin_name, pattern):
|
||||
+ """
|
||||
+ Checks plugin name matches the pattern.
|
||||
+
|
||||
+ The alternative plugin name using dashes instead of underscores is tried
|
||||
+ in case of original name is not matched.
|
||||
+
|
||||
+ (see https://bugzilla.redhat.com/show_bug.cgi?id=1980712)
|
||||
+ """
|
||||
+
|
||||
+ try_names = set((plugin_name, plugin_name.replace('_', '-')))
|
||||
+ return any(fnmatch.fnmatch(name, pattern) for name in try_names)
|
||||
+
|
||||
+
|
||||
def register_command(command_class):
|
||||
# :api
|
||||
"""A class decorator for automatic command registration."""
|
||||
--
|
||||
2.37.1
|
||||
|
@ -1,7 +1,10 @@
|
||||
From 201675a56b89d6f3543ce5d734deebe6c4d9049f Mon Sep 17 00:00:00 2001
|
||||
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 49/49] automatic: Check availability of config file
|
||||
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
|
||||
@ -38,14 +41,14 @@ ConfigParser.read = ConfigParser__newRead
|
||||
|
||||
Resolves: https://issues.redhat.com/browse/RHEL-46030
|
||||
---
|
||||
dnf/automatic/main.py | 16 ++++++++++++++--
|
||||
1 file changed, 14 insertions(+), 2 deletions(-)
|
||||
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 ccd9ab64..3d73ffce 100644
|
||||
index caef627f..bb0bd493 100644
|
||||
--- a/dnf/automatic/main.py
|
||||
+++ b/dnf/automatic/main.py
|
||||
@@ -73,7 +73,7 @@ def build_emitters(conf):
|
||||
@@ -74,7 +74,7 @@ def build_emitters(conf):
|
||||
|
||||
def parse_arguments(args):
|
||||
parser = argparse.ArgumentParser()
|
||||
@ -54,7 +57,7 @@ index ccd9ab64..3d73ffce 100644
|
||||
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')
|
||||
@@ -88,7 +88,17 @@ def parse_arguments(args):
|
||||
@@ -89,7 +89,17 @@ def parse_arguments(args):
|
||||
class AutomaticConfig(object):
|
||||
def __init__(self, filename=None, downloadupdates=None,
|
||||
installupdates=None):
|
||||
@ -73,15 +76,6 @@ index ccd9ab64..3d73ffce 100644
|
||||
filename = dnf.const.CONF_AUTOMATIC_FILENAME
|
||||
self.commands = CommandsConfig()
|
||||
self.email = EmailConfig()
|
||||
@@ -295,6 +305,8 @@ 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,
|
||||
--
|
||||
2.48.1
|
||||
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
|
||||
|
@ -1,58 +0,0 @@
|
||||
From a32b2f7d596247124ad6ff5ab71bc83bf78f0518 Mon Sep 17 00:00:00 2001
|
||||
From: Jan Kolarik <jkolarik@redhat.com>
|
||||
Date: Tue, 13 Sep 2022 13:55:35 +0200
|
||||
Subject: [PATCH] Add support for rollback of group upgrade rollback
|
||||
(RhBug:2016070)
|
||||
|
||||
= changelog =
|
||||
type: bugfix
|
||||
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2016070
|
||||
---
|
||||
dnf/transaction_sr.py | 20 ++++++++++++--------
|
||||
1 file changed, 12 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/dnf/transaction_sr.py b/dnf/transaction_sr.py
|
||||
index 5d403a3e..b389f152 100644
|
||||
--- a/dnf/transaction_sr.py
|
||||
+++ b/dnf/transaction_sr.py
|
||||
@@ -553,12 +553,14 @@ class TransactionReplay(object):
|
||||
|
||||
if action == "Install":
|
||||
self._swdb_group_install(group_id, pkg_types, group_data["packages"])
|
||||
- elif action == "Upgrade":
|
||||
- self._swdb_group_upgrade(group_id, pkg_types, group_data["packages"])
|
||||
- elif action == "Downgraded":
|
||||
- self._swdb_group_downgrade(group_id, pkg_types, group_data["packages"])
|
||||
elif action == "Removed":
|
||||
self._swdb_group_remove(group_id, pkg_types, group_data["packages"])
|
||||
+ # Groups are not versioned, but a reverse transaction could be applied,
|
||||
+ # therefore we treat both actions the same way
|
||||
+ elif action == "Upgrade" or action == "Upgraded":
|
||||
+ self._swdb_group_upgrade(group_id, pkg_types, group_data["packages"])
|
||||
+ elif action == "Downgrade" or action == "Downgraded":
|
||||
+ self._swdb_group_downgrade(group_id, pkg_types, group_data["packages"])
|
||||
else:
|
||||
errors.append(TransactionError(
|
||||
_('Unexpected value of group action "{action}" for group "{group}".')
|
||||
@@ -584,12 +586,14 @@ class TransactionReplay(object):
|
||||
|
||||
if action == "Install":
|
||||
self._swdb_environment_install(env_id, pkg_types, env_data["groups"])
|
||||
- elif action == "Upgrade":
|
||||
- self._swdb_environment_upgrade(env_id, pkg_types, env_data["groups"])
|
||||
- elif action == "Downgraded":
|
||||
- self._swdb_environment_downgrade(env_id, pkg_types, env_data["groups"])
|
||||
elif action == "Removed":
|
||||
self._swdb_environment_remove(env_id, pkg_types, env_data["groups"])
|
||||
+ # Environments are not versioned, but a reverse transaction could be applied,
|
||||
+ # therefore we treat both actions the same way
|
||||
+ elif action == "Upgrade" or action == "Upgraded":
|
||||
+ self._swdb_environment_upgrade(env_id, pkg_types, env_data["groups"])
|
||||
+ elif action == "Downgrade" or action == "Downgraded":
|
||||
+ self._swdb_environment_downgrade(env_id, pkg_types, env_data["groups"])
|
||||
else:
|
||||
errors.append(TransactionError(
|
||||
_('Unexpected value of environment action "{action}" for environment "{env}".')
|
||||
--
|
||||
2.37.3
|
||||
|
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
|
||||
|
@ -1,114 +0,0 @@
|
||||
From f1fbef17862e033bf9518bd318339b405f2664dd Mon Sep 17 00:00:00 2001
|
||||
From: Nicola Sella <nsella@redhat.com>
|
||||
Date: Mon, 22 Mar 2021 17:37:51 +0100
|
||||
Subject: [PATCH 1/2] Better explain traceback of rpm.error with dnf
|
||||
|
||||
=changelog=
|
||||
msg: Add dnf.error message to explain rpm.error traceback when package not found after resolving a transaction
|
||||
type: bugfix
|
||||
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1815327
|
||||
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1887293
|
||||
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1909845
|
||||
---
|
||||
dnf/db/group.py | 78 ++++++++++++++++++++++++++-----------------------
|
||||
1 file changed, 41 insertions(+), 37 deletions(-)
|
||||
|
||||
diff --git a/dnf/db/group.py b/dnf/db/group.py
|
||||
index 312e3b98..3a17019a 100644
|
||||
--- a/dnf/db/group.py
|
||||
+++ b/dnf/db/group.py
|
||||
@@ -26,6 +26,7 @@ import dnf.exceptions
|
||||
from dnf.i18n import _
|
||||
from dnf.util import logger
|
||||
|
||||
+import rpm
|
||||
|
||||
class PersistorBase(object):
|
||||
def __init__(self, history):
|
||||
@@ -316,43 +317,46 @@ class RPMTransaction(object):
|
||||
modular_problems = 0
|
||||
|
||||
for tsi in self:
|
||||
- if tsi.action == libdnf.transaction.TransactionItemAction_DOWNGRADE:
|
||||
- hdr = tsi.pkg._header
|
||||
- modular_problems += self._test_fail_safe(hdr, tsi.pkg)
|
||||
- ts.addInstall(hdr, tsi, 'u')
|
||||
- elif tsi.action == libdnf.transaction.TransactionItemAction_DOWNGRADED:
|
||||
- ts.addErase(tsi.pkg.idx)
|
||||
- elif tsi.action == libdnf.transaction.TransactionItemAction_INSTALL:
|
||||
- hdr = tsi.pkg._header
|
||||
- modular_problems += self._test_fail_safe(hdr, tsi.pkg)
|
||||
- ts.addInstall(hdr, tsi, 'i')
|
||||
- elif tsi.action == libdnf.transaction.TransactionItemAction_OBSOLETE:
|
||||
- hdr = tsi.pkg._header
|
||||
- modular_problems += self._test_fail_safe(hdr, tsi.pkg)
|
||||
- ts.addInstall(hdr, tsi, 'u')
|
||||
- elif tsi.action == libdnf.transaction.TransactionItemAction_OBSOLETED:
|
||||
- ts.addErase(tsi.pkg.idx)
|
||||
- elif tsi.action == libdnf.transaction.TransactionItemAction_REINSTALL:
|
||||
- # note: in rpm 4.12 there should not be set
|
||||
- # rpm.RPMPROB_FILTER_REPLACEPKG to work
|
||||
- hdr = tsi.pkg._header
|
||||
- modular_problems += self._test_fail_safe(hdr, tsi.pkg)
|
||||
- ts.addReinstall(hdr, tsi)
|
||||
- elif tsi.action == libdnf.transaction.TransactionItemAction_REINSTALLED:
|
||||
- # Required when multiple packages with the same NEVRA marked as installed
|
||||
- ts.addErase(tsi.pkg.idx)
|
||||
- elif tsi.action == libdnf.transaction.TransactionItemAction_REMOVE:
|
||||
- ts.addErase(tsi.pkg.idx)
|
||||
- elif tsi.action == libdnf.transaction.TransactionItemAction_UPGRADE:
|
||||
- hdr = tsi.pkg._header
|
||||
- modular_problems += self._test_fail_safe(hdr, tsi.pkg)
|
||||
- ts.addInstall(hdr, tsi, 'u')
|
||||
- elif tsi.action == libdnf.transaction.TransactionItemAction_UPGRADED:
|
||||
- ts.addErase(tsi.pkg.idx)
|
||||
- elif tsi.action == libdnf.transaction.TransactionItemAction_REASON_CHANGE:
|
||||
- pass
|
||||
- else:
|
||||
- raise RuntimeError("TransactionItemAction not handled: %s" % tsi.action)
|
||||
+ try:
|
||||
+ if tsi.action == libdnf.transaction.TransactionItemAction_DOWNGRADE:
|
||||
+ hdr = tsi.pkg._header
|
||||
+ modular_problems += self._test_fail_safe(hdr, tsi.pkg)
|
||||
+ ts.addInstall(hdr, tsi, 'u')
|
||||
+ elif tsi.action == libdnf.transaction.TransactionItemAction_DOWNGRADED:
|
||||
+ ts.addErase(tsi.pkg.idx)
|
||||
+ elif tsi.action == libdnf.transaction.TransactionItemAction_INSTALL:
|
||||
+ hdr = tsi.pkg._header
|
||||
+ modular_problems += self._test_fail_safe(hdr, tsi.pkg)
|
||||
+ ts.addInstall(hdr, tsi, 'i')
|
||||
+ elif tsi.action == libdnf.transaction.TransactionItemAction_OBSOLETE:
|
||||
+ hdr = tsi.pkg._header
|
||||
+ modular_problems += self._test_fail_safe(hdr, tsi.pkg)
|
||||
+ ts.addInstall(hdr, tsi, 'u')
|
||||
+ elif tsi.action == libdnf.transaction.TransactionItemAction_OBSOLETED:
|
||||
+ ts.addErase(tsi.pkg.idx)
|
||||
+ elif tsi.action == libdnf.transaction.TransactionItemAction_REINSTALL:
|
||||
+ # note: in rpm 4.12 there should not be set
|
||||
+ # rpm.RPMPROB_FILTER_REPLACEPKG to work
|
||||
+ hdr = tsi.pkg._header
|
||||
+ modular_problems += self._test_fail_safe(hdr, tsi.pkg)
|
||||
+ ts.addReinstall(hdr, tsi)
|
||||
+ elif tsi.action == libdnf.transaction.TransactionItemAction_REINSTALLED:
|
||||
+ # Required when multiple packages with the same NEVRA marked as installed
|
||||
+ ts.addErase(tsi.pkg.idx)
|
||||
+ elif tsi.action == libdnf.transaction.TransactionItemAction_REMOVE:
|
||||
+ ts.addErase(tsi.pkg.idx)
|
||||
+ elif tsi.action == libdnf.transaction.TransactionItemAction_UPGRADE:
|
||||
+ hdr = tsi.pkg._header
|
||||
+ modular_problems += self._test_fail_safe(hdr, tsi.pkg)
|
||||
+ ts.addInstall(hdr, tsi, 'u')
|
||||
+ elif tsi.action == libdnf.transaction.TransactionItemAction_UPGRADED:
|
||||
+ ts.addErase(tsi.pkg.idx)
|
||||
+ elif tsi.action == libdnf.transaction.TransactionItemAction_REASON_CHANGE:
|
||||
+ pass
|
||||
+ else:
|
||||
+ raise RuntimeError("TransactionItemAction not handled: %s" % tsi.action)
|
||||
+ except rpm.error as e:
|
||||
+ raise dnf.exceptions.Error(_("An rpm exception occurred: %s" % e))
|
||||
if modular_problems:
|
||||
raise dnf.exceptions.Error(_("No available modular metadata for modular package"))
|
||||
|
||||
--
|
||||
2.39.0
|
||||
|
@ -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
|
||||
|
File diff suppressed because it is too large
Load Diff
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
|
||||
|
@ -1,85 +0,0 @@
|
||||
From 29f4df4bf7bf7cb9099dbc7c834441ce4e75b623 Mon Sep 17 00:00:00 2001
|
||||
From: Miro Hrončok <miro@hroncok.cz>
|
||||
Date: Wed, 23 Feb 2022 13:25:12 +0100
|
||||
Subject: [PATCH] RHEL-1245: Remove /usr/bin from sys.path to avoid accidentally importing garbage
|
||||
|
||||
See https://bugzilla.redhat.com/show_bug.cgi?id=2057340
|
||||
and https://github.com/benjaminp/six/issues/359
|
||||
|
||||
dnf should never import Python modules from /usr/bin but users can
|
||||
have files in there that look like Python modules and Python will
|
||||
try to import them and fail.
|
||||
|
||||
Consider a tool that is *not* written in Python and is called "copy.pyc".
|
||||
Naturally, it resides in /usr/bin/copy.pyc and dnf fails:
|
||||
|
||||
Traceback (most recent call last):
|
||||
File "/usr/bin/dnf", line 57, in <module>
|
||||
from dnf.cli import main
|
||||
File "/usr/lib/python3.10/site-packages/dnf/__init__.py", line 30, in <module>
|
||||
import dnf.base
|
||||
File "/usr/lib/python3.10/site-packages/dnf/base.py", line 31, in <module>
|
||||
from copy import deepcopy
|
||||
ImportError: bad magic number in 'copy': b'...'
|
||||
|
||||
Similarly, a tool actually written in Python, called "copy.py"
|
||||
might as well own /usr/bin/copy.py and dnf fails as well:
|
||||
|
||||
Traceback (most recent call last):
|
||||
File "/usr/bin/dnf", line 57, in <module>
|
||||
from dnf.cli import main
|
||||
File "/usr/lib/python3.10/site-packages/dnf/__init__.py", line 30, in <module>
|
||||
import dnf.base
|
||||
File "/usr/lib/python3.10/site-packages/dnf/base.py", line 31, in <module>
|
||||
from copy import deepcopy
|
||||
ImportError: cannot import name 'deepcopy' from 'copy' (/usr/bin/copy.py)
|
||||
|
||||
Either problem can happen for a variety of names.
|
||||
We better not let that happen.
|
||||
|
||||
A more general solution that would prevent Python doing this entirely
|
||||
does not exists yet, see https://discuss.python.org/t/4235
|
||||
|
||||
Hence, proposing this to dnf, which is a critical piece of the system.
|
||||
---
|
||||
bin/dnf-automatic.in | 6 +++++-
|
||||
bin/dnf.in | 6 +++++-
|
||||
2 files changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/bin/dnf-automatic.in b/bin/dnf-automatic.in
|
||||
index 5b06aa2..17e35a0 100755
|
||||
--- a/bin/dnf-automatic.in
|
||||
+++ b/bin/dnf-automatic.in
|
||||
@@ -23,7 +23,11 @@ import os
|
||||
import sys
|
||||
|
||||
here = sys.path[0]
|
||||
-if here != '/usr/bin':
|
||||
+if here == '/usr/bin':
|
||||
+ # we never import Python modules from /usr/bin
|
||||
+ # removing this lowers the risk of accidental imports of weird files
|
||||
+ del sys.path[0]
|
||||
+else:
|
||||
# git checkout
|
||||
dnf_toplevel = os.path.dirname(here)
|
||||
sys.path[0] = dnf_toplevel
|
||||
diff --git a/bin/dnf.in b/bin/dnf.in
|
||||
index 645d0f0..55ceb3f 100755
|
||||
--- a/bin/dnf.in
|
||||
+++ b/bin/dnf.in
|
||||
@@ -48,7 +48,11 @@ if __name__ != "__main__":
|
||||
sys.exit(1)
|
||||
|
||||
here = sys.path[0]
|
||||
-if here != '/usr/bin':
|
||||
+if here == '/usr/bin':
|
||||
+ # we never import Python modules from /usr/bin
|
||||
+ # removing this lowers the risk of accidental imports of weird files
|
||||
+ del sys.path[0]
|
||||
+else:
|
||||
# git checkout
|
||||
import os
|
||||
dnf_toplevel = os.path.dirname(here)
|
||||
--
|
||||
libgit2 1.6.4
|
||||
|
@ -1,25 +0,0 @@
|
||||
From 75c59dcb38d5672ffcfea9bb4cc999ab30294fe9 Mon Sep 17 00:00:00 2001
|
||||
From: Marek Blaha <mblaha@redhat.com>
|
||||
Date: Wed, 29 Jan 2025 13:29:34 +0100
|
||||
Subject: [PATCH] Fix missing import in automatic
|
||||
|
||||
Fixes omitted `import os` in previous commit.
|
||||
---
|
||||
dnf/automatic/main.py | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/dnf/automatic/main.py b/dnf/automatic/main.py
|
||||
index 3d73ffce..9d680e9e 100644
|
||||
--- a/dnf/automatic/main.py
|
||||
+++ b/dnf/automatic/main.py
|
||||
@@ -24,6 +24,7 @@ from __future__ import unicode_literals
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
+import os
|
||||
import random
|
||||
import socket
|
||||
import time
|
||||
--
|
||||
2.48.1
|
||||
|
910
SPECS/dnf.spec
910
SPECS/dnf.spec
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user