Added patch for almalinux bugtracker
This commit is contained in:
commit
59a4e04ff0
@ -0,0 +1,35 @@
|
||||
From 5d410dee9815d3ab23e64a48871c8b9aac717127 Mon Sep 17 00:00:00 2001
|
||||
From: Marek Blaha <mblaha@redhat.com>
|
||||
Date: Wed, 18 Sep 2024 09:46:20 +0200
|
||||
Subject: [PATCH] package: remote_location() takes basedir into account
|
||||
|
||||
If the package location in the repodata contains basedir, it needs to be
|
||||
taken into account when calculating the package's remote_location.
|
||||
|
||||
Resolves: https://github.com/rpm-software-management/dnf/issues/2130
|
||||
Resolves: RHEL-71125
|
||||
|
||||
= changelog =
|
||||
msg: Fix package location if baseurl is present in the metadata
|
||||
type: bugfix
|
||||
resolves: https://github.com/rpm-software-management/dnf/issues/2130
|
||||
---
|
||||
dnf/package.py | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/dnf/package.py b/dnf/package.py
|
||||
index fc89cf98..5912f79c 100644
|
||||
--- a/dnf/package.py
|
||||
+++ b/dnf/package.py
|
||||
@@ -300,6 +300,8 @@ class Package(hawkey.Package):
|
||||
"""
|
||||
if self._from_system or self._from_cmdline:
|
||||
return None
|
||||
+ if self.baseurl:
|
||||
+ return os.path.join(self.baseurl, self.location.lstrip("/"))
|
||||
return self.repo.remote_location(self.location, schemes)
|
||||
|
||||
def _is_local_pkg(self):
|
||||
--
|
||||
2.48.1
|
||||
|
||||
@ -0,0 +1,129 @@
|
||||
From f777d26ba70778ff015a3f3af21f76e5a1e8473b Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
|
||||
Date: Tue, 11 Feb 2025 14:33:08 +0100
|
||||
Subject: [PATCH] Usage help: don't mark mandatory option parameters as
|
||||
optional
|
||||
|
||||
For: https://issues.redhat.com/browse/RHEL-63958
|
||||
---
|
||||
dnf/cli/commands/repoquery.py | 2 +-
|
||||
dnf/cli/option_parser.py | 26 +++++++++++++-------------
|
||||
2 files changed, 14 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/dnf/cli/commands/repoquery.py b/dnf/cli/commands/repoquery.py
|
||||
index 41dd688e..a5e55122 100644
|
||||
--- a/dnf/cli/commands/repoquery.py
|
||||
+++ b/dnf/cli/commands/repoquery.py
|
||||
@@ -126,7 +126,7 @@ class RepoQueryCommand(commands.Command):
|
||||
parser.add_argument('--show-duplicates', action='store_true',
|
||||
help=_("Query all versions of packages (default)"))
|
||||
parser.add_argument('--arch', '--archlist', dest='arches', default=[],
|
||||
- action=_CommaSplitCallback, metavar='[arch]',
|
||||
+ action=_CommaSplitCallback, metavar='ARCH',
|
||||
help=_('show only results from this ARCH'))
|
||||
parser.add_argument('-f', '--file', metavar='FILE', nargs='+',
|
||||
help=_('show only results that owns FILE'))
|
||||
diff --git a/dnf/cli/option_parser.py b/dnf/cli/option_parser.py
|
||||
index fba37614..c95d3d99 100644
|
||||
--- a/dnf/cli/option_parser.py
|
||||
+++ b/dnf/cli/option_parser.py
|
||||
@@ -171,7 +171,7 @@ class OptionParser(argparse.ArgumentParser):
|
||||
general_grp = self.add_argument_group(_('General {prog} options'.format(
|
||||
prog=dnf.util.MAIN_PROG_UPPER)))
|
||||
general_grp.add_argument("-c", "--config", dest="config_file_path",
|
||||
- default=None, metavar='[config file]',
|
||||
+ default=None, metavar='CONFIG_FILE',
|
||||
help=_("config file location"))
|
||||
general_grp.add_argument("-q", "--quiet", dest="quiet",
|
||||
action="store_true", default=None,
|
||||
@@ -182,7 +182,7 @@ class OptionParser(argparse.ArgumentParser):
|
||||
help=_("show {prog} version and exit").format(
|
||||
prog=dnf.util.MAIN_PROG_UPPER))
|
||||
general_grp.add_argument("--installroot", help=_("set install root"),
|
||||
- metavar='[path]')
|
||||
+ metavar='PATH]')
|
||||
general_grp.add_argument("--nodocs", action="store_const", const=['nodocs'], dest='tsflags',
|
||||
help=_("do not install documentations"))
|
||||
general_grp.add_argument("--noplugins", action="store_false",
|
||||
@@ -191,11 +191,11 @@ class OptionParser(argparse.ArgumentParser):
|
||||
general_grp.add_argument("--enableplugin", dest="enableplugin",
|
||||
default=[], action=self._SplitCallback,
|
||||
help=_("enable plugins by name"),
|
||||
- metavar='[plugin]')
|
||||
+ metavar='PLUGIN]')
|
||||
general_grp.add_argument("--disableplugin", dest="disableplugin",
|
||||
default=[], action=self._SplitCallback,
|
||||
help=_("disable plugins by name"),
|
||||
- metavar='[plugin]')
|
||||
+ metavar='PLUGIN]')
|
||||
general_grp.add_argument("--releasever", default=None,
|
||||
help=_("override the value of $releasever"
|
||||
" in config and repo files"))
|
||||
@@ -229,10 +229,10 @@ class OptionParser(argparse.ArgumentParser):
|
||||
help=_("run entirely from system cache, "
|
||||
"don't update cache"))
|
||||
general_grp.add_argument("-R", "--randomwait", dest="sleeptime", type=int,
|
||||
- default=None, metavar='[minutes]',
|
||||
+ default=None, metavar='MINUTES',
|
||||
help=_("maximum command wait time"))
|
||||
general_grp.add_argument("-d", "--debuglevel", dest="debuglevel",
|
||||
- metavar='[debug level]', default=None,
|
||||
+ metavar='DEBUG_LEVEL', default=None,
|
||||
help=_("debugging output level"), type=int)
|
||||
general_grp.add_argument("--debugsolver",
|
||||
action="store_true", default=None,
|
||||
@@ -252,7 +252,7 @@ class OptionParser(argparse.ArgumentParser):
|
||||
"repoquery").format(prog=dnf.util.MAIN_PROG))
|
||||
general_grp.add_argument("--rpmverbosity", default=None,
|
||||
help=_("debugging output level for rpm"),
|
||||
- metavar='[debug level name]')
|
||||
+ metavar='DEBUG_LEVEL_NAME')
|
||||
general_grp.add_argument("-y", "--assumeyes", action="store_true",
|
||||
default=None, help=_("automatically answer yes"
|
||||
" for all questions"))
|
||||
@@ -260,20 +260,20 @@ class OptionParser(argparse.ArgumentParser):
|
||||
default=None, help=_("automatically answer no"
|
||||
" for all questions"))
|
||||
general_grp.add_argument("--enablerepo", action=self._RepoCallback,
|
||||
- dest='repos_ed', default=[], metavar='[repo]',
|
||||
+ dest='repos_ed', default=[], metavar='REPO',
|
||||
help=_("Temporarily enable repositories for the purpose "
|
||||
"of the current dnf command. Accepts an id, a "
|
||||
"comma-separated list of ids, or a glob of ids. "
|
||||
"This option can be specified multiple times."))
|
||||
repo_group = general_grp.add_mutually_exclusive_group()
|
||||
repo_group.add_argument("--disablerepo", action=self._RepoCallback,
|
||||
- dest='repos_ed', default=[], metavar='[repo]',
|
||||
+ dest='repos_ed', default=[], metavar='REPO',
|
||||
help=_("Temporarily disable active repositories for the "
|
||||
"purpose of the current dnf command. Accepts an id, "
|
||||
"a comma-separated list of ids, or a glob of ids. "
|
||||
"This option can be specified multiple times, but "
|
||||
"is mutually exclusive with `--repo`."))
|
||||
- repo_group.add_argument('--repo', '--repoid', metavar='[repo]', dest='repo',
|
||||
+ repo_group.add_argument('--repo', '--repoid', metavar='REPO', dest='repo',
|
||||
action=self._SplitCallback, default=[],
|
||||
help=_('enable just specific repositories by an id or a glob, '
|
||||
'can be specified multiple times'))
|
||||
@@ -289,15 +289,15 @@ class OptionParser(argparse.ArgumentParser):
|
||||
general_grp.add_argument("-x", "--exclude", "--excludepkgs", default=[],
|
||||
dest='excludepkgs', action=self._SplitCallback,
|
||||
help=_("exclude packages by name or glob"),
|
||||
- metavar='[package]')
|
||||
+ metavar='PACKAGE')
|
||||
general_grp.add_argument("--disableexcludes", "--disableexcludepkgs",
|
||||
default=[], dest="disable_excludes",
|
||||
action=self._SplitCallback,
|
||||
help=_("disable excludepkgs"),
|
||||
- metavar='[repo]')
|
||||
+ metavar='{all, main, REPOID}')
|
||||
general_grp.add_argument("--repofrompath", default={},
|
||||
action=self._SplitExtendDictCallback,
|
||||
- metavar='[repo,path]',
|
||||
+ metavar='REPO,PATH',
|
||||
help=_("label and path to an additional repository to use (same "
|
||||
"path as in a baseurl), can be specified multiple times."))
|
||||
general_grp.add_argument("--noautoremove", action="store_false",
|
||||
--
|
||||
2.48.1
|
||||
|
||||
39
SOURCES/0047-Fix-typo-from-previous-commit-left-over.patch
Normal file
39
SOURCES/0047-Fix-typo-from-previous-commit-left-over.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From d2d3770168e744eeace6c36b38f4ba0709c7b9c0 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
|
||||
Date: Mon, 28 Apr 2025 12:23:27 +0200
|
||||
Subject: [PATCH 1/2] Fix typo from previous commit (left over `]`)
|
||||
|
||||
---
|
||||
dnf/cli/option_parser.py | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/dnf/cli/option_parser.py b/dnf/cli/option_parser.py
|
||||
index a23c8553..6bb32c51 100644
|
||||
--- a/dnf/cli/option_parser.py
|
||||
+++ b/dnf/cli/option_parser.py
|
||||
@@ -185,7 +185,7 @@ class OptionParser(argparse.ArgumentParser):
|
||||
help=_("show {prog} version and exit").format(
|
||||
prog=dnf.util.MAIN_PROG_UPPER))
|
||||
general_grp.add_argument("--installroot", help=_("set install root"),
|
||||
- metavar='PATH]')
|
||||
+ metavar='PATH')
|
||||
general_grp.add_argument("--nodocs", action="store_const", const=['nodocs'], dest='tsflags',
|
||||
help=_("do not install documentations"))
|
||||
general_grp.add_argument("--noplugins", action="store_false",
|
||||
@@ -194,11 +194,11 @@ class OptionParser(argparse.ArgumentParser):
|
||||
general_grp.add_argument("--enableplugin", dest="enableplugin",
|
||||
default=[], action=self._SplitCallback,
|
||||
help=_("enable plugins by name"),
|
||||
- metavar='PLUGIN]')
|
||||
+ metavar='PLUGIN')
|
||||
general_grp.add_argument("--disableplugin", dest="disableplugin",
|
||||
default=[], action=self._SplitCallback,
|
||||
help=_("disable plugins by name"),
|
||||
- metavar='PLUGIN]')
|
||||
+ metavar='PLUGIN')
|
||||
general_grp.add_argument("--releasever", default=None,
|
||||
help=_("override the value of $releasever"
|
||||
" in config and repo files"))
|
||||
--
|
||||
2.48.1
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
From 0f37439d04cfa6f2b39d3602b1b40570d37af80f Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
|
||||
Date: Mon, 28 Apr 2025 12:41:13 +0200
|
||||
Subject: [PATCH 2/2] `--disableexcludes` and `--disableexcludepkgs` values are
|
||||
not optional
|
||||
|
||||
---
|
||||
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 8b55d5a7..30627bd4 100644
|
||||
--- a/doc/command_ref.rst
|
||||
+++ b/doc/command_ref.rst
|
||||
@@ -164,7 +164,7 @@ Options
|
||||
|
||||
.. _disableexcludes-label:
|
||||
|
||||
-``--disableexcludes=[all|main|<repoid>], --disableexcludepkgs=[all|main|<repoid>]``
|
||||
+``--disableexcludes={all|main|<repoid>}, --disableexcludepkgs={all|main|<repoid>}``
|
||||
Disable ``excludepkgs`` and ``includepkgs`` configuration options. Takes one of the following three options:
|
||||
|
||||
* ``all``, disables all ``excludepkgs`` and ``includepkgs`` configurations
|
||||
--
|
||||
2.48.1
|
||||
|
||||
37
SOURCES/0049-bootc-tmt-testing.patch
Normal file
37
SOURCES/0049-bootc-tmt-testing.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From 72264e6ad00f90e7e261657f79dee7bae3ceb7e0 Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Thu, 10 Apr 2025 20:18:44 +0000
|
||||
Subject: [PATCH 1/8] bootc tmt testing
|
||||
|
||||
---
|
||||
.packit.yaml | 18 ++++++++++++++++++
|
||||
1 file changed, 18 insertions(+)
|
||||
create mode 100644 .packit.yaml
|
||||
|
||||
diff --git a/.packit.yaml b/.packit.yaml
|
||||
new file mode 100644
|
||||
index 000000000..0738de205
|
||||
--- /dev/null
|
||||
+++ b/.packit.yaml
|
||||
@@ -0,0 +1,18 @@
|
||||
+# See the documentation for more information:
|
||||
+# https://packit.dev/docs/configuration/
|
||||
+
|
||||
+specfile_path: dnf.spec
|
||||
+
|
||||
+jobs:
|
||||
+ - job: copr_build
|
||||
+ trigger: pull_request
|
||||
+ targets:
|
||||
+ - centos-stream-9-x86_64
|
||||
+ - job: tests
|
||||
+ trigger: pull_request
|
||||
+ identifier: "dnf-tests"
|
||||
+ targets:
|
||||
+ - centos-stream-9-x86_64
|
||||
+ fmf_url: https://github.com/evan-goode/ci-dnf-stack.git
|
||||
+ fmf_ref: evan-goode/bootc
|
||||
+ tmt_plan: "^/plans/integration/bootc-behave-dnf$"
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@ -0,0 +1,117 @@
|
||||
From 5f91b890799559d0a8fa5861ff8f5e2a16db1dbf Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Thu, 15 May 2025 20:48:58 +0000
|
||||
Subject: [PATCH 2/8] persistence: store persist/transient in history DB
|
||||
|
||||
For all transactions, store whether the transaction was persistent or
|
||||
transient in the history DB. Requires libdnf 0.75.0.
|
||||
|
||||
Moves some of the bootc logic to the `configure` phase.
|
||||
|
||||
For https://github.com/rpm-software-management/dnf/issues/2196.
|
||||
---
|
||||
dnf.spec | 2 +-
|
||||
dnf/base.py | 6 ++++--
|
||||
dnf/cli/cli.py | 3 +++
|
||||
dnf/db/history.py | 8 +++++++-
|
||||
4 files changed, 15 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/dnf.spec b/dnf.spec
|
||||
index 28fac9a09..4abc0084b 100644
|
||||
--- a/dnf.spec
|
||||
+++ b/dnf.spec
|
||||
@@ -2,7 +2,7 @@
|
||||
%define __cmake_in_source_build 1
|
||||
|
||||
# default dependencies
|
||||
-%global hawkey_version 0.74.0
|
||||
+%global hawkey_version 0.75.0
|
||||
%global libcomps_version 0.1.8
|
||||
%global libmodulemd_version 2.9.3
|
||||
%global rpm_version 4.14.0
|
||||
diff --git a/dnf/base.py b/dnf/base.py
|
||||
index 168207b5f..d0ce6364c 100644
|
||||
--- a/dnf/base.py
|
||||
+++ b/dnf/base.py
|
||||
@@ -118,6 +118,7 @@ class Base(object):
|
||||
self._update_security_options = {}
|
||||
self._allow_erasing = False
|
||||
self._repo_set_imported_gpg_keys = set()
|
||||
+ self._persistence = libdnf.transaction.TransactionPersistence_UNKNOWN
|
||||
self.output = None
|
||||
|
||||
def __enter__(self):
|
||||
@@ -964,7 +965,7 @@ class Base(object):
|
||||
else:
|
||||
rpmdb_version = old.end_rpmdb_version
|
||||
|
||||
- self.history.beg(rpmdb_version, [], [], cmdline)
|
||||
+ self.history.beg(rpmdb_version, [], [], cmdline=cmdline, persistence=self._persistence)
|
||||
self.history.end(rpmdb_version)
|
||||
self._plugins.run_pre_transaction()
|
||||
self._plugins.run_transaction()
|
||||
@@ -1115,7 +1116,8 @@ class Base(object):
|
||||
cmdline = ' '.join(self.cmds)
|
||||
|
||||
comment = self.conf.comment if self.conf.comment else ""
|
||||
- tid = self.history.beg(rpmdbv, using_pkgs, [], cmdline, comment)
|
||||
+ tid = self.history.beg(rpmdbv, using_pkgs, [], cmdline=cmdline,
|
||||
+ comment=comment, persistence=self._persistence)
|
||||
|
||||
if self.conf.reset_nice:
|
||||
onice = os.nice(0)
|
||||
diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py
|
||||
index 23170a82b..99ed1f282 100644
|
||||
--- a/dnf/cli/cli.py
|
||||
+++ b/dnf/cli/cli.py
|
||||
@@ -244,11 +244,14 @@ 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."))
|
||||
+ self._persistence = libdnf.transaction.TransactionPersistence_TRANSIENT
|
||||
else:
|
||||
# Not a bootc transaction.
|
||||
if self.conf.persistence == "transient":
|
||||
raise CliError(_("Transient transactions are only supported on bootc systems."))
|
||||
|
||||
+ self._persistence = libdnf.transaction.TransactionPersistence_PERSIST
|
||||
+
|
||||
if self._promptWanted():
|
||||
if self.conf.assumeno or not self.output.userconfirm():
|
||||
raise CliError(_("Operation aborted."))
|
||||
diff --git a/dnf/db/history.py b/dnf/db/history.py
|
||||
index bf9020ad0..2cde9cbc8 100644
|
||||
--- a/dnf/db/history.py
|
||||
+++ b/dnf/db/history.py
|
||||
@@ -222,6 +222,10 @@ class TransactionWrapper(object):
|
||||
def comment(self):
|
||||
return self._trans.getComment()
|
||||
|
||||
+ @property
|
||||
+ def persistence(self):
|
||||
+ return self._trans.getPersistence()
|
||||
+
|
||||
def tids(self):
|
||||
return [self._trans.getId()]
|
||||
|
||||
@@ -418,7 +422,8 @@ class SwdbInterface(object):
|
||||
# return result
|
||||
|
||||
# TODO: rename to begin_transaction?
|
||||
- def beg(self, rpmdb_version, using_pkgs, tsis, cmdline=None, comment=""):
|
||||
+ def beg(self, rpmdb_version, using_pkgs, tsis, cmdline=None, comment="",
|
||||
+ persistence=libdnf.transaction.TransactionPersistence_UNKNOWN):
|
||||
try:
|
||||
self.swdb.initTransaction()
|
||||
except:
|
||||
@@ -431,6 +436,7 @@ class SwdbInterface(object):
|
||||
int(misc.getloginuid()),
|
||||
comment)
|
||||
self.swdb.setReleasever(self.releasever)
|
||||
+ self.swdb.setPersistence(persistence)
|
||||
self._tid = tid
|
||||
|
||||
return tid
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
From 5f7fcae28541368d80fab9c9224c7974726a6b10 Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Fri, 16 May 2025 20:38:56 +0000
|
||||
Subject: [PATCH 3/8] Print "persist" or "transient" in history info
|
||||
|
||||
---
|
||||
dnf/cli/output.py | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/dnf/cli/output.py b/dnf/cli/output.py
|
||||
index 7f1d62c5a..6c97c7dc9 100644
|
||||
--- a/dnf/cli/output.py
|
||||
+++ b/dnf/cli/output.py
|
||||
@@ -1772,6 +1772,14 @@ Transaction Summary
|
||||
else:
|
||||
print(_("Command Line :"), old.cmdline)
|
||||
|
||||
+ if old.persistence == libdnf.transaction.TransactionPersistence_PERSIST:
|
||||
+ persistence_str = "Persist"
|
||||
+ elif old.persistence == libdnf.transaction.TransactionPersistence_TRANSIENT:
|
||||
+ persistence_str = "Transient"
|
||||
+ else:
|
||||
+ persistence_str = "Unknown"
|
||||
+ print(_("Persistence :"), persistence_str)
|
||||
+
|
||||
if old.comment is not None:
|
||||
if isinstance(old.comment, (list, tuple)):
|
||||
for comment in old.comment:
|
||||
--
|
||||
2.49.0
|
||||
|
||||
58
SOURCES/0052-history-persistence-for-MergedTransaction.patch
Normal file
58
SOURCES/0052-history-persistence-for-MergedTransaction.patch
Normal file
@ -0,0 +1,58 @@
|
||||
From ceaf4718a6c7435050f5bfb451077683baf01600 Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Mon, 19 May 2025 22:36:50 +0000
|
||||
Subject: [PATCH 4/8] history: persistence for MergedTransaction
|
||||
|
||||
---
|
||||
dnf/cli/output.py | 18 ++++++++++++------
|
||||
dnf/db/history.py | 4 ++++
|
||||
2 files changed, 16 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/dnf/cli/output.py b/dnf/cli/output.py
|
||||
index 6c97c7dc9..820ab88fa 100644
|
||||
--- a/dnf/cli/output.py
|
||||
+++ b/dnf/cli/output.py
|
||||
@@ -1772,13 +1772,19 @@ Transaction Summary
|
||||
else:
|
||||
print(_("Command Line :"), old.cmdline)
|
||||
|
||||
- if old.persistence == libdnf.transaction.TransactionPersistence_PERSIST:
|
||||
- persistence_str = "Persist"
|
||||
- elif old.persistence == libdnf.transaction.TransactionPersistence_TRANSIENT:
|
||||
- persistence_str = "Transient"
|
||||
+ def print_persistence(persistence):
|
||||
+ if old.persistence == libdnf.transaction.TransactionPersistence_PERSIST:
|
||||
+ persistence_str = "Persist"
|
||||
+ elif old.persistence == libdnf.transaction.TransactionPersistence_TRANSIENT:
|
||||
+ persistence_str = "Transient"
|
||||
+ else:
|
||||
+ persistence_str = "Unknown"
|
||||
+ print(_("Persistence :"), persistence_str)
|
||||
+ if isinstance(old.persistence, (list, tuple)):
|
||||
+ for persistence in old.persistence:
|
||||
+ print_persistence(persistence)
|
||||
else:
|
||||
- persistence_str = "Unknown"
|
||||
- print(_("Persistence :"), persistence_str)
|
||||
+ print_persistence(old.persistence)
|
||||
|
||||
if old.comment is not None:
|
||||
if isinstance(old.comment, (list, tuple)):
|
||||
diff --git a/dnf/db/history.py b/dnf/db/history.py
|
||||
index 2cde9cbc8..a2c1a8882 100644
|
||||
--- a/dnf/db/history.py
|
||||
+++ b/dnf/db/history.py
|
||||
@@ -269,6 +269,10 @@ class MergedTransactionWrapper(TransactionWrapper):
|
||||
def cmdline(self):
|
||||
return self._trans.listCmdlines()
|
||||
|
||||
+ @property
|
||||
+ def persistence(self):
|
||||
+ return self._trans.listPersistences()
|
||||
+
|
||||
@property
|
||||
def releasever(self):
|
||||
return self._trans.listReleasevers()
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
From abce1aabea6a28ef1d49a6530c521f9a48eedebb Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Wed, 28 May 2025 20:46:56 +0000
|
||||
Subject: [PATCH 5/8] bootc: Check whether protected paths will be modified
|
||||
|
||||
For https://github.com/rpm-software-management/dnf/issues/2199.
|
||||
|
||||
Requires libdnf 0.75.0 with the new `usr_drift_protected_paths` option.
|
||||
---
|
||||
dnf/cli/cli.py | 19 +++++++++++++++++++
|
||||
1 file changed, 19 insertions(+)
|
||||
|
||||
diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py
|
||||
index 99ed1f282..74cf418c4 100644
|
||||
--- a/dnf/cli/cli.py
|
||||
+++ b/dnf/cli/cli.py
|
||||
@@ -29,6 +29,7 @@ try:
|
||||
from collections.abc import Sequence
|
||||
except ImportError:
|
||||
from collections import Sequence
|
||||
+from collections import defaultdict
|
||||
import datetime
|
||||
import logging
|
||||
import operator
|
||||
@@ -245,6 +246,24 @@ class BaseCli(dnf.Base):
|
||||
"Keep in mind that changes to /etc and /var will still persist, and packages "
|
||||
"commonly modify these directories."))
|
||||
self._persistence = libdnf.transaction.TransactionPersistence_TRANSIENT
|
||||
+
|
||||
+ # Check whether the transaction modifies usr_drift_protected_paths
|
||||
+ transaction_protected_paths = defaultdict(list)
|
||||
+ for pkg in trans:
|
||||
+ for pkg_file_path in sorted(pkg.files):
|
||||
+ for protected_path in self.conf.usr_drift_protected_paths:
|
||||
+ if pkg_file_path.startswith("%s/" % protected_path) or pkg_file_path == protected_path:
|
||||
+ transaction_protected_paths[pkg.nevra].append(pkg_file_path)
|
||||
+ if transaction_protected_paths:
|
||||
+ logger.info(_('This operation would modify the following paths, possibly introducing '
|
||||
+ 'inconsistencies when the transient overlay on /usr is discarded. See the '
|
||||
+ 'usr_drift_protected_paths configuration option for more information.'))
|
||||
+ for nevra, protected_paths in transaction_protected_paths.items():
|
||||
+ logger.info(nevra)
|
||||
+ for protected_path in protected_paths:
|
||||
+ logger.info(" %s" % protected_path)
|
||||
+ raise CliError(_("Operation aborted."))
|
||||
+
|
||||
else:
|
||||
# Not a bootc transaction.
|
||||
if self.conf.persistence == "transient":
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
From 1a47a316ef937f5f04e5f82e64c5aef1db45c717 Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Tue, 3 Jun 2025 22:43:46 +0000
|
||||
Subject: [PATCH 6/8] spec: package /etc/dnf/usr_drift_protected_paths.d
|
||||
|
||||
---
|
||||
dnf.spec | 1 +
|
||||
dnf/cli/cli.py | 2 +-
|
||||
etc/dnf/CMakeLists.txt | 1 +
|
||||
etc/dnf/usr-drift-protected-paths.d/CMakeLists.txt | 1 +
|
||||
4 files changed, 4 insertions(+), 1 deletion(-)
|
||||
create mode 100644 etc/dnf/usr-drift-protected-paths.d/CMakeLists.txt
|
||||
|
||||
diff --git a/dnf.spec b/dnf.spec
|
||||
index 4abc0084b..da5d5fd28 100644
|
||||
--- a/dnf.spec
|
||||
+++ b/dnf.spec
|
||||
@@ -301,6 +301,7 @@ popd
|
||||
%dir %{confdir}/modules.defaults.d
|
||||
%dir %{pluginconfpath}
|
||||
%dir %{confdir}/protected.d
|
||||
+%dir %{confdir}/usr-drift-protected-paths.d
|
||||
%dir %{confdir}/vars
|
||||
%dir %{confdir}/aliases.d
|
||||
%exclude %{confdir}/aliases.d/zypper.conf
|
||||
diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py
|
||||
index 74cf418c4..5602a07b1 100644
|
||||
--- a/dnf/cli/cli.py
|
||||
+++ b/dnf/cli/cli.py
|
||||
@@ -262,7 +262,7 @@ class BaseCli(dnf.Base):
|
||||
logger.info(nevra)
|
||||
for protected_path in protected_paths:
|
||||
logger.info(" %s" % protected_path)
|
||||
- raise CliError(_("Operation aborted."))
|
||||
+ raise CliError(_("Operation aborted. Pass --setopt=usr_drift_protected_paths= to disable this check and proceed anyway."))
|
||||
|
||||
else:
|
||||
# Not a bootc transaction.
|
||||
diff --git a/etc/dnf/CMakeLists.txt b/etc/dnf/CMakeLists.txt
|
||||
index 6f0eec94e..7a60186d7 100644
|
||||
--- a/etc/dnf/CMakeLists.txt
|
||||
+++ b/etc/dnf/CMakeLists.txt
|
||||
@@ -1,3 +1,4 @@
|
||||
INSTALL (FILES "dnf-strict.conf" "dnf.conf" "automatic.conf" DESTINATION ${SYSCONFDIR}/dnf)
|
||||
ADD_SUBDIRECTORY (aliases.d)
|
||||
ADD_SUBDIRECTORY (protected.d)
|
||||
+ADD_SUBDIRECTORY (usr-drift-protected-paths.d)
|
||||
diff --git a/etc/dnf/usr-drift-protected-paths.d/CMakeLists.txt b/etc/dnf/usr-drift-protected-paths.d/CMakeLists.txt
|
||||
new file mode 100644
|
||||
index 000000000..206b1b281
|
||||
--- /dev/null
|
||||
+++ b/etc/dnf/usr-drift-protected-paths.d/CMakeLists.txt
|
||||
@@ -0,0 +1 @@
|
||||
+INSTALL(DIRECTORY DESTINATION ${SYSCONFDIR}/dnf/usr-drift-protected-paths.d)
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
From 26a9f2163c0d3828f474537687ead4e100f5911a Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Fri, 6 Jun 2025 21:24:20 +0000
|
||||
Subject: [PATCH 7/8] Support globs in usr_drift_protected_paths
|
||||
|
||||
---
|
||||
dnf/cli/cli.py | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py
|
||||
index 5602a07b1..c41f31ed6 100644
|
||||
--- a/dnf/cli/cli.py
|
||||
+++ b/dnf/cli/cli.py
|
||||
@@ -31,6 +31,7 @@ except ImportError:
|
||||
from collections import Sequence
|
||||
from collections import defaultdict
|
||||
import datetime
|
||||
+from fnmatch import fnmatch
|
||||
import logging
|
||||
import operator
|
||||
import os
|
||||
@@ -251,8 +252,8 @@ class BaseCli(dnf.Base):
|
||||
transaction_protected_paths = defaultdict(list)
|
||||
for pkg in trans:
|
||||
for pkg_file_path in sorted(pkg.files):
|
||||
- for protected_path in self.conf.usr_drift_protected_paths:
|
||||
- if pkg_file_path.startswith("%s/" % protected_path) or pkg_file_path == protected_path:
|
||||
+ for protected_pattern in self.conf.usr_drift_protected_paths:
|
||||
+ if fnmatch(pkg_file_path, protected_pattern):
|
||||
transaction_protected_paths[pkg.nevra].append(pkg_file_path)
|
||||
if transaction_protected_paths:
|
||||
logger.info(_('This operation would modify the following paths, possibly introducing '
|
||||
--
|
||||
2.49.0
|
||||
|
||||
32
SOURCES/0056-doc-Document-usr_drift_protected_paths.patch
Normal file
32
SOURCES/0056-doc-Document-usr_drift_protected_paths.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From cb765957d546f7d28aef270885418afea4906b89 Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Fri, 6 Jun 2025 22:31:27 +0000
|
||||
Subject: [PATCH 8/8] doc: Document `usr_drift_protected_paths`
|
||||
|
||||
---
|
||||
doc/conf_ref.rst | 9 +++++++++
|
||||
1 file changed, 9 insertions(+)
|
||||
|
||||
diff --git a/doc/conf_ref.rst b/doc/conf_ref.rst
|
||||
index a34e355b6..7ff286fee 100644
|
||||
--- a/doc/conf_ref.rst
|
||||
+++ b/doc/conf_ref.rst
|
||||
@@ -549,6 +549,15 @@ configuration file by your distribution to override the DNF defaults.
|
||||
|
||||
Set this to False to disable the automatic running of ``group upgrade`` when running the ``upgrade`` command. Default is ``True`` (perform the operation).
|
||||
|
||||
+.. _usr_drift_protected_paths-label:
|
||||
+
|
||||
+``usr_drift_protected_paths``
|
||||
+ :ref:`list <list-label>`
|
||||
+
|
||||
+ List of paths that are likely to cause problems when their contents drift with respect to ``/usr``, e.g. ``/etc/pam.d/*``. If a transient transaction would modify these paths, DNF aborts the operation and prints an error. Supports globs. Defaults to ``glob:/etc/dnf/usr-drift-protected-paths.d/*.conf``. So a list of paths can be protected by creating a ``.conf`` file in ``/etc/dnf/usr-drift-protected-paths.d/`` containing one path (or glob pattern) per line.
|
||||
+
|
||||
+ When using ``persistence=transient`` on bootc systems, a transient overlay is created on ``/usr``, and any changes DNF makes to ``/usr`` will be discarded on reboot. However, other paths such as ``/etc`` and ``/var`` are (often) not backed by a transient overlay, so changes to them will persist across reboots. Usually, this "filesystem drift" is fine, but it can cause problems in certain situations. For example, a configuration file in ``/etc`` that's shared by multiple packages might reference a ``.so`` file under ``/usr/lib64`` that no longer exists.
|
||||
+
|
||||
.. _varsdir_options-label:
|
||||
|
||||
``varsdir``
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@ -0,0 +1,31 @@
|
||||
From 2478a55ac8af31f426f2d6bb5adf8fd2b3ac5eff Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Wed, 20 Sep 2023 20:36:49 +0000
|
||||
Subject: [PATCH 01/11] [conf] Add test for shell-like variable expansion
|
||||
|
||||
Requires https://github.com/rpm-software-management/libdnf/pull/1622
|
||||
|
||||
This is the same test case used by the DNF 5 implementation: https://github.com/rpm-software-management/dnf5/pull/800
|
||||
---
|
||||
tests/conf/test_parser.py | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/tests/conf/test_parser.py b/tests/conf/test_parser.py
|
||||
index a9e50460f..ad0d61e31 100644
|
||||
--- a/tests/conf/test_parser.py
|
||||
+++ b/tests/conf/test_parser.py
|
||||
@@ -54,6 +54,11 @@ class ParserTest(tests.support.TestCase):
|
||||
result = '$Substitute some fact}withoutspace.'
|
||||
self.assertEqual(substitute(rawstr, substs), result)
|
||||
|
||||
+ # Test ${variable:-word} and ${variable:+word} shell-like expansion
|
||||
+ rawstr = '${lies:+alternate}-${unset:-default}-${nn:+n${nn:-${nnn:}'
|
||||
+ result = 'alternate-default-${nn:+n${nn:-${nnn:}'
|
||||
+ self.assertEqual(substitute(rawstr, substs), result)
|
||||
+
|
||||
def test_empty_option(self):
|
||||
# Parser is able to read config file with option without value
|
||||
FN = tests.support.resource_path('etc/empty_option.conf')
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@ -0,0 +1,139 @@
|
||||
From a614ec8eeb440f2fd4bfb196ddb1d24406d420a6 Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Mon, 18 Sep 2023 20:42:09 +0000
|
||||
Subject: [PATCH 02/11] Split $releasever to $releasever_major and
|
||||
$releasever_minor
|
||||
|
||||
Whenever the `releasever` substitution variable is set, automatically
|
||||
derive and set the `releasever_major` and `releasever_minor` vars by
|
||||
splitting `releasever` on the first ".".
|
||||
|
||||
Companion to the DNF 5 implementation here: https://github.com/rpm-software-management/dnf5/pull/800
|
||||
|
||||
DNF 5 issue: https://github.com/rpm-software-management/dnf5/issues/710
|
||||
|
||||
For https://bugzilla.redhat.com/show_bug.cgi?id=1789346
|
||||
---
|
||||
dnf/conf/substitutions.py | 31 +++++++++++++++++++++++++++++++
|
||||
dnf/exceptions.py | 6 ++++++
|
||||
tests/conf/test_substitutions.py | 32 ++++++++++++++++++++++++++++++++
|
||||
3 files changed, 69 insertions(+)
|
||||
|
||||
diff --git a/dnf/conf/substitutions.py b/dnf/conf/substitutions.py
|
||||
index 4d0f0d55e..5c736a8df 100644
|
||||
--- a/dnf/conf/substitutions.py
|
||||
+++ b/dnf/conf/substitutions.py
|
||||
@@ -23,8 +23,10 @@ import os
|
||||
import re
|
||||
|
||||
from dnf.i18n import _
|
||||
+from dnf.exceptions import ReadOnlyVariableError
|
||||
|
||||
ENVIRONMENT_VARS_RE = re.compile(r'^DNF_VAR_[A-Za-z0-9_]+$')
|
||||
+READ_ONLY_VARIABLES = frozenset(("releasever_major", "releasever_minor"))
|
||||
logger = logging.getLogger('dnf')
|
||||
|
||||
|
||||
@@ -43,6 +45,35 @@ class Substitutions(dict):
|
||||
elif key in numericvars:
|
||||
self[key] = val
|
||||
|
||||
+ @staticmethod
|
||||
+ def _split_releasever(releasever):
|
||||
+ # type: (str) -> tuple[str, str]
|
||||
+ pos = releasever.find(".")
|
||||
+ if pos == -1:
|
||||
+ releasever_major = releasever
|
||||
+ releasever_minor = ""
|
||||
+ else:
|
||||
+ releasever_major = releasever[:pos]
|
||||
+ releasever_minor = releasever[pos + 1:]
|
||||
+ return releasever_major, releasever_minor
|
||||
+
|
||||
+ def __setitem__(self, key, value):
|
||||
+ if Substitutions.is_read_only(key):
|
||||
+ raise ReadOnlyVariableError(f"Variable \"{key}\" is read-only", variable_name=key)
|
||||
+
|
||||
+ setitem = super(Substitutions, self).__setitem__
|
||||
+ setitem(key, value)
|
||||
+
|
||||
+ if key == "releasever" and value:
|
||||
+ releasever_major, releasever_minor = Substitutions._split_releasever(value)
|
||||
+ setitem("releasever_major", releasever_major)
|
||||
+ setitem("releasever_minor", releasever_minor)
|
||||
+
|
||||
+ @staticmethod
|
||||
+ def is_read_only(key):
|
||||
+ # type: (str) -> bool
|
||||
+ return key in READ_ONLY_VARIABLES
|
||||
+
|
||||
def update_from_etc(self, installroot, varsdir=("/etc/yum/vars/", "/etc/dnf/vars/")):
|
||||
# :api
|
||||
|
||||
diff --git a/dnf/exceptions.py b/dnf/exceptions.py
|
||||
index ef731781d..2d009b2ad 100644
|
||||
--- a/dnf/exceptions.py
|
||||
+++ b/dnf/exceptions.py
|
||||
@@ -180,6 +180,12 @@ class ProcessLockError(LockError):
|
||||
return (ProcessLockError, (self.value, self.pid))
|
||||
|
||||
|
||||
+class ReadOnlyVariableError(Error):
|
||||
+ def __init__(self, value, variable_name):
|
||||
+ super(ReadOnlyVariableError, self).__init__(value)
|
||||
+ self.variable_name = variable_name
|
||||
+
|
||||
+
|
||||
class RepoError(Error):
|
||||
# :api
|
||||
pass
|
||||
diff --git a/tests/conf/test_substitutions.py b/tests/conf/test_substitutions.py
|
||||
index b64533ff6..d8ac3c207 100644
|
||||
--- a/tests/conf/test_substitutions.py
|
||||
+++ b/tests/conf/test_substitutions.py
|
||||
@@ -23,6 +23,8 @@ from __future__ import unicode_literals
|
||||
import os
|
||||
|
||||
import dnf.conf
|
||||
+from dnf.conf.substitutions import Substitutions
|
||||
+from dnf.exceptions import ReadOnlyVariableError
|
||||
|
||||
import tests.support
|
||||
|
||||
@@ -52,3 +54,33 @@ class SubstitutionsFromEnvironmentTest(tests.support.TestCase):
|
||||
conf.substitutions.keys(),
|
||||
['basearch', 'arch', 'GENRE', 'EMPTY'])
|
||||
self.assertEqual('opera', conf.substitutions['GENRE'])
|
||||
+
|
||||
+
|
||||
+class SubstitutionsReadOnlyTest(tests.support.TestCase):
|
||||
+ def test_set_readonly(self):
|
||||
+ conf = dnf.conf.Conf()
|
||||
+ variable_name = "releasever_major"
|
||||
+ self.assertTrue(Substitutions.is_read_only(variable_name))
|
||||
+ with self.assertRaises(ReadOnlyVariableError) as cm:
|
||||
+ conf.substitutions["releasever_major"] = "1"
|
||||
+ self.assertEqual(cm.exception.variable_name, "releasever_major")
|
||||
+
|
||||
+
|
||||
+class SubstitutionsReleaseverTest(tests.support.TestCase):
|
||||
+ def test_releasever_simple(self):
|
||||
+ conf = dnf.conf.Conf()
|
||||
+ conf.substitutions["releasever"] = "1.23"
|
||||
+ self.assertEqual(conf.substitutions["releasever_major"], "1")
|
||||
+ self.assertEqual(conf.substitutions["releasever_minor"], "23")
|
||||
+
|
||||
+ def test_releasever_major_only(self):
|
||||
+ conf = dnf.conf.Conf()
|
||||
+ conf.substitutions["releasever"] = "123"
|
||||
+ self.assertEqual(conf.substitutions["releasever_major"], "123")
|
||||
+ self.assertEqual(conf.substitutions["releasever_minor"], "")
|
||||
+
|
||||
+ def test_releasever_multipart(self):
|
||||
+ conf = dnf.conf.Conf()
|
||||
+ conf.substitutions["releasever"] = "1.23.45"
|
||||
+ self.assertEqual(conf.substitutions["releasever_major"], "1")
|
||||
+ self.assertEqual(conf.substitutions["releasever_minor"], "23.45")
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@ -0,0 +1,49 @@
|
||||
From 8045771627933b20323457cf30108ea417834cdc Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Mon, 16 Oct 2023 18:27:02 +0000
|
||||
Subject: [PATCH 03/11] Document $releasever_major and $releasever_minor
|
||||
|
||||
=changelog=
|
||||
msg: Automatically derive $releasever_major and $releasever_minor from $releasever
|
||||
type: enhancement
|
||||
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1789346
|
||||
---
|
||||
doc/conf_ref.rst | 15 +++++++++++++++
|
||||
1 file changed, 15 insertions(+)
|
||||
|
||||
diff --git a/doc/conf_ref.rst b/doc/conf_ref.rst
|
||||
index 7ff286fee..9397f0008 100644
|
||||
--- a/doc/conf_ref.rst
|
||||
+++ b/doc/conf_ref.rst
|
||||
@@ -488,6 +488,9 @@ configuration file by your distribution to override the DNF defaults.
|
||||
:ref:`string <string-label>`
|
||||
|
||||
Used for substitution of ``$releasever`` in the repository configuration.
|
||||
+
|
||||
+ The ``$releasever_major`` and ``$releasever_minor`` variables will be automatically derived from ``$releasever`` by splitting it on the first ``.``. For example, if ``$releasever`` is set to ``1.23``, then ``$releasever_major`` will be ``1`` and ``$releasever_minor`` will be ``23``.
|
||||
+
|
||||
See also :ref:`repo variables <repo-variables-label>`.
|
||||
|
||||
.. _reposdir-label:
|
||||
@@ -794,6 +797,18 @@ Right side of every repo option can be enriched by the following variables:
|
||||
|
||||
Refers to the release version of operating system which DNF derives from information available in RPMDB.
|
||||
|
||||
+.. _variable-releasever_major-label:
|
||||
+
|
||||
+``$releasever_major``
|
||||
+
|
||||
+ Major version of ``$releasever``, i.e. the component of ``$releasever`` occurring before the first ``.``.
|
||||
+
|
||||
+.. _variable-releasever_minor-label:
|
||||
+
|
||||
+``$releasever_minor``
|
||||
+
|
||||
+ Minor version of ``$releasever``, i.e. the component of ``$releasever`` occurring after the first ``.``.
|
||||
+
|
||||
.. _variable-user-defined-label:
|
||||
|
||||
In addition to these hard coded variables, user-defined ones can also be used. They can be defined either via :ref:`variable files <varfiles-label>`, or by using special environmental variables. The names of these variables must be prefixed with DNF_VAR\_ and they can only consist of alphanumeric characters and underscores::
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
From 41843856d1f09c8fe718630a6fa4318441c7be38 Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Mon, 16 Oct 2023 18:44:53 +0000
|
||||
Subject: [PATCH 04/11] Document shell-like parameter expansion for variables
|
||||
|
||||
=changelog=
|
||||
msg: Support ${parameter:-word} and ${parameter:+word} parameter expansion in variables
|
||||
type: enhancement
|
||||
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1789346
|
||||
---
|
||||
doc/conf_ref.rst | 12 ++++++++++++
|
||||
1 file changed, 12 insertions(+)
|
||||
|
||||
diff --git a/doc/conf_ref.rst b/doc/conf_ref.rst
|
||||
index 9397f0008..fdb34323c 100644
|
||||
--- a/doc/conf_ref.rst
|
||||
+++ b/doc/conf_ref.rst
|
||||
@@ -829,6 +829,18 @@ Although users are encouraged to use named variables, the numbered environmental
|
||||
[myrepo]
|
||||
baseurl=https://example.site/pub/fedora/$DNF1/releases/$releasever
|
||||
|
||||
+A limited form of shell-like parameter expansion is supported for variables.
|
||||
+
|
||||
+``${my_variable:-word}`` If ``my_variable`` is unset or empty, then ``word`` will be substituted. Otherwise, the value of ``my_variable`` will be substituted.
|
||||
+
|
||||
+``${my_variable:+word}`` If ``my_variable`` is set and not empty, then ``word`` will be substituted. Otherwise, the empty string will be substituted.
|
||||
+
|
||||
+Parameter expansions can be nested up to a maximum depth of 32. For example::
|
||||
+
|
||||
+ ${my_defined_variable:+${my_undefined_variable:-foobar}}
|
||||
+
|
||||
+will evaluate to ``foobar``.
|
||||
+
|
||||
|
||||
.. _conf_main_and_repo_options-label:
|
||||
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@ -0,0 +1,161 @@
|
||||
From 9a0f2a9ad87551900e7590ccf023fb9b72b3fe0c Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Mon, 20 Jan 2025 21:36:18 +0000
|
||||
Subject: [PATCH 05/11] Derive releasever_{major,minor} in conf, not
|
||||
substitutions
|
||||
|
||||
This allows setting a releasever_major or releasever_minor
|
||||
independent of releasever, which is needed by EPEL.
|
||||
|
||||
Related: https://issues.redhat.com/browse/RHEL-68034
|
||||
---
|
||||
dnf/conf/config.py | 26 ++++++++++++++++++++++++++
|
||||
dnf/conf/substitutions.py | 17 +++--------------
|
||||
tests/conf/test_substitutions.py | 19 +++++++++----------
|
||||
tests/test_config.py | 16 ++++++++++++++++
|
||||
4 files changed, 54 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/dnf/conf/config.py b/dnf/conf/config.py
|
||||
index ed6daeb2d..49280e522 100644
|
||||
--- a/dnf/conf/config.py
|
||||
+++ b/dnf/conf/config.py
|
||||
@@ -429,6 +429,32 @@ class MainConf(BaseConfig):
|
||||
return
|
||||
self.substitutions['releasever'] = str(val)
|
||||
|
||||
+ @property
|
||||
+ def releasever_major(self):
|
||||
+ # :api
|
||||
+ return self.substitutions.get('releasever_major')
|
||||
+
|
||||
+ @releasever_major.setter
|
||||
+ def releasever_major(self, val):
|
||||
+ # :api
|
||||
+ if val is None:
|
||||
+ self.substitutions.pop('releasever_major', None)
|
||||
+ return
|
||||
+ self.substitutions['releasever_major'] = str(val)
|
||||
+
|
||||
+ @property
|
||||
+ def releasever_minor(self):
|
||||
+ # :api
|
||||
+ return self.substitutions.get('releasever_minor')
|
||||
+
|
||||
+ @releasever_minor.setter
|
||||
+ def releasever_minor(self, val):
|
||||
+ # :api
|
||||
+ if val is None:
|
||||
+ self.substitutions.pop('releasever_minor', None)
|
||||
+ return
|
||||
+ self.substitutions['releasever_minor'] = str(val)
|
||||
+
|
||||
@property
|
||||
def arch(self):
|
||||
# :api
|
||||
diff --git a/dnf/conf/substitutions.py b/dnf/conf/substitutions.py
|
||||
index 5c736a8df..8582d5d84 100644
|
||||
--- a/dnf/conf/substitutions.py
|
||||
+++ b/dnf/conf/substitutions.py
|
||||
@@ -22,11 +22,12 @@ import logging
|
||||
import os
|
||||
import re
|
||||
|
||||
+from libdnf.conf import ConfigParser
|
||||
from dnf.i18n import _
|
||||
from dnf.exceptions import ReadOnlyVariableError
|
||||
|
||||
ENVIRONMENT_VARS_RE = re.compile(r'^DNF_VAR_[A-Za-z0-9_]+$')
|
||||
-READ_ONLY_VARIABLES = frozenset(("releasever_major", "releasever_minor"))
|
||||
+READ_ONLY_VARIABLES = frozenset()
|
||||
logger = logging.getLogger('dnf')
|
||||
|
||||
|
||||
@@ -45,18 +46,6 @@ class Substitutions(dict):
|
||||
elif key in numericvars:
|
||||
self[key] = val
|
||||
|
||||
- @staticmethod
|
||||
- def _split_releasever(releasever):
|
||||
- # type: (str) -> tuple[str, str]
|
||||
- pos = releasever.find(".")
|
||||
- if pos == -1:
|
||||
- releasever_major = releasever
|
||||
- releasever_minor = ""
|
||||
- else:
|
||||
- releasever_major = releasever[:pos]
|
||||
- releasever_minor = releasever[pos + 1:]
|
||||
- return releasever_major, releasever_minor
|
||||
-
|
||||
def __setitem__(self, key, value):
|
||||
if Substitutions.is_read_only(key):
|
||||
raise ReadOnlyVariableError(f"Variable \"{key}\" is read-only", variable_name=key)
|
||||
@@ -65,7 +54,7 @@ class Substitutions(dict):
|
||||
setitem(key, value)
|
||||
|
||||
if key == "releasever" and value:
|
||||
- releasever_major, releasever_minor = Substitutions._split_releasever(value)
|
||||
+ releasever_major, releasever_minor = ConfigParser.splitReleasever(value)
|
||||
setitem("releasever_major", releasever_major)
|
||||
setitem("releasever_minor", releasever_minor)
|
||||
|
||||
diff --git a/tests/conf/test_substitutions.py b/tests/conf/test_substitutions.py
|
||||
index d8ac3c207..78d3e7274 100644
|
||||
--- a/tests/conf/test_substitutions.py
|
||||
+++ b/tests/conf/test_substitutions.py
|
||||
@@ -56,16 +56,6 @@ class SubstitutionsFromEnvironmentTest(tests.support.TestCase):
|
||||
self.assertEqual('opera', conf.substitutions['GENRE'])
|
||||
|
||||
|
||||
-class SubstitutionsReadOnlyTest(tests.support.TestCase):
|
||||
- def test_set_readonly(self):
|
||||
- conf = dnf.conf.Conf()
|
||||
- variable_name = "releasever_major"
|
||||
- self.assertTrue(Substitutions.is_read_only(variable_name))
|
||||
- with self.assertRaises(ReadOnlyVariableError) as cm:
|
||||
- conf.substitutions["releasever_major"] = "1"
|
||||
- self.assertEqual(cm.exception.variable_name, "releasever_major")
|
||||
-
|
||||
-
|
||||
class SubstitutionsReleaseverTest(tests.support.TestCase):
|
||||
def test_releasever_simple(self):
|
||||
conf = dnf.conf.Conf()
|
||||
@@ -84,3 +74,12 @@ class SubstitutionsReleaseverTest(tests.support.TestCase):
|
||||
conf.substitutions["releasever"] = "1.23.45"
|
||||
self.assertEqual(conf.substitutions["releasever_major"], "1")
|
||||
self.assertEqual(conf.substitutions["releasever_minor"], "23.45")
|
||||
+
|
||||
+ def test_releasever_major_minor_overrides(self):
|
||||
+ conf = dnf.conf.Conf()
|
||||
+ conf.substitutions["releasever"] = "1.23"
|
||||
+ conf.substitutions["releasever_major"] = "45"
|
||||
+ conf.substitutions["releasever_minor"] = "67"
|
||||
+ self.assertEqual(conf.substitutions["releasever"], "1.23")
|
||||
+ self.assertEqual(conf.substitutions["releasever_major"], "45")
|
||||
+ self.assertEqual(conf.substitutions["releasever_minor"], "67")
|
||||
diff --git a/tests/test_config.py b/tests/test_config.py
|
||||
index d85026705..16bdcccba 100644
|
||||
--- a/tests/test_config.py
|
||||
+++ b/tests/test_config.py
|
||||
@@ -145,3 +145,19 @@ class ConfTest(tests.support.TestCase):
|
||||
conf = Conf()
|
||||
with self.assertRaises(dnf.exceptions.ConfigError):
|
||||
conf.debuglevel = '11'
|
||||
+
|
||||
+ def test_releasever_major_minor(self):
|
||||
+ conf = Conf()
|
||||
+ conf.releasever = '1.2'
|
||||
+ self.assertEqual(conf.releasever_major, '1')
|
||||
+ self.assertEqual(conf.releasever_minor, '2')
|
||||
+
|
||||
+ # override releasever_major
|
||||
+ conf.releasever_major = '3'
|
||||
+ self.assertEqual(conf.releasever_major, '3')
|
||||
+ self.assertEqual(conf.releasever_minor, '2')
|
||||
+
|
||||
+ # override releasever_minor
|
||||
+ conf.releasever_minor = '4'
|
||||
+ self.assertEqual(conf.releasever_major, '3')
|
||||
+ self.assertEqual(conf.releasever_minor, '4')
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@ -0,0 +1,177 @@
|
||||
From 22d6966c80a83e932da8f7f47a907e4940ab1677 Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Tue, 21 Jan 2025 19:16:13 +0000
|
||||
Subject: [PATCH 06/11] Override releasever_{major,minor} with provides
|
||||
|
||||
The releasever_major and releasever_minor substitution variables are
|
||||
usually derived by splitting releasever on the first `.`. However, to
|
||||
support EPEL 10 [1], we would like a way for distributions to override these
|
||||
values. Specifically, we would like RHEL 10 to have a releasever of `10`
|
||||
with a releasever_major of `10` and a releasever_minor of `0` (later
|
||||
incrementing to `1`, `2`, to correspond with the RHEL minor version).
|
||||
|
||||
This commit adds a new API function, `detect_releasevers`, which derives
|
||||
releasever, releasever_major, and releasever_minor from virtual provides
|
||||
on the system-release package (any of `DISTROVERPKG`). The detection of
|
||||
releasever is unchanged. releasever_major and releasever_minor are
|
||||
specified by the versions of the `system-release-major` and
|
||||
`system-release-minor` provides, respectively.
|
||||
|
||||
If the user specifies a `--releasever=X.Y` on the command line, the
|
||||
distribution settings for releasever, releasever_major, and releasever_minor
|
||||
will all be overridden: releasever will be set to X.Y, releasever_major will be
|
||||
set to X, and releasever_minor will be set to Y, same as before. If a user
|
||||
wants to specify a custom releasever_major and releasever_minor, they have to
|
||||
set all three with `--setopt=releasever=X --setopt=releasever_major=Y
|
||||
--setopt=releasever_minor=z`, taking care to put `releasever_major` and
|
||||
`releasever_minor` after `releasever` so they are not overridden.
|
||||
|
||||
[1] https://issues.redhat.com/browse/RHEL-68034
|
||||
---
|
||||
dnf/base.py | 10 ++++++++--
|
||||
dnf/cli/cli.py | 11 +++++++++--
|
||||
dnf/const.py.in | 2 ++
|
||||
dnf/rpm/__init__.py | 43 +++++++++++++++++++++++++++++++++++++++----
|
||||
4 files changed, 58 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/dnf/base.py b/dnf/base.py
|
||||
index d0ce6364c..7d3dfdee7 100644
|
||||
--- a/dnf/base.py
|
||||
+++ b/dnf/base.py
|
||||
@@ -157,8 +157,14 @@ class Base(object):
|
||||
conf = dnf.conf.Conf()
|
||||
subst = conf.substitutions
|
||||
if 'releasever' not in subst:
|
||||
- subst['releasever'] = \
|
||||
- dnf.rpm.detect_releasever(conf.installroot)
|
||||
+ releasever, major, minor = \
|
||||
+ dnf.rpm.detect_releasevers(conf.installroot)
|
||||
+ subst['releasever'] = releasever
|
||||
+ if major is not None:
|
||||
+ subst['releasever_major'] = major
|
||||
+ if minor is not None:
|
||||
+ subst['releasever_minor'] = minor
|
||||
+
|
||||
return conf
|
||||
|
||||
def _setup_modular_excludes(self):
|
||||
diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py
|
||||
index c41f31ed6..ca0e35c4d 100644
|
||||
--- a/dnf/cli/cli.py
|
||||
+++ b/dnf/cli/cli.py
|
||||
@@ -994,13 +994,20 @@ class Cli(object):
|
||||
from_root = "/"
|
||||
subst = conf.substitutions
|
||||
subst.update_from_etc(from_root, varsdir=conf._get_value('varsdir'))
|
||||
+
|
||||
# cachedir, logs, releasever, and gpgkey are taken from or stored in installroot
|
||||
+ major = None
|
||||
+ minor = None
|
||||
if releasever is None and conf.releasever is None:
|
||||
- releasever = dnf.rpm.detect_releasever(conf.installroot)
|
||||
+ releasever, major, minor = dnf.rpm.detect_releasevers(conf.installroot)
|
||||
elif releasever == '/':
|
||||
- releasever = dnf.rpm.detect_releasever(releasever)
|
||||
+ releasever, major, minor = dnf.rpm.detect_releasevers(releasever)
|
||||
if releasever is not None:
|
||||
conf.releasever = releasever
|
||||
+ if major is not None:
|
||||
+ conf.releasever_major = major
|
||||
+ if minor is not None:
|
||||
+ conf.releasever_minor = minor
|
||||
if conf.releasever is None:
|
||||
logger.warning(_("Unable to detect release version (use '--releasever' to specify "
|
||||
"release version)"))
|
||||
diff --git a/dnf/const.py.in b/dnf/const.py.in
|
||||
index bcadc8041..07aab7a44 100644
|
||||
--- a/dnf/const.py.in
|
||||
+++ b/dnf/const.py.in
|
||||
@@ -25,6 +25,8 @@ CONF_AUTOMATIC_FILENAME='/etc/dnf/automatic.conf'
|
||||
DISTROVERPKG=('system-release(releasever)', 'system-release',
|
||||
'distribution-release(releasever)', 'distribution-release',
|
||||
'redhat-release', 'suse-release')
|
||||
+DISTROVER_MAJOR_PKG='system-release(releasever_major)'
|
||||
+DISTROVER_MINOR_PKG='system-release(releasever_minor)'
|
||||
GROUP_PACKAGE_TYPES = ('mandatory', 'default', 'conditional') # :api
|
||||
INSTALLONLYPKGS=['kernel', 'kernel-PAE',
|
||||
'installonlypkg(kernel)',
|
||||
diff --git a/dnf/rpm/__init__.py b/dnf/rpm/__init__.py
|
||||
index 12efca7fb..d4be4d03a 100644
|
||||
--- a/dnf/rpm/__init__.py
|
||||
+++ b/dnf/rpm/__init__.py
|
||||
@@ -26,12 +26,21 @@ import dnf.exceptions
|
||||
import rpm # used by ansible (dnf.rpm.rpm.labelCompare in lib/ansible/modules/packaging/os/dnf.py)
|
||||
|
||||
|
||||
-def detect_releasever(installroot):
|
||||
+def detect_releasevers(installroot):
|
||||
# :api
|
||||
- """Calculate the release version for the system."""
|
||||
+ """Calculate the release version for the system, including releasever_major
|
||||
+ and releasever_minor if they are overriden by the system-release-major or
|
||||
+ system-release-minor provides."""
|
||||
|
||||
ts = transaction.initReadOnlyTransaction(root=installroot)
|
||||
ts.pushVSFlags(~(rpm._RPMVSF_NOSIGNATURES | rpm._RPMVSF_NODIGESTS))
|
||||
+
|
||||
+ distrover_major_pkg = dnf.const.DISTROVER_MAJOR_PKG
|
||||
+ distrover_minor_pkg = dnf.const.DISTROVER_MINOR_PKG
|
||||
+ if dnf.pycomp.PY3:
|
||||
+ distrover_major_pkg = bytes(distrover_major_pkg, 'utf-8')
|
||||
+ distrover_minor_pkg = bytes(distrover_minor_pkg, 'utf-8')
|
||||
+
|
||||
for distroverpkg in dnf.const.DISTROVERPKG:
|
||||
if dnf.pycomp.PY3:
|
||||
distroverpkg = bytes(distroverpkg, 'utf-8')
|
||||
@@ -47,6 +56,8 @@ def detect_releasever(installroot):
|
||||
msg = 'Error: rpmdb failed to list provides. Try: rpm --rebuilddb'
|
||||
raise dnf.exceptions.Error(msg)
|
||||
releasever = hdr['version']
|
||||
+ releasever_major = None
|
||||
+ releasever_minor = None
|
||||
try:
|
||||
try:
|
||||
# header returns bytes -> look for bytes
|
||||
@@ -61,13 +72,37 @@ def detect_releasever(installroot):
|
||||
if hdr['name'] not in (distroverpkg, distroverpkg.decode("utf8")):
|
||||
# override the package version
|
||||
releasever = ver
|
||||
+
|
||||
+ for provide, flag, ver in zip(
|
||||
+ hdr[rpm.RPMTAG_PROVIDENAME],
|
||||
+ hdr[rpm.RPMTAG_PROVIDEFLAGS],
|
||||
+ hdr[rpm.RPMTAG_PROVIDEVERSION]):
|
||||
+ if isinstance(provide, str):
|
||||
+ provide = bytes(provide, "utf-8")
|
||||
+ if provide == distrover_major_pkg and flag == rpm.RPMSENSE_EQUAL and ver:
|
||||
+ releasever_major = ver
|
||||
+ if provide == distrover_minor_pkg and flag == rpm.RPMSENSE_EQUAL and ver:
|
||||
+ releasever_minor = ver
|
||||
+
|
||||
except (ValueError, KeyError, IndexError):
|
||||
pass
|
||||
|
||||
if is_py3bytes(releasever):
|
||||
releasever = str(releasever, "utf-8")
|
||||
- return releasever
|
||||
- return None
|
||||
+ if is_py3bytes(releasever_major):
|
||||
+ releasever_major = str(releasever_major, "utf-8")
|
||||
+ if is_py3bytes(releasever_minor):
|
||||
+ releasever_minor = str(releasever_minor, "utf-8")
|
||||
+ return releasever, releasever_major, releasever_minor
|
||||
+ return (None, None, None)
|
||||
+
|
||||
+
|
||||
+def detect_releasever(installroot):
|
||||
+ # :api
|
||||
+ """Calculate the release version for the system."""
|
||||
+
|
||||
+ releasever, _, _ = detect_releasevers(installroot)
|
||||
+ return releasever
|
||||
|
||||
|
||||
def _header(path):
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@ -0,0 +1,122 @@
|
||||
From 8478b6314237f830418bf478f68ca06d6d3d9f48 Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Fri, 24 Jan 2025 22:50:22 +0000
|
||||
Subject: [PATCH 07/11] Add --releasever-major and --releasever-minor options
|
||||
|
||||
Allows the user to override the $releasever_major and $releasever_minor
|
||||
variables on the command line, like --releasever.
|
||||
---
|
||||
dnf/cli/cli.py | 29 +++++++++++++++++------------
|
||||
dnf/cli/option_parser.py | 6 ++++++
|
||||
doc/command_ref.rst | 8 ++++++++
|
||||
doc/conf_ref.rst | 2 ++
|
||||
4 files changed, 33 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/dnf/cli/cli.py b/dnf/cli/cli.py
|
||||
index ca0e35c4d..21e8764d0 100644
|
||||
--- a/dnf/cli/cli.py
|
||||
+++ b/dnf/cli/cli.py
|
||||
@@ -859,7 +859,7 @@ class Cli(object):
|
||||
dnf.conf.PRIO_DEFAULT)
|
||||
self.demands.cacheonly = True
|
||||
self.base.conf._configure_from_options(opts)
|
||||
- self._read_conf_file(opts.releasever)
|
||||
+ self._read_conf_file(opts.releasever, opts.releasever_major, opts.releasever_minor)
|
||||
if 'arch' in opts:
|
||||
self.base.conf.arch = opts.arch
|
||||
self.base.conf._adjust_conf_options()
|
||||
@@ -968,7 +968,7 @@ class Cli(object):
|
||||
)
|
||||
)
|
||||
|
||||
- def _read_conf_file(self, releasever=None):
|
||||
+ def _read_conf_file(self, releasever=None, releasever_major=None, releasever_minor=None):
|
||||
timer = dnf.logging.Timer('config')
|
||||
conf = self.base.conf
|
||||
|
||||
@@ -996,18 +996,23 @@ class Cli(object):
|
||||
subst.update_from_etc(from_root, varsdir=conf._get_value('varsdir'))
|
||||
|
||||
# cachedir, logs, releasever, and gpgkey are taken from or stored in installroot
|
||||
- major = None
|
||||
- minor = None
|
||||
+
|
||||
+ det_major = None
|
||||
+ det_minor = None
|
||||
if releasever is None and conf.releasever is None:
|
||||
- releasever, major, minor = dnf.rpm.detect_releasevers(conf.installroot)
|
||||
+ releasever, det_major, det_minor = dnf.rpm.detect_releasevers(conf.installroot)
|
||||
elif releasever == '/':
|
||||
- releasever, major, minor = dnf.rpm.detect_releasevers(releasever)
|
||||
- if releasever is not None:
|
||||
- conf.releasever = releasever
|
||||
- if major is not None:
|
||||
- conf.releasever_major = major
|
||||
- if minor is not None:
|
||||
- conf.releasever_minor = minor
|
||||
+ releasever, det_major, det_minor = dnf.rpm.detect_releasevers(releasever)
|
||||
+
|
||||
+ def or_else(*args):
|
||||
+ for arg in args:
|
||||
+ if arg is not None:
|
||||
+ return arg
|
||||
+ return None
|
||||
+ conf.releasever = or_else(releasever, conf.releasever)
|
||||
+ conf.releasever_major = or_else(releasever_major, det_major, conf.releasever_major)
|
||||
+ conf.releasever_minor = or_else(releasever_minor, det_minor, conf.releasever_minor)
|
||||
+
|
||||
if conf.releasever is None:
|
||||
logger.warning(_("Unable to detect release version (use '--releasever' to specify "
|
||||
"release version)"))
|
||||
diff --git a/dnf/cli/option_parser.py b/dnf/cli/option_parser.py
|
||||
index 6bb32c517..cf52309d8 100644
|
||||
--- a/dnf/cli/option_parser.py
|
||||
+++ b/dnf/cli/option_parser.py
|
||||
@@ -202,6 +202,12 @@ class OptionParser(argparse.ArgumentParser):
|
||||
general_grp.add_argument("--releasever", default=None,
|
||||
help=_("override the value of $releasever"
|
||||
" in config and repo files"))
|
||||
+ general_grp.add_argument("--releasever-major", default=None,
|
||||
+ help=_("override the value of $releasever_major"
|
||||
+ " in config and repo files"))
|
||||
+ general_grp.add_argument("--releasever-minor", default=None,
|
||||
+ help=_("override the value of $releasever_minor"
|
||||
+ " in config and repo files"))
|
||||
general_grp.add_argument("--setopt", dest="setopts", default=[],
|
||||
action=self._SetoptsCallback,
|
||||
help=_("set arbitrary config and repo options"))
|
||||
diff --git a/doc/command_ref.rst b/doc/command_ref.rst
|
||||
index 30627bd4d..dc2e01efc 100644
|
||||
--- a/doc/command_ref.rst
|
||||
+++ b/doc/command_ref.rst
|
||||
@@ -335,6 +335,14 @@ Options
|
||||
Configure DNF as if the distribution release was ``<release>``. This can
|
||||
affect cache paths, values in configuration files and mirrorlist URLs.
|
||||
|
||||
+``--releasever_major=<major version>``
|
||||
+ Override the releasever_major variable, which is usually automatically
|
||||
+ detected or taken from the part of ``$releasever`` before the first ``.``.
|
||||
+
|
||||
+``--releasever_minor=<minor version>``
|
||||
+ Override the releasever_minor variable, which is usually automatically
|
||||
+ detected or taken from the part of ``$releasever`` after the first ``.``.
|
||||
+
|
||||
.. _repofrompath_options-label:
|
||||
|
||||
|
||||
diff --git a/doc/conf_ref.rst b/doc/conf_ref.rst
|
||||
index fdb34323c..07ab6e27b 100644
|
||||
--- a/doc/conf_ref.rst
|
||||
+++ b/doc/conf_ref.rst
|
||||
@@ -491,6 +491,8 @@ configuration file by your distribution to override the DNF defaults.
|
||||
|
||||
The ``$releasever_major`` and ``$releasever_minor`` variables will be automatically derived from ``$releasever`` by splitting it on the first ``.``. For example, if ``$releasever`` is set to ``1.23``, then ``$releasever_major`` will be ``1`` and ``$releasever_minor`` will be ``23``.
|
||||
|
||||
+ ``$releasever_major`` and ``$releasever_minor`` can also be set by the distribution.
|
||||
+
|
||||
See also :ref:`repo variables <repo-variables-label>`.
|
||||
|
||||
.. _reposdir-label:
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@ -0,0 +1,55 @@
|
||||
From c916d89d48e4579fd54f11971d24985e9ca3090a Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Mon, 27 Jan 2025 18:49:11 +0000
|
||||
Subject: [PATCH 08/11] doc: Document detect_releasevers and update example
|
||||
|
||||
Adds dnf.rpm.detect_releasevers to the API docs and mention it is
|
||||
now preferred over dnf.rpm.detect_releasever.
|
||||
|
||||
Updates examples/install_extension.py to use detect_releasevers and set
|
||||
the releasever_major and releasever_minor substitution variables.
|
||||
---
|
||||
doc/api_rpm.rst | 8 ++++++++
|
||||
doc/examples/install_extension.py | 6 +++++-
|
||||
2 files changed, 13 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/doc/api_rpm.rst b/doc/api_rpm.rst
|
||||
index c59ed67d1..562be41a4 100644
|
||||
--- a/doc/api_rpm.rst
|
||||
+++ b/doc/api_rpm.rst
|
||||
@@ -27,6 +27,14 @@
|
||||
|
||||
Returns ``None`` if the information can not be determined (perhaps because the tree has no RPMDB).
|
||||
|
||||
+.. function:: detect_releasevers(installroot)
|
||||
+
|
||||
+ Returns a tuple of the release name, overridden major release, and overridden minor release of the distribution of the tree rooted at `installroot`. The function uses information from RPMDB found under the tree. The major and minor release versions are usually derived from the release version by splitting it on the first ``.``, but distributions can override the derived major and minor versions. It's preferred to use ``detect_releasevers`` over ``detect_releasever``; if you use the latter, you will not be aware of distribution overrides for the major and minor release versions.
|
||||
+
|
||||
+ Returns ``(None, None, None)`` if the information can not be determined (perhaps because the tree has no RPMDB).
|
||||
+
|
||||
+ If the distribution does not override the release major version, then the second item of the returned tuple will be ``None``. Likewise, if the release minor version is not overridden, the third return value will be ``None``.
|
||||
+
|
||||
.. function:: basearch(arch)
|
||||
|
||||
Return base architecture of the processor based on `arch` type given. E.g. when `arch` i686 is given then the returned value will be i386.
|
||||
diff --git a/doc/examples/install_extension.py b/doc/examples/install_extension.py
|
||||
index dbd3b8904..b1540e12e 100644
|
||||
--- a/doc/examples/install_extension.py
|
||||
+++ b/doc/examples/install_extension.py
|
||||
@@ -32,8 +32,12 @@ if __name__ == '__main__':
|
||||
|
||||
with dnf.Base() as base:
|
||||
# Substitutions are needed for correct interpretation of repo files.
|
||||
- RELEASEVER = dnf.rpm.detect_releasever(base.conf.installroot)
|
||||
+ RELEASEVER, MAJOR, MINOR = dnf.rpm.detect_releasever(base.conf.installroot)
|
||||
base.conf.substitutions['releasever'] = RELEASEVER
|
||||
+ if MAJOR is not None:
|
||||
+ base.conf.substitutions['releasever_major'] = MAJOR
|
||||
+ if MINOR is not None:
|
||||
+ base.conf.substitutions['releasever_minor'] = MINOR
|
||||
# Repositories are needed if we want to install anything.
|
||||
base.read_all_repos()
|
||||
# A sack is required by marking methods and dependency resolving.
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@ -0,0 +1,128 @@
|
||||
From d0058b39d1d009856c85522908cb85ad59cf0ef2 Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Mon, 27 Jan 2025 19:20:14 +0000
|
||||
Subject: [PATCH 09/11] tests: Patch detect_releasevers, not detect_releasever
|
||||
|
||||
---
|
||||
tests/api/test_dnf_rpm.py | 4 ++++
|
||||
tests/cli/commands/test_clean.py | 2 +-
|
||||
tests/support.py | 2 +-
|
||||
tests/test_base.py | 4 ++--
|
||||
tests/test_cli.py | 10 +++++-----
|
||||
5 files changed, 13 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/tests/api/test_dnf_rpm.py b/tests/api/test_dnf_rpm.py
|
||||
index e6d8de847..fb606ffcd 100644
|
||||
--- a/tests/api/test_dnf_rpm.py
|
||||
+++ b/tests/api/test_dnf_rpm.py
|
||||
@@ -14,6 +14,10 @@ class DnfRpmApiTest(TestCase):
|
||||
# dnf.rpm.detect_releasever
|
||||
self.assertHasAttr(dnf.rpm, "detect_releasever")
|
||||
|
||||
+ def test_detect_releasevers(self):
|
||||
+ # dnf.rpm.detect_releasevers
|
||||
+ self.assertHasAttr(dnf.rpm, "detect_releasevers")
|
||||
+
|
||||
def test_basearch(self):
|
||||
# dnf.rpm.basearch
|
||||
self.assertHasAttr(dnf.rpm, "basearch")
|
||||
diff --git a/tests/cli/commands/test_clean.py b/tests/cli/commands/test_clean.py
|
||||
index cc0a5df30..c77cb3efe 100644
|
||||
--- a/tests/cli/commands/test_clean.py
|
||||
+++ b/tests/cli/commands/test_clean.py
|
||||
@@ -31,7 +31,7 @@ from tests.support import mock
|
||||
'''
|
||||
def _run(cli, args):
|
||||
with mock.patch('sys.stdout', new_callable=StringIO), \
|
||||
- mock.patch('dnf.rpm.detect_releasever', return_value=69):
|
||||
+ mock.patch('dnf.rpm.detect_releasevers', return_value=(69, None, None)):
|
||||
cli.configure(['clean', '--config', '/dev/null'] + args)
|
||||
cli.run()
|
||||
|
||||
diff --git a/tests/support.py b/tests/support.py
|
||||
index e50684ef5..d03683edc 100644
|
||||
--- a/tests/support.py
|
||||
+++ b/tests/support.py
|
||||
@@ -177,7 +177,7 @@ def command_run(cmd, args):
|
||||
|
||||
class Base(dnf.Base):
|
||||
def __init__(self, *args, **kwargs):
|
||||
- with mock.patch('dnf.rpm.detect_releasever', return_value=69):
|
||||
+ with mock.patch('dnf.rpm.detect_releasevers', return_value=(69, None, None)):
|
||||
super(Base, self).__init__(*args, **kwargs)
|
||||
|
||||
# mock objects
|
||||
diff --git a/tests/test_base.py b/tests/test_base.py
|
||||
index ad3ef6759..9e0a656d3 100644
|
||||
--- a/tests/test_base.py
|
||||
+++ b/tests/test_base.py
|
||||
@@ -57,7 +57,7 @@ class BaseTest(tests.support.TestCase):
|
||||
self.assertIsNotNone(base)
|
||||
base.close()
|
||||
|
||||
- @mock.patch('dnf.rpm.detect_releasever', lambda x: 'x')
|
||||
+ @mock.patch('dnf.rpm.detect_releasevers', lambda x: ('x', None, None))
|
||||
@mock.patch('dnf.util.am_i_root', lambda: True)
|
||||
def test_default_config_root(self):
|
||||
base = dnf.Base()
|
||||
@@ -67,7 +67,7 @@ class BaseTest(tests.support.TestCase):
|
||||
self.assertIsNotNone(reg.match(base.conf.cachedir))
|
||||
base.close()
|
||||
|
||||
- @mock.patch('dnf.rpm.detect_releasever', lambda x: 'x')
|
||||
+ @mock.patch('dnf.rpm.detect_releasevers', lambda x: ('x', None, None))
|
||||
@mock.patch('dnf.util.am_i_root', lambda: False)
|
||||
def test_default_config_user(self):
|
||||
base = dnf.Base()
|
||||
diff --git a/tests/test_cli.py b/tests/test_cli.py
|
||||
index 9c130c368..573d4ae2b 100644
|
||||
--- a/tests/test_cli.py
|
||||
+++ b/tests/test_cli.py
|
||||
@@ -191,7 +191,7 @@ class ConfigureTest(tests.support.DnfBaseTestCase):
|
||||
# call setUp() once again *after* am_i_root() is mocked so the cachedir is set as expected
|
||||
self.setUp()
|
||||
self.base._conf.installroot = self._installroot
|
||||
- with mock.patch('dnf.rpm.detect_releasever', return_value=69):
|
||||
+ with mock.patch('dnf.rpm.detect_releasevers', return_value=(69, None, None)):
|
||||
self.cli.configure(['update', '-c', self.conffile])
|
||||
reg = re.compile('^' + self._installroot + '/var/tmp/dnf-[.a-zA-Z0-9_-]+$')
|
||||
self.assertIsNotNone(reg.match(self.base.conf.cachedir))
|
||||
@@ -203,7 +203,7 @@ class ConfigureTest(tests.support.DnfBaseTestCase):
|
||||
def test_configure_root(self):
|
||||
""" Test Cli.configure as root."""
|
||||
self.base._conf = dnf.conf.Conf()
|
||||
- with mock.patch('dnf.rpm.detect_releasever', return_value=69):
|
||||
+ with mock.patch('dnf.rpm.detect_releasevers', return_value=(69, None, None)):
|
||||
self.cli.configure(['update', '--nogpgcheck', '-c', self.conffile])
|
||||
reg = re.compile('^/var/cache/dnf$')
|
||||
self.assertIsNotNone(reg.match(self.base.conf.system_cachedir))
|
||||
@@ -213,7 +213,7 @@ class ConfigureTest(tests.support.DnfBaseTestCase):
|
||||
|
||||
def test_configure_verbose(self):
|
||||
self.base._conf.installroot = self._installroot
|
||||
- with mock.patch('dnf.rpm.detect_releasever', return_value=69):
|
||||
+ with mock.patch('dnf.rpm.detect_releasevers', return_value=(69, None, None)):
|
||||
self.cli.configure(['-v', 'update', '-c', self.conffile])
|
||||
parser = argparse.ArgumentParser()
|
||||
expected = "%s -v update -c %s " % (parser.prog, self.conffile)
|
||||
@@ -225,7 +225,7 @@ class ConfigureTest(tests.support.DnfBaseTestCase):
|
||||
@mock.patch('os.path.exists', return_value=True)
|
||||
def test_conf_exists_in_installroot(self, ospathexists):
|
||||
with mock.patch('logging.Logger.warning'), \
|
||||
- mock.patch('dnf.rpm.detect_releasever', return_value=69):
|
||||
+ mock.patch('dnf.rpm.detect_releasevers', return_value=(69, None, None)):
|
||||
self.cli.configure(['--installroot', '/roots/dnf', 'update'])
|
||||
self.assertEqual(self.base.conf.config_file_path, '/roots/dnf/etc/dnf/dnf.conf')
|
||||
self.assertEqual(self.base.conf.installroot, '/roots/dnf')
|
||||
@@ -233,7 +233,7 @@ class ConfigureTest(tests.support.DnfBaseTestCase):
|
||||
@mock.patch('dnf.cli.cli.Cli._parse_commands', new=mock.MagicMock)
|
||||
@mock.patch('os.path.exists', return_value=False)
|
||||
def test_conf_notexists_in_installroot(self, ospathexists):
|
||||
- with mock.patch('dnf.rpm.detect_releasever', return_value=69):
|
||||
+ with mock.patch('dnf.rpm.detect_releasevers', return_value=(69, None, None)):
|
||||
self.cli.configure(['--installroot', '/roots/dnf', 'update'])
|
||||
self.assertEqual(self.base.conf.config_file_path, '/etc/dnf/dnf.conf')
|
||||
self.assertEqual(self.base.conf.installroot, '/roots/dnf')
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@ -0,0 +1,96 @@
|
||||
From c3ba8afd83f4df5a3ed66088a458d65926a03716 Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Tue, 4 Feb 2025 23:01:43 +0000
|
||||
Subject: [PATCH 10/11] Document how --releasever, --releasever_{major,minor}
|
||||
affect each other
|
||||
|
||||
---
|
||||
dnf/conf/config.py | 16 ++++++++++++++++
|
||||
doc/command_ref.rst | 2 ++
|
||||
tests/test_config.py | 3 +++
|
||||
3 files changed, 21 insertions(+)
|
||||
|
||||
diff --git a/dnf/conf/config.py b/dnf/conf/config.py
|
||||
index 49280e522..3bcd2f3d3 100644
|
||||
--- a/dnf/conf/config.py
|
||||
+++ b/dnf/conf/config.py
|
||||
@@ -424,6 +424,12 @@ class MainConf(BaseConfig):
|
||||
@releasever.setter
|
||||
def releasever(self, val):
|
||||
# :api
|
||||
+ """
|
||||
+ Sets the releasever variable and sets releasever_major and
|
||||
+ releasever_minor accordingly. releasever_major is set to the part of
|
||||
+ $releasever before the first ".". releasever_minor is set to the part
|
||||
+ after the first ".".
|
||||
+ """
|
||||
if val is None:
|
||||
self.substitutions.pop('releasever', None)
|
||||
return
|
||||
@@ -437,6 +443,11 @@ class MainConf(BaseConfig):
|
||||
@releasever_major.setter
|
||||
def releasever_major(self, val):
|
||||
# :api
|
||||
+ """
|
||||
+ Override the releasever_major variable, which is usually derived from
|
||||
+ the releasever variable. This setter does not update the value of
|
||||
+ $releasever.
|
||||
+ """
|
||||
if val is None:
|
||||
self.substitutions.pop('releasever_major', None)
|
||||
return
|
||||
@@ -445,6 +456,11 @@ class MainConf(BaseConfig):
|
||||
@property
|
||||
def releasever_minor(self):
|
||||
# :api
|
||||
+ """
|
||||
+ Override the releasever_minor variable, which is usually derived from
|
||||
+ the releasever variable. This setter does not update the value of
|
||||
+ $releasever.
|
||||
+ """
|
||||
return self.substitutions.get('releasever_minor')
|
||||
|
||||
@releasever_minor.setter
|
||||
diff --git a/doc/command_ref.rst b/doc/command_ref.rst
|
||||
index dc2e01efc..1a20ae397 100644
|
||||
--- a/doc/command_ref.rst
|
||||
+++ b/doc/command_ref.rst
|
||||
@@ -338,10 +338,12 @@ Options
|
||||
``--releasever_major=<major version>``
|
||||
Override the releasever_major variable, which is usually automatically
|
||||
detected or taken from the part of ``$releasever`` before the first ``.``.
|
||||
+ This option does not affect the ``$releasever`` variable.
|
||||
|
||||
``--releasever_minor=<minor version>``
|
||||
Override the releasever_minor variable, which is usually automatically
|
||||
detected or taken from the part of ``$releasever`` after the first ``.``.
|
||||
+ This option does not affect the ``$releasever`` variable.
|
||||
|
||||
.. _repofrompath_options-label:
|
||||
|
||||
diff --git a/tests/test_config.py b/tests/test_config.py
|
||||
index 16bdcccba..69ba988c4 100644
|
||||
--- a/tests/test_config.py
|
||||
+++ b/tests/test_config.py
|
||||
@@ -149,15 +149,18 @@ class ConfTest(tests.support.TestCase):
|
||||
def test_releasever_major_minor(self):
|
||||
conf = Conf()
|
||||
conf.releasever = '1.2'
|
||||
+ self.assertEqual(conf.releasever, '1.2')
|
||||
self.assertEqual(conf.releasever_major, '1')
|
||||
self.assertEqual(conf.releasever_minor, '2')
|
||||
|
||||
# override releasever_major
|
||||
conf.releasever_major = '3'
|
||||
+ self.assertEqual(conf.releasever, '1.2')
|
||||
self.assertEqual(conf.releasever_major, '3')
|
||||
self.assertEqual(conf.releasever_minor, '2')
|
||||
|
||||
# override releasever_minor
|
||||
conf.releasever_minor = '4'
|
||||
+ self.assertEqual(conf.releasever, '1.2')
|
||||
self.assertEqual(conf.releasever_major, '3')
|
||||
self.assertEqual(conf.releasever_minor, '4')
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@ -0,0 +1,39 @@
|
||||
From 45429b40f588c739fab8e369d92fac3b78472b19 Mon Sep 17 00:00:00 2001
|
||||
From: Evan Goode <mail@evangoo.de>
|
||||
Date: Fri, 7 Feb 2025 14:22:09 -0500
|
||||
Subject: [PATCH 11/11] Move releasever_minor setter docstring to the correct
|
||||
function
|
||||
|
||||
---
|
||||
dnf/conf/config.py | 10 +++++-----
|
||||
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/dnf/conf/config.py b/dnf/conf/config.py
|
||||
index 3bcd2f3d3..b6a1b0f2f 100644
|
||||
--- a/dnf/conf/config.py
|
||||
+++ b/dnf/conf/config.py
|
||||
@@ -456,16 +456,16 @@ class MainConf(BaseConfig):
|
||||
@property
|
||||
def releasever_minor(self):
|
||||
# :api
|
||||
- """
|
||||
- Override the releasever_minor variable, which is usually derived from
|
||||
- the releasever variable. This setter does not update the value of
|
||||
- $releasever.
|
||||
- """
|
||||
return self.substitutions.get('releasever_minor')
|
||||
|
||||
@releasever_minor.setter
|
||||
def releasever_minor(self, val):
|
||||
# :api
|
||||
+ """
|
||||
+ Override the releasever_minor variable, which is usually derived from
|
||||
+ the releasever variable. This setter does not update the value of
|
||||
+ $releasever.
|
||||
+ """
|
||||
if val is None:
|
||||
self.substitutions.pop('releasever_minor', None)
|
||||
return
|
||||
--
|
||||
2.49.0
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
%define __cmake_in_source_build 1
|
||||
|
||||
# default dependencies
|
||||
%global hawkey_version 0.74.0
|
||||
%global hawkey_version 0.75.0
|
||||
%global libcomps_version 0.1.8
|
||||
%global libmodulemd_version 2.9.3
|
||||
%global rpm_version 4.14.0
|
||||
@ -22,7 +22,7 @@
|
||||
%endif
|
||||
|
||||
%if 0%{?rhel} == 9
|
||||
%global hawkey_version 0.69.0-13
|
||||
%global hawkey_version 0.69.0-16
|
||||
%endif
|
||||
|
||||
# override dependencies for fedora 26
|
||||
@ -73,7 +73,7 @@ It supports RPMs, modules and comps groups & environments.
|
||||
|
||||
Name: dnf
|
||||
Version: 4.14.0
|
||||
Release: 25%{?dist}.alma.1
|
||||
Release: 31%{?dist}.alma.1
|
||||
Summary: %{pkg_summary}
|
||||
# For a breakdown of the licensing, see PACKAGE-LICENSING
|
||||
License: GPLv2+
|
||||
@ -123,6 +123,29 @@ Patch41: 0041-bootc-Use-ostree-GObject-API-to-get-deployment-statu.patch
|
||||
Patch42: 0042-bootc-Re-locking-use-ostree-admin-unlock-transient.patch
|
||||
Patch43: 0043-spec-Add-dnf-bootc-subpackage.patch
|
||||
Patch44: 0044-Require-libdnf-0.74.0-with-persistence-option.patch
|
||||
Patch45: 0045-package-remote_location-takes-basedir-into-account.patch
|
||||
Patch46: 0046-Usage-help-don-t-mark-mandatory-option-parameters-as.patch
|
||||
Patch47: 0047-Fix-typo-from-previous-commit-left-over.patch
|
||||
Patch48: 0048-disableexcludes-and-disableexcludepkgs-values-are-no.patch
|
||||
Patch49: 0049-bootc-tmt-testing.patch
|
||||
Patch50: 0050-persistence-store-persist-transient-in-history-DB.patch
|
||||
Patch51: 0051-Print-persist-or-transient-in-history-info.patch
|
||||
Patch52: 0052-history-persistence-for-MergedTransaction.patch
|
||||
Patch53: 0053-bootc-Check-whether-protected-paths-will-be-modified.patch
|
||||
Patch54: 0054-spec-package-etc-dnf-usr_drift_protected_paths.d.patch
|
||||
Patch55: 0055-Support-globs-in-usr_drift_protected_paths.patch
|
||||
Patch56: 0056-doc-Document-usr_drift_protected_paths.patch
|
||||
Patch57: 0057-conf-Add-test-for-shell-like-variable-expansion.patch
|
||||
Patch58: 0058-Split-releasever-to-releasever_major-and-releasever_.patch
|
||||
Patch59: 0059-Document-releasever_major-and-releasever_minor.patch
|
||||
Patch60: 0060-Document-shell-like-parameter-expansion-for-variable.patch
|
||||
Patch61: 0061-Derive-releasever_-major-minor-in-conf-not-substitut.patch
|
||||
Patch62: 0062-Override-releasever_-major-minor-with-provides.patch
|
||||
Patch63: 0063-Add-releasever-major-and-releasever-minor-options.patch
|
||||
Patch64: 0064-doc-Document-detect_releasevers-and-update-example.patch
|
||||
Patch65: 0065-tests-Patch-detect_releasevers-not-detect_releasever.patch
|
||||
Patch66: 0066-Document-how-releasever-releasever_-major-minor-affe.patch
|
||||
Patch67: 0067-Move-releasever_minor-setter-docstring-to-the-correc.patch
|
||||
|
||||
# AlmaLinux Patch
|
||||
Patch10000: almalinux_bugtracker.patch
|
||||
@ -222,6 +245,7 @@ Requires: rpm-plugin-systemd-inhibit
|
||||
%else
|
||||
Recommends: (rpm-plugin-systemd-inhibit if systemd)
|
||||
%endif
|
||||
Provides: dnf4 = %{version}-%{release}
|
||||
|
||||
%description -n python3-%{name}
|
||||
Python 3 interface to DNF.
|
||||
@ -277,6 +301,7 @@ mkdir -p %{buildroot}%{_localstatedir}/log/
|
||||
mkdir -p %{buildroot}%{_var}/cache/dnf/
|
||||
touch %{buildroot}%{_localstatedir}/log/%{name}.log
|
||||
ln -sr %{buildroot}%{_bindir}/dnf-3 %{buildroot}%{_bindir}/dnf
|
||||
ln -sr %{buildroot}%{_bindir}/dnf-3 %{buildroot}%{_bindir}/dnf4
|
||||
mv %{buildroot}%{_bindir}/dnf-automatic-3 %{buildroot}%{_bindir}/dnf-automatic
|
||||
rm -vf %{buildroot}%{_bindir}/dnf-automatic-*
|
||||
|
||||
@ -350,6 +375,7 @@ popd
|
||||
%dir %{confdir}/modules.defaults.d
|
||||
%dir %{pluginconfpath}
|
||||
%dir %{confdir}/protected.d
|
||||
%dir %{confdir}/usr-drift-protected-paths.d
|
||||
%dir %{confdir}/vars
|
||||
%dir %{confdir}/aliases.d
|
||||
%exclude %{confdir}/aliases.d/zypper.conf
|
||||
@ -405,6 +431,7 @@ popd
|
||||
|
||||
%files -n python3-%{name}
|
||||
%{_bindir}/%{name}-3
|
||||
%{_bindir}/%{name}4
|
||||
%exclude %{python3_sitelib}/%{name}/automatic
|
||||
%{python3_sitelib}/%{name}/
|
||||
%dir %{py3pluginpath}
|
||||
@ -428,9 +455,29 @@ popd
|
||||
# bootc subpackage does not include any files
|
||||
|
||||
%changelog
|
||||
* Tue May 13 2025 Eduard Abdullin <eabdullin@almalinux.org> - 4.14.0-25.alma.1
|
||||
* Tue Nov 11 2025 Eduard Abdullin <eabdullin@almalinux.org> - 4.14.0-31.alma.1
|
||||
- Added patch for almalinux bugtracker
|
||||
|
||||
* Mon Jun 30 2025 Evan Goode <egoode@redhat.com> - 4.14.0-31
|
||||
- Introduce $releasever_major, $releasever_minor variables, shell-style
|
||||
variable substitution (RHEL-65817)
|
||||
|
||||
* Thu Jun 26 2025 Evan Goode <egoode@redhat.com> - 4.14.0-30
|
||||
- Mark transient transactions in DNF history (RHEL-84512)
|
||||
- Warn/disallow changes outside /usr, /etc with --transient (RHEL-84499)
|
||||
|
||||
* Fri May 02 2025 Ales Matej <amatej@redhat.com> - 4.14.0-29
|
||||
- man page: don't mark mandatory option parameters as optional (RHEL-63958)
|
||||
|
||||
* Fri Apr 04 2025 Evan Goode <egoode@redhat.com> - 4.14.0-28
|
||||
- Add dnf4 provides and symlink /usr/bin/dnf4 -> /usr/bin/dnf-3 (RHEL-82310)
|
||||
|
||||
* Fri Mar 07 2025 Ales Matej <amatej@redhat.com> - 4.14.0-27
|
||||
- usage help: don't mark mandatory option parameters as optional (RHEL-63958)
|
||||
|
||||
* Fri Mar 07 2025 Marek Blaha <mblaha@redhat.com> - 4.14.0-26
|
||||
- package: remote_location() takes basedir into account (RHEL-71125)
|
||||
|
||||
* Tue Feb 04 2025 Petr Pisar <ppisar@redhat.com> - 4.14.0-25
|
||||
- Add support for transient transactions (RHEL-70917)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user