import CS libdnf-0.73.1-15.el10

This commit is contained in:
AlmaLinux RelEng Bot 2026-05-19 15:12:41 -04:00
parent 63a639a61a
commit cb0427830a
13 changed files with 573 additions and 21 deletions

View File

@ -0,0 +1,206 @@
From 433af8870a741f04d2e55616e83d251a972eac32 Mon Sep 17 00:00:00 2001
From: Matej Focko <mfocko@redhat.com>
Date: Fri, 30 Jan 2026 12:28:09 +0100
Subject: [PATCH] fix: compare RPMItem in transaction with rpmvercmp
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Previous implementation resorts to manual comparison of the EVR fields
including the following issues:
• There appears to be a typo when comparing epochs:
} else if (epoch < 0) {
instead of
} else if (epochDif < 0) {
N.B. epoch < 0 is unreachable
• RPM packaging guidelines **do not** define any requirements on the
value (and is internally represented as int32_t)
• On the contrary Fedora packaging guidelines denote:
If present, it MUST consist of a positive integer.
• There is a manual parsing of the version fields by “chopping off” the
parts ofversion and parsing them via std::stoi.
• More importantly, reported by bugs below, the release fields are
ignored altogether.
Instead of manually processing the EVR, with a potential room to error,
switch to using the ::rpmvercmp from rpm/rpmver.h that should be the
“source of truth” in this case.
Also cover the discovered problems with regression tests in unit tests.
Fixes RHEL-81778
Fixes RHEL-81779
Fixes RHEL-128443 (RHEL10 clone of RHEL-81779)
Signed-off-by: Matej Focko <mfocko@redhat.com>
(cherry picked from commit 1bcd660168302c120b73b99238babf39f3131faa)
---
libdnf/transaction/RPMItem.cpp | 39 +++++++--------
tests/libdnf/transaction/RpmItemTest.cpp | 61 ++++++++++++++++++++++++
tests/libdnf/transaction/RpmItemTest.hpp | 2 +
3 files changed, 80 insertions(+), 22 deletions(-)
diff --git a/libdnf/transaction/RPMItem.cpp b/libdnf/transaction/RPMItem.cpp
index ecce789d..92c26d09 100644
--- a/libdnf/transaction/RPMItem.cpp
+++ b/libdnf/transaction/RPMItem.cpp
@@ -20,6 +20,7 @@
#include <algorithm>
#include <map>
+#include <rpm/rpmver.h>
#include <sstream>
#include "../hy-subject.h"
@@ -343,35 +344,29 @@ RPMItem::resolveTransactionItemReason(SQLite3Ptr conn,
* Compare RPM packages
* This method doesn't care about compare package names
* \param other RPMItem to compare with
- * \return true if other package is newer (has higher version and/or epoch)
+ * \return true if other package is newer (has higher epoch, version, or release)
*/
bool
RPMItem::operator<(const RPMItem &other) const
{
- // compare epochs
- int32_t epochDif = other.getEpoch() - getEpoch();
- if (epochDif > 0) {
- return true;
- } else if (epoch < 0) {
- return false;
+ // Compare epochs
+ if (getEpoch() != other.getEpoch()) {
+ return getEpoch() < other.getEpoch();
}
- // compare versions
- std::stringstream versionThis(getVersion());
- std::stringstream versionOther(other.getVersion());
-
- std::string bufferThis;
- std::string bufferOther;
- while (std::getline(versionThis, bufferThis, '.') &&
- std::getline(versionOther, bufferOther, '.')) {
- int subVersionThis = std::stoi(bufferThis);
- int subVersionOther = std::stoi(bufferOther);
- if (subVersionThis == subVersionOther) {
- continue;
- }
- return subVersionOther > subVersionThis;
+ // Compare versions
+ auto version = getVersion();
+ auto otherVersion = other.getVersion();
+ auto cmpResult = ::rpmvercmp(version.c_str(), otherVersion.c_str());
+ if (cmpResult != 0) {
+ return cmpResult < 0;
}
- return false;
+
+ // Compare releases
+ auto release = getRelease();
+ auto otherRelease = other.getRelease();
+ cmpResult = ::rpmvercmp(release.c_str(), otherRelease.c_str());
+ return cmpResult < 0;
}
std::vector< int64_t >
diff --git a/tests/libdnf/transaction/RpmItemTest.cpp b/tests/libdnf/transaction/RpmItemTest.cpp
index 774c716a..503e4ec3 100644
--- a/tests/libdnf/transaction/RpmItemTest.cpp
+++ b/tests/libdnf/transaction/RpmItemTest.cpp
@@ -119,3 +119,64 @@ RpmItemTest::testGetTransactionItems()
//CPPUNIT_ASSERT(createMs.count() == 0);
//CPPUNIT_ASSERT(readMs.count() == 0);
}
+
+/**
+ * Regression test for RHEL-81778
+ * Regression test for RHEL-81779
+ */
+void
+RpmItemTest::testComparison()
+{
+ auto a = std::make_shared< RPMItem >(conn);
+ a->setName("rsyslog");
+ a->setEpoch(0);
+ a->setVersion("8.2102.0");
+ a->setRelease("1.el9");
+ a->setArch("aarch64");
+
+ auto b = std::make_shared< RPMItem >(conn);
+ b->setName("rsyslog");
+ b->setEpoch(0);
+ b->setVersion("8.2102.0");
+ b->setRelease("5.el9");
+ b->setArch("aarch64");
+
+ // rsyslog-8.2102.0-1.el9.aarch64 < rsyslog-8.2102.0-5.el9.aarch64
+ CPPUNIT_ASSERT(*a < *b);
+ CPPUNIT_ASSERT(!(*b < *a));
+
+ a->setRelease("2.el9");
+ b->setRelease("1.el9");
+
+ // rsyslog-8.2102.0-1.el9.aarch64 < rsyslog-8.2102.0-2.el9.aarch64
+ CPPUNIT_ASSERT(*b < *a);
+ CPPUNIT_ASSERT(!(*a < *b));
+
+ b->setRelease("10.el9");
+
+ // rsyslog-8.2102.0-2.el9.aarch64 < rsyslog-8.2102.0-10.el9.aarch64
+ CPPUNIT_ASSERT(*a < *b);
+ CPPUNIT_ASSERT(!(*b < *a));
+
+ // Cover fixed comparison of epochs (previously falling through to version
+ // comparison when left side being newer)
+ {
+ auto a = std::make_shared< RPMItem >(conn);
+ a->setName("rsyslog");
+ a->setEpoch(0);
+ a->setVersion("8.2102.0");
+ a->setRelease("1.el9");
+ a->setArch("aarch64");
+
+ auto b = std::make_shared< RPMItem >(conn);
+ b->setName("rsyslog");
+ b->setEpoch(3);
+ b->setVersion("8.2101.0");
+ b->setRelease("1.el9");
+ b->setArch("aarch64");
+
+ // rsyslog-0:8.2102.0-1.el9.aarch64 < rsyslog-3:8.2101.0-1.el9.aarch64
+ CPPUNIT_ASSERT(*a < *b);
+ CPPUNIT_ASSERT(!(*b < *a));
+ }
+}
diff --git a/tests/libdnf/transaction/RpmItemTest.hpp b/tests/libdnf/transaction/RpmItemTest.hpp
index 59cc6c59..bb4cd930 100644
--- a/tests/libdnf/transaction/RpmItemTest.hpp
+++ b/tests/libdnf/transaction/RpmItemTest.hpp
@@ -10,6 +10,7 @@ class RpmItemTest : public CppUnit::TestCase {
CPPUNIT_TEST(testCreate);
CPPUNIT_TEST(testCreateDuplicates);
CPPUNIT_TEST(testGetTransactionItems);
+ CPPUNIT_TEST(testComparison);
CPPUNIT_TEST_SUITE_END();
public:
@@ -19,6 +20,7 @@ public:
void testCreate();
void testCreateDuplicates();
void testGetTransactionItems();
+ void testComparison();
private:
std::shared_ptr< SQLite3 > conn;
--
2.52.0

View File

@ -0,0 +1,34 @@
From 9d5c8b965294d52a0feda55f274d033a279fe090 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Fri, 9 Jan 2026 07:26:34 +0100
Subject: [PATCH 1/5] Mark all protected packages as user installed for all
transactions
Closes: https://github.com/rpm-software-management/dnf/issues/2192
---
libdnf/goal/Goal.cpp | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/libdnf/goal/Goal.cpp b/libdnf/goal/Goal.cpp
index 9882273c..f2b20ced 100644
--- a/libdnf/goal/Goal.cpp
+++ b/libdnf/goal/Goal.cpp
@@ -987,6 +987,15 @@ Goal::jobLength()
bool
Goal::run(DnfGoalActions flags)
{
+ // Automatically mark all protected packages as user installed.
+ // When a protected package is installed as a dependency it can block
+ // removal of the last package that depends on it (because the protected
+ // package cannot be removed, not even as an unused dependency).
+ // To prevent this and still correctly resolve dependencies of the protected
+ // packages mark them all as user installed.
+ if (pImpl->protectedPkgs) {
+ userInstalled(*pImpl->protectedPkgs);
+ }
auto job = pImpl->constructJob(flags);
pImpl->actions = static_cast<DnfGoalActions>(pImpl->actions | flags);
int ret = pImpl->solve(job->getQueue(), flags);
--
2.53.0

View File

@ -0,0 +1,149 @@
From 93d8bfbe36913804d8963f04e4d9491d6bfa25a1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Mon, 26 Jan 2026 14:07:37 +0100
Subject: [PATCH 2/5] Add `filterUnneededExtraUserinstalled` and Python version
to the API
This can be used to get unneeded packages with for example protected
packages extra marked as userinstalled.
---
libdnf/sack/query.cpp | 18 +++++++++++----
libdnf/sack/query.hpp | 1 +
python/hawkey/query-py.cpp | 47 ++++++++++++++++++++++++++++++++++++++
3 files changed, 62 insertions(+), 4 deletions(-)
diff --git a/libdnf/sack/query.cpp b/libdnf/sack/query.cpp
index e4682927..c1c50ec1 100644
--- a/libdnf/sack/query.cpp
+++ b/libdnf/sack/query.cpp
@@ -830,7 +830,7 @@ private:
void filterUpdownByPriority(const Filter & f, Map *m);
void filterUpdownAble(const Filter &f, Map *m);
void filterDataiterator(const Filter & f, Map *m);
- int filterUnneededOrSafeToRemove(const Swdb &swdb, bool debug_solver, bool safeToRemove);
+ int filterUnneededOrSafeToRemove(const Swdb &swdb, bool debug_solver, bool safeToRemove, PackageSet *extra_userinstalled);
void obsoletesByPriority(Pool * pool, Solvable * candidate, Map * m, const Map * target, int obsprovides);
bool isGlob(const std::vector<const char *> &matches) const;
@@ -2245,7 +2245,7 @@ Query::Impl::filterDataiterator(const Filter & f, Map *m)
}
int
-Query::Impl::filterUnneededOrSafeToRemove(const Swdb &swdb, bool debug_solver, bool safeToRemove)
+Query::Impl::filterUnneededOrSafeToRemove(const Swdb &swdb, bool debug_solver, bool safeToRemove, PackageSet *extra_userinstalled)
{
apply();
Goal goal(sack);
@@ -2260,6 +2260,10 @@ Query::Impl::filterUnneededOrSafeToRemove(const Swdb &swdb, bool debug_solver, b
}
goal.userInstalled(*userInstalled);
+ if (extra_userinstalled != NULL) {
+ goal.userInstalled(*extra_userinstalled);
+ }
+
int ret1 = goal.run(DNF_NONE);
if (ret1)
return -1;
@@ -2575,13 +2579,19 @@ Query::filterDuplicated()
int
Query::filterUnneeded(const Swdb &swdb, bool debug_solver)
{
- return pImpl->filterUnneededOrSafeToRemove(swdb, debug_solver, false);
+ return pImpl->filterUnneededOrSafeToRemove(swdb, debug_solver, false, NULL);
}
int
Query::filterSafeToRemove(const Swdb &swdb, bool debug_solver)
{
- return pImpl->filterUnneededOrSafeToRemove(swdb, debug_solver, true);
+ return pImpl->filterUnneededOrSafeToRemove(swdb, debug_solver, true, NULL);
+}
+
+int
+Query::filterUnneededExtraUserinstalled(const Swdb &swdb, PackageSet &extra_userinstalled, bool debug_solver)
+{
+ return pImpl->filterUnneededOrSafeToRemove(swdb, debug_solver, false, &extra_userinstalled);
}
void
diff --git a/libdnf/sack/query.hpp b/libdnf/sack/query.hpp
index 306b24e3..a5ed7745 100644
--- a/libdnf/sack/query.hpp
+++ b/libdnf/sack/query.hpp
@@ -177,6 +177,7 @@ public:
void filterRecent(const long unsigned int recent_limit);
void filterDuplicated();
int filterUnneeded(const Swdb &swdb, bool debug_solver);
+ int filterUnneededExtraUserinstalled(const Swdb &swdb, PackageSet &extra_userinstalled, bool debug_solver);
int filterSafeToRemove(const Swdb &swdb, bool debug_solver);
void getAdvisoryPkgs(int cmpType, std::vector<AdvisoryPkg> & advisoryPkgs);
void filterUserInstalled(const Swdb &swdb);
diff --git a/python/hawkey/query-py.cpp b/python/hawkey/query-py.cpp
index a25a0d6b..b30cc22f 100644
--- a/python/hawkey/query-py.cpp
+++ b/python/hawkey/query-py.cpp
@@ -819,6 +819,52 @@ filter_unneeded(PyObject *self, PyObject *args, PyObject *kwds) try
return filter_unneeded_or_safe_to_remove(self, args, kwds, false);
} CATCH_TO_PYTHON
+static PyObject *
+filter_unneeded_extra_userinstalled(PyObject *self, PyObject *args, PyObject *kwds) try
+{
+ const char *kwlist[] = {"swdb", "extra_userinstalled", "debug_solver", NULL};
+ PyObject *pySwdb;
+ PyObject *extra_userinstalled;
+ PyObject *debug_solver = NULL;
+
+ if (!PyArg_ParseTupleAndKeywords(
+ args, kwds, "OO|O!", (char **)kwlist, &pySwdb, &extra_userinstalled, &PyBool_Type, &debug_solver)) {
+ return NULL;
+ }
+
+ UniquePtrPyObject thisPySwdb(PyObject_GetAttrString(pySwdb, "this"));
+ auto swigSwdb = reinterpret_cast< SwdbSwigPyObject * >(thisPySwdb.get());
+ if (swigSwdb == nullptr) {
+ PyErr_SetString(PyExc_SystemError, "Unable to parse SwigPyObject");
+ return NULL;
+ }
+ libdnf::Swdb *swdb = swigSwdb->ptr;
+ if (swdb == NULL) {
+ PyErr_SetString(PyExc_SystemError, "Unable to parse swig object");
+ return NULL;
+ }
+
+ HyQuery query = ((_QueryObject *) self)->query;
+ auto extra_userinstalled_pset = pyseq_to_packageset(extra_userinstalled, query->getSack());
+ if (!extra_userinstalled_pset) {
+ PyErr_SetString(PyExc_SystemError, "Unable to parse SwigPyObject: extra_userinstalled PackageSet");
+ return NULL;
+ }
+
+ std::unique_ptr<libdnf::Query> self_query_copy(new libdnf::Query(*query));
+ gboolean c_debug_solver = debug_solver != NULL && PyObject_IsTrue(debug_solver);
+
+ int ret = self_query_copy->filterUnneededExtraUserinstalled(*swdb, *extra_userinstalled_pset, c_debug_solver);
+ if (ret == -1) {
+ PyErr_SetString(PyExc_SystemError, "Unable to provide query with unneded filter");
+ return NULL;
+ }
+
+ PyObject *final_query = queryToPyObject(self_query_copy.release(), ((_QueryObject *) self)->sack,
+ Py_TYPE(self));
+ return final_query;
+} CATCH_TO_PYTHON
+
static PyObject *
q_add(_QueryObject *self, PyObject *list) try
{
@@ -1081,6 +1127,7 @@ static struct PyMethodDef query_methods[] = {
{"_nevra", (PyCFunction)add_nevra_or_other_filter, METH_VARARGS, NULL},
{"_recent", (PyCFunction)add_filter_recent, METH_VARARGS, NULL},
{"_unneeded", (PyCFunction)filter_unneeded, METH_KEYWORDS|METH_VARARGS, NULL},
+ {"_unneeded_extra_userinstalled", (PyCFunction)filter_unneeded_extra_userinstalled, METH_KEYWORDS|METH_VARARGS, NULL},
{"_safe_to_remove", (PyCFunction)filter_safe_to_remove, METH_KEYWORDS|METH_VARARGS, NULL},
{NULL} /* sentinel */
};
--
2.53.0

View File

@ -0,0 +1,31 @@
From 3da41b9d881fc5f0bb8c09b4d1ae4dde9626dd1e Mon Sep 17 00:00:00 2001
From: Evan Goode <mail@evangoo.de>
Date: Tue, 27 Jan 2026 13:00:50 -0500
Subject: [PATCH 4/5] Describe all problems even when there are protected
removals
Previously, if a transaction involved removal (or dependency break) of a
protected package, only the protected package problem would be described
by `describeProblemRules`. Information about excluded or versionlocked
packages would be missing.
For: RHEL-146507
---
libdnf/goal/Goal.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/libdnf/goal/Goal.cpp b/libdnf/goal/Goal.cpp
index f2b20ced..47d9888e 100644
--- a/libdnf/goal/Goal.cpp
+++ b/libdnf/goal/Goal.cpp
@@ -1108,7 +1108,6 @@ Goal::describeProblemRules(unsigned i, bool pkgs)
auto problem = pImpl->describeProtectedRemoval();
if (!problem.empty()) {
output.push_back(std::move(problem));
- return output;
}
auto solv = pImpl->solv;
--
2.53.0

View File

@ -0,0 +1,60 @@
From 35f16bc89b567460dd7857f632a38790839baca9 Mon Sep 17 00:00:00 2001
From: Evan Goode <mail@evangoo.de>
Date: Tue, 27 Jan 2026 13:19:14 -0500
Subject: [PATCH 5/5] Clearer error for protected package broken dependencies
The error message now distinguishes removal of a protected package from
breaking dependencies of protected packages.
---
libdnf/goal/Goal.cpp | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
diff --git a/libdnf/goal/Goal.cpp b/libdnf/goal/Goal.cpp
index 47d9888e..4544cd9e 100644
--- a/libdnf/goal/Goal.cpp
+++ b/libdnf/goal/Goal.cpp
@@ -1752,11 +1752,11 @@ Goal::Impl::protectedInRemovals()
std::string
Goal::Impl::describeProtectedRemoval()
{
- std::string message(_("The operation would result in removing"
- " the following protected packages: "));
Pool * pool = solv->pool;
if (removalOfProtected && removalOfProtected->size()) {
+ const std::string removal_message(_("The operation would result in removing "
+ "the following protected packages: "));
Id id = -1;
std::vector<const char *> names;
while((id = removalOfProtected->next(id)) != -1) {
@@ -1766,9 +1766,13 @@ Goal::Impl::describeProtectedRemoval()
if (names.empty()) {
return {};
}
- return message + std::accumulate(std::next(names.begin()), names.end(),
- std::string(names[0]), [](std::string a, std::string b) { return a + ", " + b; });
+ return removal_message +
+ std::accumulate(std::next(names.begin()), names.end(), std::string(names[0]),
+ [](std::string a, std::string b) { return a + ", " + b; });
}
+
+ const std::string broken_dependency_message(_("The operation would result in broken "
+ "dependencies for the following protected packages: "));
auto pset = brokenDependencyAllPkgs(DNF_PACKAGE_STATE_INSTALLED);
Id id = -1;
Id protected_kernel = protectedRunningKernel();
@@ -1781,8 +1785,9 @@ Goal::Impl::describeProtectedRemoval()
}
if (names.empty())
return {};
- return message + std::accumulate(std::next(names.begin()), names.end(), std::string(names[0]),
- [](std::string a, std::string b) { return a + ", " + b; });
+ return broken_dependency_message +
+ std::accumulate(std::next(names.begin()), names.end(), std::string(names[0]),
+ [](std::string a, std::string b) { return a + ", " + b; });
}
}
--
2.53.0

View File

@ -0,0 +1,57 @@
From 83d3c39df84e96860efd35c2e18903dd16d050c7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Tue, 10 Feb 2026 13:04:42 +0100
Subject: [PATCH] Goal: set protected as userinstalled only for the temporary
job
This way the goal's `staging` is not affected.
---
libdnf/goal/Goal.cpp | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/libdnf/goal/Goal.cpp b/libdnf/goal/Goal.cpp
index 4544cd9e..c624fb41 100644
--- a/libdnf/goal/Goal.cpp
+++ b/libdnf/goal/Goal.cpp
@@ -987,15 +987,6 @@ Goal::jobLength()
bool
Goal::run(DnfGoalActions flags)
{
- // Automatically mark all protected packages as user installed.
- // When a protected package is installed as a dependency it can block
- // removal of the last package that depends on it (because the protected
- // package cannot be removed, not even as an unused dependency).
- // To prevent this and still correctly resolve dependencies of the protected
- // packages mark them all as user installed.
- if (pImpl->protectedPkgs) {
- userInstalled(*pImpl->protectedPkgs);
- }
auto job = pImpl->constructJob(flags);
pImpl->actions = static_cast<DnfGoalActions>(pImpl->actions | flags);
int ret = pImpl->solve(job->getQueue(), flags);
@@ -1444,6 +1435,22 @@ Goal::Impl::constructJob(DnfGoalActions flags)
allowUninstallAllButProtected(job->getQueue(), flags);
+ // Automatically mark all protected packages as user installed.
+ // When a protected package is installed as a dependency it can block
+ // removal of the last package that depends on it (because the protected
+ // package cannot be removed, not even as an unused dependency).
+ // To prevent this and still correctly resolve dependencies of the protected
+ // packages mark them all as user installed.
+ if (protectedPkgs) {
+ Id id = -1;
+ while (true) {
+ id = protectedPkgs->next(id);
+ if (id == -1)
+ break;
+ queue_push2(job->getQueue(), SOLVER_SOLVABLE|SOLVER_USERINSTALLED, id);
+ }
+ }
+
if (flags & DNF_VERIFY)
job->pushBack(SOLVER_VERIFY|SOLVER_SOLVABLE_ALL, 0);
--
2.53.0

View File

@ -1,7 +1,7 @@
From d7ce52b5793e8c0be03bbdfac416e7c76bfbb03a Mon Sep 17 00:00:00 2001
From 72252383942769f8ad7858e3d5abe2cb64488371 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Fri, 13 Mar 2026 17:40:15 +0100
Subject: [PATCH 19/24] tests: Add tests for dnf_keyring_add_public_key()
Subject: [PATCH 25/30] tests: Add tests for dnf_keyring_add_public_key()
Upstream commit: dc3f0098e30a9154f530ea4fc31c500927a7ad01

View File

@ -1,7 +1,7 @@
From 7e50092e3000e428efc410fe19c926a482fa2156 Mon Sep 17 00:00:00 2001
From 49df864cde21f9d160bfd422058a3e33970222cc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Fri, 13 Mar 2026 17:40:15 +0100
Subject: [PATCH 20/24] Move importing a key from a memory block into a
Subject: [PATCH 26/30] Move importing a key from a memory block into a
separate function
Upstream commit: 89b6944551c08c17c5be12db17211201264350a1

View File

@ -1,7 +1,7 @@
From b078d8bb7d8c76f839a3be1d5fdbcb7ab76de8ea Mon Sep 17 00:00:00 2001
From 435b2a678af4f428d66044f7c5035c640abbc780 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Wed, 18 Mar 2026 13:36:18 +0100
Subject: [PATCH 21/24] Log identifiers of keys imported by
Subject: [PATCH 27/30] Log identifiers of keys imported by
dnf_keyring_add_public_key()
Upstream commit: e0c56202ebde444bb73065843ac3dc2f7e4a8f3a

View File

@ -1,7 +1,7 @@
From 3892eefb77e95a4dd9113a727503bb4ce29eac2c Mon Sep 17 00:00:00 2001
From 569f317bbf22e4ccc3a473cd3ee895a2891852f1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Wed, 18 Mar 2026 13:36:18 +0100
Subject: [PATCH 22/24] Fix dnf_keyring_add_public_key() to add all keys from
Subject: [PATCH 28/30] Fix dnf_keyring_add_public_key() to add all keys from
an ASCII-armored block
Upstream commit: 21e58e48d73a0edba62510bac8d49392c5166ebb

View File

@ -1,7 +1,7 @@
From 6e64245b6092d412b59a5571ce6fda588b132ebb Mon Sep 17 00:00:00 2001
From 3b3c8910837d51431e9cc79e131671f48ea5f04b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Wed, 18 Mar 2026 15:46:30 +0100
Subject: [PATCH 23/24] Fix dnf_keyring_add_public_key() to add keys from all
Subject: [PATCH 29/30] Fix dnf_keyring_add_public_key() to add keys from all
ASCII-armored blocks
Upstream commit: af94b4cc5b7f96829ab8cb9d7dc3fbc92fa56d92

View File

@ -1,7 +1,7 @@
From aa80ec474cd76f9a895c84d6d2c0429b89b65a8f Mon Sep 17 00:00:00 2001
From 60ab51a163451fe6da0173ae7a3a05d8689ff7ef Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Thu, 9 Apr 2026 16:26:20 +0200
Subject: [PATCH 24/24] Fix formatting error messages when importing subkeys
Subject: [PATCH 30/30] Fix formatting error messages when importing subkeys
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

View File

@ -56,7 +56,7 @@
Name: libdnf
Version: %{libdnf_major_version}.%{libdnf_minor_version}.%{libdnf_micro_version}
Release: 12%{?dist}.1
Release: 15%{?dist}
Summary: Library providing simplified C and Python API to libsolv
License: LGPL-2.1-or-later
URL: https://github.com/rpm-software-management/libdnf
@ -79,12 +79,18 @@ Patch15: 0015-module-Warn-if-module-config-file-is-inaccessible.patch
Patch16: 0016-history-DB-Add-persistence-column.patch
Patch17: 0017-MergedTransaction-listPersistences.patch
Patch18: 0018-conf-Add-usr_drift_protected_paths.patch
Patch19: 0019-tests-Add-tests-for-dnf_keyring_add_public_key.patch
Patch20: 0020-Move-importing-a-key-from-a-memory-block-into-a-sepa.patch
Patch21: 0021-Log-identifiers-of-keys-imported-by-dnf_keyring_add_.patch
Patch22: 0022-Fix-dnf_keyring_add_public_key-to-add-all-keys-from-.patch
Patch23: 0023-Fix-dnf_keyring_add_public_key-to-add-keys-from-all-.patch
Patch24: 0024-Fix-formatting-error-messages-when-importing-subkeys.patch
Patch19: 0019-fix-compare-RPMItem-in-transaction-with-rpmvercmp.patch
Patch20: 0020-Mark-all-protected-packages-as-user-installed-for-al.patch
Patch21: 0021-Add-filterUnneededExtraUserinstalled-and-Python-vers.patch
Patch22: 0022-Describe-all-problems-even-when-there-are-protected-.patch
Patch23: 0023-Clearer-error-for-protected-package-broken-dependenc.patch
Patch24: 0024-Goal-set-protected-as-userinstalled-only-for-the-tem.patch
Patch25: 0025-tests-Add-tests-for-dnf_keyring_add_public_key.patch
Patch26: 0026-Move-importing-a-key-from-a-memory-block-into-a-sepa.patch
Patch27: 0027-Log-identifiers-of-keys-imported-by-dnf_keyring_add_.patch
Patch28: 0028-Fix-dnf_keyring_add_public_key-to-add-all-keys-from-.patch
Patch29: 0029-Fix-dnf_keyring_add_public_key-to-add-keys-from-all-.patch
Patch30: 0030-Fix-formatting-error-messages-when-importing-subkeys.patch
BuildRequires: cmake
BuildRequires: gcc
@ -328,9 +334,18 @@ popd
%endif
%changelog
* Mon Apr 13 2026 Petr Pisar <ppisar@redhat.com> - 0.73.1-12.1
* Mon Apr 13 2026 Petr Pisar <ppisar@redhat.com> - 0.73.1-15
- Fix dnf_keyring_add_public_key() to add multiple keys from a single file
(RHEL-156041)
(RHEL-156063)
* Mon Feb 09 2026 Ales Matej <amatej@redhat.com> - 0.73.1-14
- Mark all protected packages as user installed for all transactions (RHEL-128445)
- Add `filterUnneededExtraUserinstalled` and Python version to the API
- Describe all problems even when there are protected removals (RHEL-146507)
- Clearer error for protected package broken dependencies
* Tue Feb 03 2026 Matej Focko <mfocko@redhat.com> - 0.73.1-13
- Fix comparison of RPM items in the transaction (RHEL-128443)
* Thu Jun 26 2025 Evan Goode <egoode@redhat.com> - 0.73.1-12
- Bump version due to failed build