import libdnf-0.48.0-5.el8

This commit is contained in:
CentOS Sources 2020-11-03 06:47:38 -05:00 committed by Andrew Lukoshko
parent 14e924f91d
commit 0211e1573c
15 changed files with 6604 additions and 60209 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/libdnf-0.39.1.tar.gz
SOURCES/libdnf-0.48.0.tar.gz

View File

@ -1 +1 @@
a74a37b029439749298705ff3c1ccfbd0f0fd821 SOURCES/libdnf-0.39.1.tar.gz
452c2195741b627bd97b0be11cd4a4dc4118e330 SOURCES/libdnf-0.48.0.tar.gz

View File

@ -0,0 +1,244 @@
From a96d701f7f55ff475e11ac9cda63b81c31c54e7a Mon Sep 17 00:00:00 2001
From: Daniel Mach <dmach@redhat.com>
Date: Wed, 6 May 2020 08:34:46 +0200
Subject: [PATCH] history: Fix dnf history rollback when a package was removed
(RhBug:1683134)
---
libdnf/transaction/MergedTransaction.cpp | 25 +++-
.../transaction/MergedTransactionTest.cpp | 120 ++++++++++++++++--
.../transaction/MergedTransactionTest.hpp | 6 +-
3 files changed, 137 insertions(+), 14 deletions(-)
diff --git a/libdnf/transaction/MergedTransaction.cpp b/libdnf/transaction/MergedTransaction.cpp
index a7c06ffa9..a8d878cb5 100644
--- a/libdnf/transaction/MergedTransaction.cpp
+++ b/libdnf/transaction/MergedTransaction.cpp
@@ -19,6 +19,7 @@
*/
#include "MergedTransaction.hpp"
+#include <algorithm>
#include <vector>
namespace libdnf {
@@ -171,6 +172,21 @@ MergedTransaction::getConsoleOutput()
return output;
}
+
+static bool transaction_item_sort_function(const std::shared_ptr<TransactionItemBase> lhs, const std::shared_ptr<TransactionItemBase> rhs) {
+ if (lhs->isForwardAction() && rhs->isForwardAction()) {
+ return false;
+ }
+ if (lhs->isBackwardAction() && rhs->isBackwardAction()) {
+ return false;
+ }
+ if (lhs->isBackwardAction()) {
+ return true;
+ }
+ return false;
+}
+
+
/**
* Get list of transaction items involved in the merged transaction
* Actions are merged using following rules:
@@ -203,6 +219,9 @@ MergedTransaction::getItems()
// iterate over transaction
for (auto t : transactions) {
auto transItems = t->getItems();
+ // sort transaction items by their action type - forward/backward
+ // this fixes behavior of the merging algorithm in several edge cases
+ std::sort(transItems.begin(), transItems.end(), transaction_item_sort_function);
// iterate over transaction items
for (auto transItem : transItems) {
// get item and its type
@@ -383,10 +402,6 @@ MergedTransaction::mergeItem(ItemPairMap &itemPairMap, TransactionItemBasePtr mT
auto firstState = previousItemPair.first->getAction();
auto newState = mTransItem->getAction();
- if (firstState == TransactionItemAction::INSTALL && mTransItem->isBackwardAction()) {
- return;
- }
-
switch (firstState) {
case TransactionItemAction::REMOVE:
case TransactionItemAction::OBSOLETED:
@@ -399,6 +414,8 @@ MergedTransaction::mergeItem(ItemPairMap &itemPairMap, TransactionItemBasePtr mT
// Install -> Remove = (nothing)
itemPairMap.erase(name);
break;
+ } else if (mTransItem->isBackwardAction()) {
+ break;
}
// altered -> transfer install to the altered package
mTransItem->setAction(TransactionItemAction::INSTALL);
diff --git a/tests/libdnf/transaction/MergedTransactionTest.cpp b/tests/libdnf/transaction/MergedTransactionTest.cpp
index 90ad182cf..52507700b 100644
--- a/tests/libdnf/transaction/MergedTransactionTest.cpp
+++ b/tests/libdnf/transaction/MergedTransactionTest.cpp
@@ -700,7 +700,7 @@ MergedTransactionTest::test_downgrade()
}
void
-MergedTransactionTest::test_install_downgrade()
+MergedTransactionTest::test_install_downgrade_upgrade_remove()
{
auto trans1 = std::make_shared< libdnf::swdb_private::Transaction >(conn);
trans1->addItem(
@@ -724,19 +724,123 @@ MergedTransactionTest::test_install_downgrade()
TransactionItemReason::USER
);
+ auto trans3 = std::make_shared< libdnf::swdb_private::Transaction >(conn);
+ trans3->addItem(
+ nevraToRPMItem(conn, "tour-0:4.6-1.noarch"),
+ "repo2",
+ TransactionItemAction::UPGRADED,
+ TransactionItemReason::USER
+ );
+ trans3->addItem(
+ nevraToRPMItem(conn, "tour-0:4.8-1.noarch"),
+ "repo1",
+ TransactionItemAction::UPGRADE,
+ TransactionItemReason::USER
+ );
+
+ auto trans4 = std::make_shared< libdnf::swdb_private::Transaction >(conn);
+ trans4->addItem(
+ nevraToRPMItem(conn, "tour-0:4.8-1.noarch"),
+ "repo1",
+ TransactionItemAction::REMOVE,
+ TransactionItemReason::USER
+ );
+
MergedTransaction merged(trans1);
+
+ // test merging trans1, trans2
merged.merge(trans2);
+ auto items2 = merged.getItems();
+ CPPUNIT_ASSERT_EQUAL(1, (int)items2.size());
+ auto item2 = items2.at(0);
+ CPPUNIT_ASSERT_EQUAL(std::string("tour-4.6-1.noarch"), item2->getItem()->toStr());
+ CPPUNIT_ASSERT_EQUAL(std::string("repo2"), item2->getRepoid());
+ CPPUNIT_ASSERT_EQUAL(TransactionItemAction::INSTALL, item2->getAction());
+ CPPUNIT_ASSERT_EQUAL(TransactionItemReason::USER, item2->getReason());
- auto items = merged.getItems();
- CPPUNIT_ASSERT_EQUAL(1, (int)items.size());
+ // test merging trans1, trans2, trans3
+ merged.merge(trans3);
+ auto items3 = merged.getItems();
+ CPPUNIT_ASSERT_EQUAL(1, (int)items3.size());
+ auto item3 = items3.at(0);
+ CPPUNIT_ASSERT_EQUAL(std::string("tour-4.8-1.noarch"), item3->getItem()->toStr());
+ CPPUNIT_ASSERT_EQUAL(std::string("repo1"), item3->getRepoid());
+ CPPUNIT_ASSERT_EQUAL(TransactionItemAction::INSTALL, item3->getAction());
+ CPPUNIT_ASSERT_EQUAL(TransactionItemReason::USER, item3->getReason());
- auto item = items.at(0);
- CPPUNIT_ASSERT_EQUAL(std::string("tour-4.6-1.noarch"), item->getItem()->toStr());
- CPPUNIT_ASSERT_EQUAL(std::string("repo2"), item->getRepoid());
- CPPUNIT_ASSERT_EQUAL(TransactionItemAction::INSTALL, item->getAction());
- CPPUNIT_ASSERT_EQUAL(TransactionItemReason::USER, item->getReason());
+ // test merging trans1, trans2, trans3, trans4
+ merged.merge(trans4);
+ auto items4 = merged.getItems();
+ CPPUNIT_ASSERT_EQUAL(0, (int)items4.size());
+ // trans4 removes the package, empty output is expected
}
+
+void
+MergedTransactionTest::test_downgrade_upgrade_remove()
+{
+ auto trans1 = std::make_shared< libdnf::swdb_private::Transaction >(conn);
+ trans1->addItem(
+ nevraToRPMItem(conn, "tour-0:4.6-1.noarch"),
+ "repo2",
+ TransactionItemAction::DOWNGRADE,
+ TransactionItemReason::USER
+ );
+ trans1->addItem(
+ nevraToRPMItem(conn, "tour-0:4.8-1.noarch"),
+ "repo1",
+ TransactionItemAction::DOWNGRADED,
+ TransactionItemReason::USER
+ );
+
+ // items are in reversed order than in test_install_downgrade_upgrade_remove()
+ // fixing this required ordering transaction items by forward/backward action
+ auto trans2 = std::make_shared< libdnf::swdb_private::Transaction >(conn);
+ trans2->addItem(
+ nevraToRPMItem(conn, "tour-0:4.8-1.noarch"),
+ "repo1",
+ TransactionItemAction::UPGRADE,
+ TransactionItemReason::USER
+ );
+ trans2->addItem(
+ nevraToRPMItem(conn, "tour-0:4.6-1.noarch"),
+ "repo2",
+ TransactionItemAction::UPGRADED,
+ TransactionItemReason::USER
+ );
+
+ auto trans3 = std::make_shared< libdnf::swdb_private::Transaction >(conn);
+ trans3->addItem(
+ nevraToRPMItem(conn, "tour-0:4.8-1.noarch"),
+ "repo1",
+ TransactionItemAction::REMOVE,
+ TransactionItemReason::USER
+ );
+
+ MergedTransaction merged(trans1);
+
+ // test merging trans1, trans2
+ merged.merge(trans2);
+ auto items2 = merged.getItems();
+ CPPUNIT_ASSERT_EQUAL(1, (int)items2.size());
+ auto item2 = items2.at(0);
+ CPPUNIT_ASSERT_EQUAL(std::string("tour-4.8-1.noarch"), item2->getItem()->toStr());
+ CPPUNIT_ASSERT_EQUAL(std::string("repo1"), item2->getRepoid());
+ CPPUNIT_ASSERT_EQUAL(TransactionItemAction::REINSTALL, item2->getAction());
+ CPPUNIT_ASSERT_EQUAL(TransactionItemReason::USER, item2->getReason());
+
+ // test merging trans1, trans2, trans3
+ merged.merge(trans3);
+ auto items3 = merged.getItems();
+ CPPUNIT_ASSERT_EQUAL(1, (int)items3.size());
+ auto item3 = items3.at(0);
+ CPPUNIT_ASSERT_EQUAL(std::string("tour-4.8-1.noarch"), item3->getItem()->toStr());
+ CPPUNIT_ASSERT_EQUAL(std::string("repo1"), item3->getRepoid());
+ CPPUNIT_ASSERT_EQUAL(TransactionItemAction::REMOVE, item3->getAction());
+ CPPUNIT_ASSERT_EQUAL(TransactionItemReason::USER, item3->getReason());
+}
+
+
void
MergedTransactionTest::test_multilib_identity()
{
diff --git a/tests/libdnf/transaction/MergedTransactionTest.hpp b/tests/libdnf/transaction/MergedTransactionTest.hpp
index 9f1ed660a..77585e865 100644
--- a/tests/libdnf/transaction/MergedTransactionTest.hpp
+++ b/tests/libdnf/transaction/MergedTransactionTest.hpp
@@ -26,7 +26,8 @@ class MergedTransactionTest : public CppUnit::TestCase {
CPPUNIT_TEST(test_add_obsoleted_obsoleted);
CPPUNIT_TEST(test_downgrade);
- CPPUNIT_TEST(test_install_downgrade);
+ CPPUNIT_TEST(test_install_downgrade_upgrade_remove);
+ CPPUNIT_TEST(test_downgrade_upgrade_remove);
CPPUNIT_TEST(test_multilib_identity);
@@ -56,7 +57,8 @@ class MergedTransactionTest : public CppUnit::TestCase {
// END: tests ported from DNF unit tests
void test_downgrade();
- void test_install_downgrade();
+ void test_install_downgrade_upgrade_remove();
+ void test_downgrade_upgrade_remove();
void test_multilib_identity();
private:

View File

@ -1,131 +0,0 @@
From 1dffef87fc2f07763f64eeabc1ea891e68d23541 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Tue, 26 Nov 2019 13:05:49 +0100
Subject: [PATCH] [user-agent] Drop the whitelist
- Stop checking os-release(5) data against a hard-coded whitelist and
just use them as they are, to avoid a maintenance burden in the
future (see [1] for details)
- Clean up the getUserAgent() function a bit
Note that, by removing the whitelist, there's a risk of leaking a
"unique" value from the os-release file now, but a rather small one.
[1] https://github.com/rpm-software-management/libdnf/pull/851
---
libdnf/utils/os-release.cpp | 58 ++++++++++++++++++++--------------------------------------
libdnf/utils/os-release.hpp | 7 ++-----
2 files changed, 22 insertions(+), 43 deletions(-)
diff --git a/libdnf/utils/os-release.cpp b/libdnf/utils/os-release.cpp
index 57be110..1d8a95b 100644
--- a/libdnf/utils/os-release.cpp
+++ b/libdnf/utils/os-release.cpp
@@ -36,17 +36,8 @@
namespace libdnf {
// sorted by precedence (see os-release(5) for details)
-static const std::array<const std::string, 2> paths = {"/etc/os-release", "/usr/lib/os-release"};
-// whitelists used for sanity-checking the os-release data when constructing a
-// User-Agent string (to avoid reporting rare systems or platforms that could
-// be tracked)
-static const std::map<std::string, std::vector<std::string>> distros = {
- // taken from the {fedora,generic}-release.spec files
- { "Fedora", { "cinnamon", "cloud", "container", "coreos", "generic", "iot",
- "kde", "matecompiz", "server", "silverblue", "snappy", "soas",
- "workstation", "xfce" } },
-};
-std::array<const std::string, 1> canons = { "Linux" };
+static const std::array<const std::string, 2>
+paths = {"/etc/os-release", "/usr/lib/os-release"};
std::map<std::string, std::string> getOsReleaseData()
{
@@ -118,47 +109,38 @@ std::string getUserAgent(const std::map<std::string, std::string> & osReleaseDat
{
std::ostringstream oss;
auto logger(Log::getLogger());
- std::string msg = "os-release: falling back to basic User-Agent";
- // start with the basic libdnf string
oss << USER_AGENT;
+ std::string fallback = oss.str();
- // mandatory OS data (bail out if missing or unknown)
if (!osReleaseData.count("NAME") || !osReleaseData.count("VERSION_ID")) {
- logger->debug(tfm::format("%s: missing NAME or VERSION_ID", msg));
- return oss.str();
+ logger->debug(tfm::format(
+ "User-Agent: falling back to '%s': missing NAME or VERSION_ID",
+ fallback
+ ));
+ return fallback;
}
std::string name = osReleaseData.at("NAME");
std::string version = osReleaseData.at("VERSION_ID");
- if (!distros.count(name)) {
- logger->debug(tfm::format("%s: distro %s not whitelisted", msg, name));
- return oss.str();
- }
+ std::string variant = "generic";
+ if (osReleaseData.count("VARIANT_ID"))
+ variant = osReleaseData.at("VARIANT_ID");
- // mandatory platform data from RPM (bail out if missing or unknown)
std::string canon = getCanonOs();
std::string arch = getBaseArch();
- if (canon.empty() || arch.empty()
- || std::find(canons.begin(), canons.end(), canon) == canons.end()) {
- logger->debug(tfm::format("%s: could not detect canonical OS or basearch", msg));
- return oss.str();
- }
-
- // optional OS data (use fallback values if missing or unknown)
- std::string variant = "generic";
- auto list = distros.at(name);
- if (osReleaseData.count("VARIANT_ID")) {
- std::string value = osReleaseData.at("VARIANT_ID");
- if (std::find(list.begin(), list.end(), value) != list.end())
- variant = value;
+ if (canon.empty() || arch.empty()) {
+ logger->debug(tfm::format(
+ "User-Agent: falling back to '%s': could not detect OS or basearch",
+ fallback
+ ));
+ return fallback;
}
- // good to go!
- oss << " (" << name << " " << version << "; " << variant << "; "
- << canon << "." << arch << ")";
+ oss << " (" << name << " " << version << "; " << variant << "; " << canon
+ << "." << arch << ")";
std::string result = oss.str();
- logger->debug(tfm::format("os-release: User-Agent constructed: %s", result));
+ logger->debug(tfm::format("User-Agent: constructed: '%s'", result));
return result;
}
diff --git a/libdnf/utils/os-release.hpp b/libdnf/utils/os-release.hpp
index ef4d14f..e7b24a7 100644
--- a/libdnf/utils/os-release.hpp
+++ b/libdnf/utils/os-release.hpp
@@ -50,11 +50,8 @@ getOsReleaseData();
* libdnf (NAME VERSION_ID; VARIANT_ID; OS.BASEARCH)
*
* where NAME, VERSION_ID and VARIANT_ID are OS identifiers read from the
- * passed os-release data, and OS and BASEARCH (if found) are the canonical OS
- * name and base architecture, respectively, detected using RPM.
- *
- * Note that the OS part (enclosed in parentheses) will only be included for
- * whitelisted values.
+ * passed os-release data, and OS and BASEARCH are the canonical OS name and
+ * base architecture, respectively, detected using RPM.
*
* @param osReleaseData a map containing os-release data (will be loaded from
* disk if not specified)
--
libgit2 0.28.2

View File

@ -0,0 +1,51 @@
From 69e7baa4f6484c39ce25869d0c6252393b7c0411 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Thu, 4 Jun 2020 11:13:48 +0200
Subject: [PATCH] Add log file level main config option (RhBug:1802074)
https://bugzilla.redhat.com/show_bug.cgi?id=1802074
---
libdnf/conf/ConfigMain.cpp | 3 +++
libdnf/conf/ConfigMain.hpp | 1 +
4 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/libdnf/conf/ConfigMain.cpp b/libdnf/conf/ConfigMain.cpp
index 305b8e233..06352b7f3 100644
--- a/libdnf/conf/ConfigMain.cpp
+++ b/libdnf/conf/ConfigMain.cpp
@@ -169,6 +169,7 @@ class ConfigMain::Impl {
OptionNumber<std::int32_t> debuglevel{2, 0, 10};
OptionNumber<std::int32_t> errorlevel{3, 0, 10};
+ OptionNumber<std::int32_t> logfilelevel{9, 0, 10};
OptionPath installroot{"/", false, true};
OptionPath config_file_path{CONF_FILENAME};
OptionBool plugins{true};
@@ -350,6 +351,7 @@ ConfigMain::Impl::Impl(Config & owner)
{
owner.optBinds().add("debuglevel", debuglevel);
owner.optBinds().add("errorlevel", errorlevel);
+ owner.optBinds().add("logfilelevel", logfilelevel);
owner.optBinds().add("installroot", installroot);
owner.optBinds().add("config_file_path", config_file_path);
owner.optBinds().add("plugins", plugins);
@@ -491,6 +493,7 @@ ConfigMain::~ConfigMain() = default;
OptionNumber<std::int32_t> & ConfigMain::debuglevel() { return pImpl->debuglevel; }
OptionNumber<std::int32_t> & ConfigMain::errorlevel() { return pImpl->errorlevel; }
+OptionNumber<std::int32_t> & ConfigMain::logfilelevel() { return pImpl->logfilelevel; }
OptionString & ConfigMain::installroot() { return pImpl->installroot; }
OptionString & ConfigMain::config_file_path() { return pImpl->config_file_path; }
OptionBool & ConfigMain::plugins() { return pImpl->plugins; }
diff --git a/libdnf/conf/ConfigMain.hpp b/libdnf/conf/ConfigMain.hpp
index 118ecbf1c..706471029 100644
--- a/libdnf/conf/ConfigMain.hpp
+++ b/libdnf/conf/ConfigMain.hpp
@@ -49,6 +49,7 @@ class ConfigMain : public Config {
OptionNumber<std::int32_t> & debuglevel();
OptionNumber<std::int32_t> & errorlevel();
+ OptionNumber<std::int32_t> & logfilelevel();
OptionString & installroot();
OptionString & config_file_path();
OptionBool & plugins();

View File

@ -1,88 +0,0 @@
From c398ea4431ea539b0847fdf7fddf1892655081de Mon Sep 17 00:00:00 2001
From: Jaroslav Rohel <jrohel@redhat.com>
Date: Sun, 15 Dec 2019 16:43:01 +0100
Subject: [PATCH] [context] wildcard support in dnf_context_repo_set_data
(RhBug:1781420)
Adds support for wildcard pattern in repo_id to these functions:
gboolean dnf_context_repo_enable(DnfContext *context,
const gchar *repo_id, GError **error);
gboolean dnf_context_repo_disable(DnfContext *context,
const gchar *repo_id, GError **error);
For example, it is used by microdnf for enable and disable repositories
(arguments "--enablerepo=" and "--disablerepo=").
---
libdnf/dnf-context.cpp | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/libdnf/dnf-context.cpp b/libdnf/dnf-context.cpp
index 061bf6f85..4b0a009fc 100644
--- a/libdnf/dnf-context.cpp
+++ b/libdnf/dnf-context.cpp
@@ -52,6 +52,7 @@
#include <fcntl.h>
#include <unistd.h>
#endif
+#include <fnmatch.h>
#include <unistd.h>
#include "log.hpp"
@@ -2273,20 +2274,19 @@ dnf_context_repo_set_data(DnfContext *context,
GError **error)
{
DnfContextPrivate *priv = GET_PRIVATE(context);
- DnfRepo *repo = NULL;
- guint i;
+ bool found = false;
- /* find a repo with a matching ID */
- for (i = 0; i < priv->repos->len; i++) {
- auto repo_tmp = static_cast<DnfRepo *>(g_ptr_array_index(priv->repos, i));
- if (g_strcmp0(dnf_repo_get_id(repo_tmp), repo_id) == 0) {
- repo = repo_tmp;
- break;
+ /* set repos with a matching ID */
+ for (guint i = 0; i < priv->repos->len; ++i) {
+ auto repo = static_cast<DnfRepo *>(g_ptr_array_index(priv->repos, i));
+ if (fnmatch(repo_id, dnf_repo_get_id(repo), 0) == 0) {
+ dnf_repo_set_enabled(repo, enabled);
+ found = true;
}
}
/* nothing found */
- if (repo == NULL) {
+ if (!found) {
g_set_error(error,
DNF_ERROR,
DNF_ERROR_INTERNAL_ERROR,
@@ -2294,8 +2294,6 @@ dnf_context_repo_set_data(DnfContext *context,
return FALSE;
}
- /* this is runtime only */
- dnf_repo_set_enabled(repo, enabled);
return TRUE;
}
@@ -2305,7 +2303,8 @@ dnf_context_repo_set_data(DnfContext *context,
* @repo_id: A repo_id, e.g. "fedora-rawhide"
* @error: A #GError or %NULL
*
- * Enables a specific repo.
+ * Enables a specific repo(s).
+ * Wildcard pattern is supported.
*
* This must be done before dnf_context_setup() is called.
*
@@ -2329,7 +2328,8 @@ dnf_context_repo_enable(DnfContext *context,
* @repo_id: A repo_id, e.g. "fedora-rawhide"
* @error: A #GError or %NULL
*
- * Disables a specific repo.
+ * Disables a specific repo(s).
+ * Wildcard pattern is supported.
*
* This must be done before dnf_context_setup() is called.
*

View File

@ -0,0 +1,83 @@
From 227cf617dd6afd7583f1c864c66ba2ca95e3d09d Mon Sep 17 00:00:00 2001
From: Pavla Kratochvilova <pkratoch@redhat.com>
Date: Wed, 24 Jun 2020 08:48:49 +0200
Subject: [PATCH 1/2] Accept '==' as an operator in reldeps (RhBug:1847946)
Although rpm doesn't support this and using '==' can result in an
unexpected behavior, libdnf accepted '==' by mistake for some time and
other tools (namely Ansible Tower) already rely on it.
This brings back the '==' support with a deprecation warning.
https://bugzilla.redhat.com/show_bug.cgi?id=1847946
---
libdnf/repo/DependencySplitter.cpp | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/libdnf/repo/DependencySplitter.cpp b/libdnf/repo/DependencySplitter.cpp
index 0030ea6d3..402962286 100644
--- a/libdnf/repo/DependencySplitter.cpp
+++ b/libdnf/repo/DependencySplitter.cpp
@@ -20,16 +20,21 @@
#include "DependencySplitter.hpp"
#include "../dnf-sack.h"
+#include "../log.hpp"
#include "../utils/regex/regex.hpp"
+#include "bgettext/bgettext-lib.h"
+#include "tinyformat/tinyformat.hpp"
+
namespace libdnf {
static const Regex RELDEP_REGEX =
- Regex("^(\\S*)\\s*(<=|>=|<|>|=)?\\s*(\\S*)$", REG_EXTENDED);
+ Regex("^(\\S*)\\s*(<=|>=|<|>|=|==)?\\s*(\\S*)$", REG_EXTENDED);
static bool
getCmpFlags(int *cmp_type, std::string matchCmpType)
{
+ auto logger(Log::getLogger());
int subexpr_len = matchCmpType.size();
auto match_start = matchCmpType.c_str();
if (subexpr_len == 2) {
@@ -41,6 +46,13 @@ getCmpFlags(int *cmp_type, std::string matchCmpType)
*cmp_type |= HY_GT;
*cmp_type |= HY_EQ;
}
+ else if (strncmp(match_start, "==", 2) == 0) {
+ auto msg = tfm::format(_("Using '==' operator in reldeps can result in an undefined "
+ "behavior. It is deprecated and the support will be dropped "
+ "in future versions. Use '=' operator instead."));
+ logger->warning(msg);
+ *cmp_type |= HY_EQ;
+ }
else
return false;
} else if (subexpr_len == 1) {
From 1f9b14f1d30113a602e18f60ef7ba1f11aead10f Mon Sep 17 00:00:00 2001
From: Pavla Kratochvilova <pkratoch@redhat.com>
Date: Wed, 24 Jun 2020 13:08:48 +0200
Subject: [PATCH 2/2] Add tests for '==' operator in reldeps
---
python/hawkey/tests/tests/test_reldep.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/python/hawkey/tests/tests/test_reldep.py b/python/hawkey/tests/tests/test_reldep.py
index 8b479cfd7..a9f6cae6f 100644
--- a/python/hawkey/tests/tests/test_reldep.py
+++ b/python/hawkey/tests/tests/test_reldep.py
@@ -61,6 +61,11 @@ def test_custom_querying(self):
reldep = hawkey.Reldep(self.sack, "P-lib = 3-3")
q = hawkey.Query(self.sack).filter(provides=reldep)
self.assertLength(q, 1)
+ # '==' operator is deprecated and the support will be dropped in future
+ # versions (see bug 1847946)
+ reldep = hawkey.Reldep(self.sack, "P-lib == 3-3")
+ q = hawkey.Query(self.sack).filter(provides=reldep)
+ self.assertLength(q, 1)
reldep = hawkey.Reldep(self.sack, "P-lib >= 3")
q = hawkey.Query(self.sack).filter(provides=reldep)
self.assertLength(q, 1)

View File

@ -1,339 +0,0 @@
From b36464f01ffadab9ca49eed1a06ab480626b28c2 Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Mon, 16 Dec 2019 10:10:51 +0100
Subject: [PATCH 1/2] Add new query filter upgrades_by_priority
It returns upgrades only from repository with the lowest priority.
---
libdnf/hy-types.h | 3 +-
libdnf/sack/query.cpp | 60 ++++++++++++++++++++++++++++++++++
python/hawkey/hawkeymodule.cpp | 1 +
python/hawkey/query-py.cpp | 5 ++-
4 files changed, 67 insertions(+), 2 deletions(-)
diff --git a/libdnf/hy-types.h b/libdnf/hy-types.h
index b34988d89..380a0d5cc 100644
--- a/libdnf/hy-types.h
+++ b/libdnf/hy-types.h
@@ -97,7 +97,8 @@ enum _hy_key_name_e {
* @brief Use for strings of whole NEVRA (missing epoch is handled as epoch 0)
* Allowed compare types - only HY_EQ or HY_NEQ
*/
- HY_PKG_NEVRA_STRICT = 36
+ HY_PKG_NEVRA_STRICT = 36,
+ HY_PKG_UPGRADES_BY_PRIORITY = 37,
};
enum _hy_comparison_type_e {
diff --git a/libdnf/sack/query.cpp b/libdnf/sack/query.cpp
index eea0ce1b1..ecfd3110f 100644
--- a/libdnf/sack/query.cpp
+++ b/libdnf/sack/query.cpp
@@ -148,6 +148,13 @@ NameArchSolvableComparator(const Solvable * first, const Solvable * second)
return first->arch < second->arch;
}
+static bool
+NamePrioritySolvableKey(const Solvable * first, const Solvable * second)
+{
+ if (first->name != second->name)
+ return first->name < second->name;
+ return first->repo->priority > second->repo->priority;
+}
static bool
match_type_num(int keyname) {
@@ -158,6 +165,7 @@ match_type_num(int keyname) {
case HY_PKG_LATEST_PER_ARCH:
case HY_PKG_UPGRADABLE:
case HY_PKG_UPGRADES:
+ case HY_PKG_UPGRADES_BY_PRIORITY:
case HY_PKG_DOWNGRADABLE:
case HY_PKG_DOWNGRADES:
return true;
@@ -690,6 +698,7 @@ class Query::Impl {
void filterAdvisory(const Filter & f, Map *m, int keyname);
void filterLatest(const Filter & f, Map *m);
void filterUpdown(const Filter & f, Map *m);
+ 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);
@@ -1732,6 +1741,54 @@ Query::Impl::filterUpdown(const Filter & f, Map *m)
}
}
+void
+Query::Impl::filterUpdownByPriority(const Filter & f, Map *m)
+{
+ Pool *pool = dnf_sack_get_pool(sack);
+ auto resultPset = result.get();
+
+ dnf_sack_make_provides_ready(sack);
+ auto repoInstalled = pool->installed;
+ if (!repoInstalled) {
+ return;
+ }
+
+ for (auto match_in : f.getMatches()) {
+ if (match_in.num == 0)
+ continue;
+ std::vector<Solvable *> upgradeCandidates;
+ upgradeCandidates.reserve(resultPset->size());
+ Id id = -1;
+ while ((id = resultPset->next(id)) != -1) {
+ Solvable *candidate = pool_id2solvable(pool, id);
+ if (candidate->repo == repoInstalled)
+ continue;
+ upgradeCandidates.push_back(candidate);
+ }
+ if (upgradeCandidates.empty()) {
+ continue;
+ }
+ std::sort(upgradeCandidates.begin(), upgradeCandidates.end(), NamePrioritySolvableKey);
+ Id name = 0;
+ int priority = 0;
+ for (auto * candidate: upgradeCandidates) {
+ if (name != candidate->name) {
+ name = candidate->name;
+ priority = candidate->repo->priority;
+ id = pool_solvable2id(pool, candidate);
+ if (what_upgrades(pool, id) > 0) {
+ MAPSET(m, id);
+ }
+ } else if (priority == candidate->repo->priority) {
+ id = pool_solvable2id(pool, candidate);
+ if (what_upgrades(pool, id) > 0) {
+ MAPSET(m, id);
+ }
+ }
+ }
+ }
+}
+
void
Query::Impl::filterUpdownAble(const Filter &f, Map *m)
{
@@ -1949,6 +2006,9 @@ Query::Impl::apply()
case HY_PKG_UPGRADES:
filterUpdown(f, &m);
break;
+ case HY_PKG_UPGRADES_BY_PRIORITY:
+ filterUpdownByPriority(f, &m);
+ break;
default:
filterDataiterator(f, &m);
}
diff --git a/python/hawkey/hawkeymodule.cpp b/python/hawkey/hawkeymodule.cpp
index 0f05f46c2..4351e96e1 100644
--- a/python/hawkey/hawkeymodule.cpp
+++ b/python/hawkey/hawkeymodule.cpp
@@ -281,6 +281,7 @@ PYCOMP_MOD_INIT(_hawkey)
PyModule_AddIntConstant(m, "PKG_SUPPLEMENTS", HY_PKG_SUPPLEMENTS);
PyModule_AddIntConstant(m, "PKG_UPGRADABLE", HY_PKG_UPGRADABLE);
PyModule_AddIntConstant(m, "PKG_UPGRADES", HY_PKG_UPGRADES);
+ PyModule_AddIntConstant(m, "PKG_UPGRADES_BY_PRIORITY", HY_PKG_UPGRADES_BY_PRIORITY);
PyModule_AddIntConstant(m, "PKG_URL", HY_PKG_URL);
PyModule_AddIntConstant(m, "PKG_VERSION", HY_PKG_VERSION);
diff --git a/python/hawkey/query-py.cpp b/python/hawkey/query-py.cpp
index 116ffa1b0..286e306d3 100644
--- a/python/hawkey/query-py.cpp
+++ b/python/hawkey/query-py.cpp
@@ -89,6 +89,7 @@ static const int keyname_int_matches[] = {
HY_PKG_SUPPLEMENTS,
HY_PKG_UPGRADABLE,
HY_PKG_UPGRADES,
+ HY_PKG_UPGRADES_BY_PRIORITY,
HY_PKG_URL,
HY_PKG_VERSION
};
@@ -128,6 +129,7 @@ static const char * const keyname_char_matches[] = {
"supplements",
"upgradable",
"upgrades",
+ "upgrades_by_priority",
"url",
"version",
NULL
@@ -273,7 +275,8 @@ filter_add(HyQuery query, key_t keyname, int cmp_type, PyObject *match)
keyname == HY_PKG_LATEST_PER_ARCH ||
keyname == HY_PKG_LATEST ||
keyname == HY_PKG_UPGRADABLE ||
- keyname == HY_PKG_UPGRADES) {
+ keyname == HY_PKG_UPGRADES ||
+ keyname == HY_PKG_UPGRADES_BY_PRIORITY) {
int val;
if (!PyInt_Check(match) || cmp_type != HY_EQ) {
From 4b83ae692f90d0d3cbc377c7f93bdb7e99e477ef Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Mon, 16 Dec 2019 18:34:37 +0100
Subject: [PATCH 2/2] Add new query filter obsoletes_by_priority
---
libdnf/hy-types.h | 1 +
libdnf/sack/query.cpp | 65 ++++++++++++++++++++++++++++++++++
python/hawkey/hawkeymodule.cpp | 1 +
python/hawkey/query-py.cpp | 5 ++-
4 files changed, 71 insertions(+), 1 deletion(-)
diff --git a/libdnf/hy-types.h b/libdnf/hy-types.h
index 380a0d5cc..e96459c25 100644
--- a/libdnf/hy-types.h
+++ b/libdnf/hy-types.h
@@ -99,6 +99,7 @@ enum _hy_key_name_e {
*/
HY_PKG_NEVRA_STRICT = 36,
HY_PKG_UPGRADES_BY_PRIORITY = 37,
+ HY_PKG_OBSOLETES_BY_PRIORITY = 38,
};
enum _hy_comparison_type_e {
diff --git a/libdnf/sack/query.cpp b/libdnf/sack/query.cpp
index ecfd3110f..6e9e4715f 100644
--- a/libdnf/sack/query.cpp
+++ b/libdnf/sack/query.cpp
@@ -179,6 +179,7 @@ match_type_pkg(int keyname) {
switch (keyname) {
case HY_PKG:
case HY_PKG_OBSOLETES:
+ case HY_PKG_OBSOLETES_BY_PRIORITY:
return true;
default:
return false;
@@ -692,6 +693,7 @@ class Query::Impl {
void filterArch(const Filter & f, Map *m);
void filterSourcerpm(const Filter & f, Map *m);
void filterObsoletes(const Filter & f, Map *m);
+ void filterObsoletesByPriority(const Filter & f, Map *m);
void filterProvidesReldep(const Filter & f, Map *m);
void filterReponame(const Filter & f, Map *m);
void filterLocation(const Filter & f, Map *m);
@@ -702,6 +704,7 @@ class Query::Impl {
void filterUpdownAble(const Filter &f, Map *m);
void filterDataiterator(const Filter & f, Map *m);
int filterUnneededOrSafeToRemove(const Swdb &swdb, bool debug_solver, bool safeToRemove);
+ void obsoletesByPriority(Pool * pool, Solvable * candidate, Map * m, const Map * target, int obsprovides);
bool isGlob(const std::vector<const char *> &matches) const;
};
@@ -1469,6 +1472,65 @@ Query::Impl::filterObsoletes(const Filter & f, Map *m)
}
}
+void
+Query::Impl::obsoletesByPriority(Pool * pool, Solvable * candidate, Map * m, const Map * target, int obsprovides)
+{
+ if (!candidate->repo)
+ return;
+ for (Id *r_id = candidate->repo->idarraydata + candidate->obsoletes; *r_id; ++r_id) {
+ Id r, rr;
+ FOR_PROVIDES(r, rr, *r_id) {
+ if (!MAPTST(target, r))
+ continue;
+ assert(r != SYSTEMSOLVABLE);
+ Solvable *so = pool_id2solvable(pool, r);
+ if (!obsprovides && !pool_match_nevr(pool, so, *r_id))
+ continue; /* only matching pkg names */
+ MAPSET(m, pool_solvable2id(pool, candidate));
+ break;
+ }
+ }
+}
+
+void
+Query::Impl::filterObsoletesByPriority(const Filter & f, Map *m)
+{
+ Pool *pool = dnf_sack_get_pool(sack);
+ int obsprovides = pool_get_flag(pool, POOL_FLAG_OBSOLETEUSESPROVIDES);
+ Map *target;
+ auto resultPset = result.get();
+
+ assert(f.getMatchType() == _HY_PKG);
+ assert(f.getMatches().size() == 1);
+ target = dnf_packageset_get_map(f.getMatches()[0].pset);
+ dnf_sack_make_provides_ready(sack);
+ std::vector<Solvable *> obsoleteCandidates;
+ obsoleteCandidates.reserve(resultPset->size());
+ Id id = -1;
+ while ((id = resultPset->next(id)) != -1) {
+ Solvable *candidate = pool_id2solvable(pool, id);
+ obsoleteCandidates.push_back(candidate);
+ }
+ if (obsoleteCandidates.empty()) {
+ return;
+ }
+ std::sort(obsoleteCandidates.begin(), obsoleteCandidates.end(), NamePrioritySolvableKey);
+ Id name = 0;
+ int priority = 0;
+ for (auto * candidate: obsoleteCandidates) {
+ if (candidate->repo == pool->installed) {
+ obsoletesByPriority(pool, candidate, m, target, obsprovides);
+ }
+ if (name != candidate->name) {
+ name = candidate->name;
+ priority = candidate->repo->priority;
+ obsoletesByPriority(pool, candidate, m, target, obsprovides);
+ } else if (priority == candidate->repo->priority) {
+ obsoletesByPriority(pool, candidate, m, target, obsprovides);
+ }
+ }
+}
+
void
Query::Impl::filterProvidesReldep(const Filter & f, Map *m)
{
@@ -1969,6 +2031,9 @@ Query::Impl::apply()
filterObsoletes(f, &m);
}
break;
+ case HY_PKG_OBSOLETES_BY_PRIORITY:
+ filterObsoletesByPriority(f, &m);
+ break;
case HY_PKG_PROVIDES:
assert(f.getMatchType() == _HY_RELDEP);
filterProvidesReldep(f, &m);
diff --git a/python/hawkey/hawkeymodule.cpp b/python/hawkey/hawkeymodule.cpp
index 4351e96e1..82d05e2cb 100644
--- a/python/hawkey/hawkeymodule.cpp
+++ b/python/hawkey/hawkeymodule.cpp
@@ -270,6 +270,7 @@ PYCOMP_MOD_INIT(_hawkey)
PyModule_AddIntConstant(m, "PKG_NEVRA", HY_PKG_NEVRA);
PyModule_AddIntConstant(m, "PKG_NEVRA_STRICT", HY_PKG_NEVRA_STRICT);
PyModule_AddIntConstant(m, "PKG_OBSOLETES", HY_PKG_OBSOLETES);
+ PyModule_AddIntConstant(m, "PKG_OBSOLETES_BY_PRIORITY", HY_PKG_OBSOLETES_BY_PRIORITY);
PyModule_AddIntConstant(m, "PKG_PROVIDES", HY_PKG_PROVIDES);
PyModule_AddIntConstant(m, "PKG_RECOMMENDS", HY_PKG_RECOMMENDS);
PyModule_AddIntConstant(m, "PKG_RELEASE", HY_PKG_RELEASE);
diff --git a/python/hawkey/query-py.cpp b/python/hawkey/query-py.cpp
index 286e306d3..9178a6d0c 100644
--- a/python/hawkey/query-py.cpp
+++ b/python/hawkey/query-py.cpp
@@ -78,6 +78,7 @@ static const int keyname_int_matches[] = {
HY_PKG_NEVRA,
HY_PKG_NEVRA_STRICT,
HY_PKG_OBSOLETES,
+ HY_PKG_OBSOLETES_BY_PRIORITY,
HY_PKG_PROVIDES,
HY_PKG_RECOMMENDS,
HY_PKG_RELEASE,
@@ -118,6 +119,7 @@ static const char * const keyname_char_matches[] = {
"nevra",
"nevra_strict",
"obsoletes",
+ "obsoletes_by_priority",
"provides",
"recommends",
"release",
@@ -342,7 +344,8 @@ filter_add(HyQuery query, key_t keyname, int cmp_type, PyObject *match)
// match is a sequence now:
switch (keyname) {
case HY_PKG:
- case HY_PKG_OBSOLETES: {
+ case HY_PKG_OBSOLETES:
+ case HY_PKG_OBSOLETES_BY_PRIORITY: {
// It could be a sequence of packages or reldep/strings. Lets try packages first.
auto pset = pyseq_to_packageset(match, query->getSack());
if (!pset) {

View File

@ -1,98 +0,0 @@
From dc3b2a2b22106fa4c0033a5557584f3b08c942e2 Mon Sep 17 00:00:00 2001
From: Marek Blaha <mblaha@redhat.com>
Date: Fri, 3 Jan 2020 12:35:33 +0100
Subject: [PATCH] Remove killGpgAgent function (RhBug:1781601)
Instead ensure that /run/user/$UID directory exists so gpgagent could
create its socket in it.
The solution with KILLAGENT caused race condition with gpgme_release()
call and that resulted in dnf being possibly terminated by SIGPIPE after
importing the first repository gpg key.
https://bugzilla.redhat.com/show_bug.cgi?id=1781601
---
libdnf/repo/Repo.cpp | 56 +++++++++++++++++++++++---------------------
1 file changed, 29 insertions(+), 27 deletions(-)
diff --git a/libdnf/repo/Repo.cpp b/libdnf/repo/Repo.cpp
index 850e5b4a8..c1891cce9 100644
--- a/libdnf/repo/Repo.cpp
+++ b/libdnf/repo/Repo.cpp
@@ -846,27 +846,35 @@ std::vector<Key> Repo::Impl::retrieve(const std::string & url)
return keyInfos;
}
-static void killGpgAgent(gpgme_ctx_t context, const std::string & gpgDir)
-{
+/*
+ * Creates the '/run/user/$UID' directory if it doesn't exist. If this
+ * directory exists, gpgagent will create its sockets under
+ * '/run/user/$UID/gnupg'.
+ *
+ * If this directory doesn't exist, gpgagent will create its sockets in gpg
+ * home directory, which is under '/var/cache/yum/metadata/' and this was
+ * causing trouble with container images, see [1].
+ *
+ * Previous solution was to send the agent a "KILLAGENT" message, but that
+ * would cause a race condition with calling gpgme_release(), see [2], [3],
+ * [4].
+ *
+ * Since the agent doesn't clean up its sockets properly, by creating this
+ * directory we make sure they are in a place that is not causing trouble with
+ * container images.
+ *
+ * [1] https://bugzilla.redhat.com/show_bug.cgi?id=1650266
+ * [2] https://bugzilla.redhat.com/show_bug.cgi?id=1769831
+ * [3] https://github.com/rpm-software-management/microdnf/issues/50
+ * [4] https://bugzilla.redhat.com/show_bug.cgi?id=1781601
+ */
+static void ensure_socket_dir_exists() {
auto logger(Log::getLogger());
-
- auto gpgErr = gpgme_set_protocol(context, GPGME_PROTOCOL_ASSUAN);
- if (gpgErr != GPG_ERR_NO_ERROR) {
- auto msg = tfm::format(_("%s: gpgme_set_protocol(): %s"), __func__, gpgme_strerror(gpgErr));
- logger->warning(msg);
- return;
- }
- std::string gpgAgentSock = gpgDir + "/S.gpg-agent";
- gpgErr = gpgme_ctx_set_engine_info(context, GPGME_PROTOCOL_ASSUAN, gpgAgentSock.c_str(), gpgDir.c_str());
- if (gpgErr != GPG_ERR_NO_ERROR) {
- auto msg = tfm::format(_("%s: gpgme_ctx_set_engine_info(): %s"), __func__, gpgme_strerror(gpgErr));
- logger->warning(msg);
- return;
- }
- gpgErr = gpgme_op_assuan_transact_ext(context, "KILLAGENT", NULL, NULL, NULL, NULL, NULL, NULL, NULL);
- if (gpgErr != GPG_ERR_NO_ERROR) {
- auto msg = tfm::format(_("%s: gpgme_op_assuan_transact_ext(): %s"), __func__, gpgme_strerror(gpgErr));
- logger->debug(msg);
+ std::string dirname = "/run/user/" + std::to_string(getuid());
+ int res = mkdir(dirname.c_str(), 0700);
+ if (res != 0 && errno != EEXIST) {
+ logger->debug(tfm::format("Failed to create directory \"%s\": %d - %s",
+ dirname, errno, strerror(errno)));
}
}
@@ -876,6 +884,7 @@ void Repo::Impl::importRepoKeys()
auto gpgDir = getCachedir() + "/pubring";
auto knownKeys = keyidsFromPubring(gpgDir);
+ ensure_socket_dir_exists();
for (const auto & gpgkeyUrl : conf->gpgkey().getValue()) {
auto keyInfos = retrieve(gpgkeyUrl);
for (auto & keyInfo : keyInfos) {
@@ -908,13 +917,6 @@ void Repo::Impl::importRepoKeys()
gpgImportKey(ctx, keyInfo.rawKey);
- // Running gpg-agent kept opened sockets on the system.
- // It tries to exit gpg-agent. Path to the communication socket is derived from homedir.
- // The gpg-agent automaticaly removes all its socket before exit.
- // Newer gpg-agent creates sockets under [/var]/run/user/{pid}/... if directory exists.
- // In this case gpg-agent will not be exited.
- killGpgAgent(ctx, gpgDir);
-
logger->debug(tfm::format(_("repo %s: imported key 0x%s."), id, keyInfo.getId()));
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,21 @@
diff -u b/python/hawkey/goal-py.cpp b/python/hawkey/goal-py.cpp
--- b/python/hawkey/goal-py.cpp
+++ b/python/hawkey/goal-py.cpp
@@ -253,7 +253,7 @@
int c_value = PyObject_IsTrue(value);
self->goal->set_protect_running_kernel(c_value);
return 0;
-} CATCH_TO_PYTHON
+} CATCH_TO_PYTHON_INT
static PyObject *
erase(_GoalObject *self, PyObject *args, PyObject *kwds) try
@@ -645,7 +645,7 @@
static PyGetSetDef goal_getsetters[] = {
{(char*)"actions", (getter)get_actions, NULL, NULL, NULL},
- {"protect_running_kernel", (getter)get_protect_running_kernel,
+ {(char*)"protect_running_kernel", (getter)get_protect_running_kernel,
(setter)set_protect_running_kernel, NULL, NULL},
{NULL} /* sentinel */
};

File diff suppressed because it is too large Load Diff

View File

@ -1,126 +0,0 @@
From 594560870c416d0133b08a64e0632a53a6217f71 Mon Sep 17 00:00:00 2001
From: Marek Blaha <mblaha@redhat.com>
Date: Mon, 20 Jan 2020 09:58:03 +0100
Subject: [PATCH] Fix filtering packages by advisory (RhBug:1770125)
Currently the filter does not work well in situation when more versions
and architectures of advisory packages are available.
Let's have package gjs-1.56.2-6.fc30.x86_64
and two advisories related to gjs package:
FEDORA-2019-f4eb34cf4c
gjs-1.56.2-1.fc30.src
gjs-1.56.2-1.fc30.x86_64
FEDORA-2019-57b5902ed1
gjs-1.56.2-6.fc30.src
gjs-1.56.2-6.fc30.x86_64
In this case the FEDORA-2019-57b5902ed1 advisory is not matched for
gjs-1.56.2-6.fc30.x86_64 package (considering >= operator as in 'dnf
update --bugfix') because only the package of `src` architecture as been
checked. The checking of other versions/architectures was missing.
https://bugzilla.redhat.com/show_bug.cgi?id=1770125
---
libdnf/sack/query.cpp | 63 +++++++++++++++----------------------------
1 file changed, 22 insertions(+), 41 deletions(-)
diff --git a/libdnf/sack/query.cpp b/libdnf/sack/query.cpp
index 6e9e4715f..122a50df6 100644
--- a/libdnf/sack/query.cpp
+++ b/libdnf/sack/query.cpp
@@ -518,9 +518,9 @@ advisoryPkgCompareSolvable(const AdvisoryPkg &first, const Solvable &s)
{
if (first.getName() != s.name)
return first.getName() < s.name;
- if (first.getEVR() != s.evr)
- return first.getEVR() < s.evr;
- return first.getArch() < s.arch;
+ if (first.getArch() != s.arch)
+ return first.getArch() < s.arch;
+ return first.getEVR() < s.evr;
}
static bool
@@ -1607,13 +1607,12 @@ Query::Impl::filterLocation(const Filter & f, Map *m)
/**
* @brief Reduce query to security filters. It reflect following compare types: HY_EQ, HY_GT, HY_LT.
-* In case HY_GT or HY_LT, it first find all advisory packages that EQ to packages in result.
-* Then it adds packages from Result to Map *m if Name and Arch is EQ, and EVR comparison is
-* according to one of selected compare type (HY_EQ, HY_GT, HY_LT).
*
-* @param f p_f:...
-* @param m p_m:...
-* @param keyname p_keyname:...
+* @param f: Filter that should be applied on advisories
+* @param m: Map of query results complying the filter
+* @param keyname: how are the advisories matched. HY_PKG_ADVISORY, HY_PKG_ADVISORY_BUG,
+* HY_PKG_ADVISORY_CVE, HY_PKG_ADVISORY_TYPE and HY_PKG_ADVISORY_SEVERITY
+* are supported
*/
void
Query::Impl::filterAdvisory(const Filter & f, Map *m, int keyname)
@@ -1668,7 +1667,6 @@ Query::Impl::filterAdvisory(const Filter & f, Map *m, int keyname)
// convert nevras (from DnfAdvisoryPkg) to pool ids
Id id = -1;
int cmp_type = f.getCmpType();
- bool cmpTypeGreaterOrLower = cmp_type & HY_GT || cmp_type & HY_LT;
while (true) {
if (pkgs.size() == 0)
break;
@@ -1676,40 +1674,23 @@ Query::Impl::filterAdvisory(const Filter & f, Map *m, int keyname)
if (id == -1)
break;
Solvable* s = pool_id2solvable(pool, id);
- auto low = std::lower_bound(pkgs.begin(), pkgs.end(), *s, advisoryPkgCompareSolvable);
- if (low != pkgs.end() && low->nevraEQ(s)) {
- if (cmpTypeGreaterOrLower) {
- pkgsSecondRun.push_back(*low);
- } else {
+ if (cmp_type == HY_EQ) {
+ auto low = std::lower_bound(pkgs.begin(), pkgs.end(), *s, advisoryPkgCompareSolvable);
+ if (low != pkgs.end() && low->nevraEQ(s)) {
MAPSET(m, id);
}
- }
- }
- if (!cmpTypeGreaterOrLower) {
- return;
- }
- std::sort(pkgsSecondRun.begin(), pkgsSecondRun.end(), advisoryPkgSort);
- id = -1;
- while (true) {
- if (pkgsSecondRun.size() == 0)
- break;
- id = resultPset->next(id);
- if (id == -1)
- break;
- Solvable* s = pool_id2solvable(pool, id);
- auto low = std::lower_bound(pkgsSecondRun.begin(), pkgsSecondRun.end(), *s,
- advisoryPkgCompareSolvableNameArch);
- while (low != pkgsSecondRun.end() && low->getName() == s->name &&
- low->getArch() == s->arch) {
-
- int cmp = pool_evrcmp(pool, s->evr, low->getEVR(), EVRCMP_COMPARE);
- if ((cmp > 0 && cmp_type & HY_GT) ||
- (cmp < 0 && cmp_type & HY_LT) ||
- (cmp == 0 && cmp_type & HY_EQ)) {
- MAPSET(m, id);
- break;
+ } else {
+ auto low = std::lower_bound(pkgs.begin(), pkgs.end(), *s, advisoryPkgCompareSolvableNameArch);
+ while (low != pkgs.end() && low->getName() == s->name && low->getArch() == s->arch) {
+ int cmp = pool_evrcmp(pool, s->evr, low->getEVR(), EVRCMP_COMPARE);
+ if ((cmp > 0 && cmp_type & HY_GT) ||
+ (cmp < 0 && cmp_type & HY_LT) ||
+ (cmp == 0 && cmp_type & HY_EQ)) {
+ MAPSET(m, id);
+ break;
+ }
+ ++low;
}
- ++low;
}
}
}

View File

@ -1,306 +0,0 @@
From add2ce925b65532455e3522113bede4f99993638 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hr=C3=A1zk=C3=BD?= <lhrazky@redhat.com>
Date: Wed, 10 Jul 2019 15:42:19 +0200
Subject: [PATCH 1/5] Query: use the common dep switch branch for CONFLICTS
when applying
Join the HY_PKG_CONFLICTS switch branch with the rest of the
dependencies and remove the matchtype assert. The assert is done in the
filterRcoReldep() function and the rest is the same.
---
libdnf/sack/query.cpp | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/libdnf/sack/query.cpp b/libdnf/sack/query.cpp
index 122a50df..f044faa6 100644
--- a/libdnf/sack/query.cpp
+++ b/libdnf/sack/query.cpp
@@ -1977,9 +1977,6 @@ Query::Impl::apply()
case HY_PKG_EMPTY:
/* used to set query empty by keeping Map m empty */
break;
- case HY_PKG_CONFLICTS:
- filterRcoReldep(f, &m);
- break;
case HY_PKG_NAME:
filterName(f, &m);
break;
@@ -2019,12 +2016,12 @@ Query::Impl::apply()
assert(f.getMatchType() == _HY_RELDEP);
filterProvidesReldep(f, &m);
break;
+ case HY_PKG_CONFLICTS:
case HY_PKG_ENHANCES:
case HY_PKG_RECOMMENDS:
case HY_PKG_REQUIRES:
case HY_PKG_SUGGESTS:
case HY_PKG_SUPPLEMENTS:
- assert(f.getMatchType() == _HY_RELDEP);
filterRcoReldep(f, &m);
break;
case HY_PKG_REPONAME:
--
2.25.4
From 8b06d5b286d165eb8002b6a002d336ab2b72b0b2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hr=C3=A1zk=C3=BD?= <lhrazky@redhat.com>
Date: Thu, 11 Jul 2019 11:54:11 +0200
Subject: [PATCH 2/5] Query: add a dependency by solvable filter
(RhBug:1534123,1698034)
This allows to filter all dependencies (requires, conflicts, recommends,
etc.) by a list of solvables that match the dependency.
Can be used in the dnf repoquery command instead of a low-level piece of
code which was expanding packages to their provides and then matching the
dependencies as reldeps.
https://bugzilla.redhat.com/show_bug.cgi?id=1534123
https://bugzilla.redhat.com/show_bug.cgi?id=1698034
---
libdnf/sack/query.cpp | 33 +++++++++++++++++++++++++++++++--
1 file changed, 31 insertions(+), 2 deletions(-)
diff --git a/libdnf/sack/query.cpp b/libdnf/sack/query.cpp
index f044faa6..d96d5d12 100644
--- a/libdnf/sack/query.cpp
+++ b/libdnf/sack/query.cpp
@@ -280,7 +280,7 @@ valid_filter_num(int keyname, int cmp_type)
static bool
valid_filter_pkg(int keyname, int cmp_type)
{
- if (!match_type_pkg(keyname))
+ if (!match_type_pkg(keyname) && !match_type_reldep(keyname))
return false;
return cmp_type == HY_EQ || cmp_type == HY_NEQ;
}
@@ -683,6 +683,7 @@ private:
void filterNevraStrict(int cmpType, const char **matches);
void initResult();
void filterPkg(const Filter & f, Map *m);
+ void filterDepSolvable(const Filter & f, Map * m);
void filterRcoReldep(const Filter & f, Map *m);
void filterName(const Filter & f, Map *m);
void filterEpoch(const Filter & f, Map *m);
@@ -1058,6 +1059,30 @@ Query::Impl::filterPkg(const Filter & f, Map *m)
map_init_clone(m, dnf_packageset_get_map(f.getMatches()[0].pset));
}
+void
+Query::Impl::filterDepSolvable(const Filter & f, Map * m)
+{
+ assert(f.getMatchType() == _HY_PKG);
+ assert(f.getMatches().size() == 1);
+
+ dnf_sack_make_provides_ready(sack);
+ Pool * pool = dnf_sack_get_pool(sack);
+ Id rco_key = reldep_keyname2id(f.getKeyname());
+
+ IdQueue out;
+
+ const auto filter_pset = f.getMatches()[0].pset;
+ Id id = -1;
+ while ((id = filter_pset->next(id)) != -1) {
+ out.clear();
+ pool_whatmatchessolvable(pool, rco_key, id, out.getQueue(), -1);
+
+ for (int j = 0; j < out.size(); ++j) {
+ MAPSET(m, out[j]);
+ }
+ }
+}
+
void
Query::Impl::filterRcoReldep(const Filter & f, Map *m)
{
@@ -2022,7 +2047,11 @@ Query::Impl::apply()
case HY_PKG_REQUIRES:
case HY_PKG_SUGGESTS:
case HY_PKG_SUPPLEMENTS:
- filterRcoReldep(f, &m);
+ if (f.getMatchType() == _HY_RELDEP)
+ filterRcoReldep(f, &m);
+ else {
+ filterDepSolvable(f, &m);
+ }
break;
case HY_PKG_REPONAME:
filterReponame(f, &m);
--
2.25.4
From 1a62aa8336ab390a1825d052a096b613805b20ca Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hr=C3=A1zk=C3=BD?= <lhrazky@redhat.com>
Date: Wed, 21 Aug 2019 16:50:49 +0200
Subject: [PATCH 3/5] Hawkey tests: fix filtering on requires by passing a
query
Fixes tests after allowing to pass a query (or an iterable of packages)
as an argument to dependency filters (requires, suggests, etc.) in
"Query: add a dependency by solvable filter".
Drops the exception check and adds a simple test for the new
functionality.
---
python/hawkey/tests/tests/test_query.py | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/python/hawkey/tests/tests/test_query.py b/python/hawkey/tests/tests/test_query.py
index 1d45f163..3ee009dd 100644
--- a/python/hawkey/tests/tests/test_query.py
+++ b/python/hawkey/tests/tests/test_query.py
@@ -352,12 +352,17 @@ class TestQueryUpdates(base.TestCase):
q = hawkey.Query(self.sack).filter(name="penny")
o = hawkey.Query(self.sack)
self.assertRaises(hawkey.QueryException, o.filter, obsoletes__gt=q)
- self.assertRaises(hawkey.ValueException, o.filter, requires=q)
o = hawkey.Query(self.sack).filter(obsoletes=q)
self.assertLength(o, 1)
self.assertEqual(str(o[0]), "fool-1-5.noarch")
+ def test_requires_with_package_list(self):
+ q = hawkey.Query(self.sack).filter(name="fool")
+ o = hawkey.Query(self.sack).filter(requires=q)
+ self.assertLength(o, 1)
+ self.assertEqual(str(o[0]), "walrus-2-6.noarch")
+
def test_subquery_evaluated(self):
q = hawkey.Query(self.sack).filter(name="penny")
self.assertFalse(q.evaluated)
--
2.25.4
From d1554451b123c2a83f665d743214ca4d3d0ef3a0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hr=C3=A1zk=C3=BD?= <lhrazky@redhat.com>
Date: Tue, 14 Jan 2020 13:40:58 +0100
Subject: [PATCH 4/5] Query: Add support for a sequence of packages to
dependency queries
In addition to supporting a query as an argument to the dependency
filters (which then gets resolved to a list of packages), add support
for passing a sequence of packages directly.
---
python/hawkey/query-py.cpp | 16 ++++++++--------
python/hawkey/tests/tests/test_query.py | 8 +++++++-
2 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/python/hawkey/query-py.cpp b/python/hawkey/query-py.cpp
index 274b8c3e..5e1d368b 100644
--- a/python/hawkey/query-py.cpp
+++ b/python/hawkey/query-py.cpp
@@ -345,7 +345,13 @@ filter_add(HyQuery query, key_t keyname, int cmp_type, PyObject *match)
switch (keyname) {
case HY_PKG:
case HY_PKG_OBSOLETES:
- case HY_PKG_OBSOLETES_BY_PRIORITY: {
+ case HY_PKG_OBSOLETES_BY_PRIORITY:
+ case HY_PKG_CONFLICTS:
+ case HY_PKG_REQUIRES:
+ case HY_PKG_ENHANCES:
+ case HY_PKG_RECOMMENDS:
+ case HY_PKG_SUGGESTS:
+ case HY_PKG_SUPPLEMENTS: {
// It could be a sequence of packages or reldep/strings. Lets try packages first.
auto pset = pyseq_to_packageset(match, query->getSack());
if (!pset) {
@@ -372,13 +378,7 @@ filter_add(HyQuery query, key_t keyname, int cmp_type, PyObject *match)
break;
}
- case HY_PKG_CONFLICTS:
- case HY_PKG_PROVIDES:
- case HY_PKG_REQUIRES:
- case HY_PKG_ENHANCES:
- case HY_PKG_RECOMMENDS:
- case HY_PKG_SUGGESTS:
- case HY_PKG_SUPPLEMENTS: {
+ case HY_PKG_PROVIDES: {
auto reldeplist = pyseq_to_reldeplist(match, query->getSack(), cmp_type);
if (reldeplist == NULL)
return 1;
diff --git a/python/hawkey/tests/tests/test_query.py b/python/hawkey/tests/tests/test_query.py
index 3ee009dd..ff942e71 100644
--- a/python/hawkey/tests/tests/test_query.py
+++ b/python/hawkey/tests/tests/test_query.py
@@ -357,12 +357,18 @@ class TestQueryUpdates(base.TestCase):
self.assertLength(o, 1)
self.assertEqual(str(o[0]), "fool-1-5.noarch")
- def test_requires_with_package_list(self):
+ def test_requires_with_query(self):
q = hawkey.Query(self.sack).filter(name="fool")
o = hawkey.Query(self.sack).filter(requires=q)
self.assertLength(o, 1)
self.assertEqual(str(o[0]), "walrus-2-6.noarch")
+ def test_requires_with_package_list(self):
+ q = hawkey.Query(self.sack).filter(name="fool")
+ o = hawkey.Query(self.sack).filter(requires=q.run())
+ self.assertLength(o, 1)
+ self.assertEqual(str(o[0]), "walrus-2-6.noarch")
+
def test_subquery_evaluated(self):
q = hawkey.Query(self.sack).filter(name="penny")
self.assertFalse(q.evaluated)
--
2.25.4
From cbaafb957532dfde13080903503cae4488b0863f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Tue, 17 Mar 2020 13:11:14 +0100
Subject: [PATCH 5/5] Use libsolv selection for filtering DepSolvables
(RhBug:1812596)
We cannot use pool_whatmatchessolvable because it considers only
installable solvables, which means source rpms are ignored.
https://bugzilla.redhat.com/show_bug.cgi?id=1812596
---
libdnf/sack/query.cpp | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/libdnf/sack/query.cpp b/libdnf/sack/query.cpp
index d96d5d12..390703c9 100644
--- a/libdnf/sack/query.cpp
+++ b/libdnf/sack/query.cpp
@@ -29,6 +29,7 @@ extern "C" {
#include <solv/bitmap.h>
#include <solv/evr.h>
#include <solv/solver.h>
+#include <solv/selection.h>
}
#include "query.hpp"
@@ -1075,9 +1076,22 @@ Query::Impl::filterDepSolvable(const Filter & f, Map * m)
Id id = -1;
while ((id = filter_pset->next(id)) != -1) {
out.clear();
- pool_whatmatchessolvable(pool, rco_key, id, out.getQueue(), -1);
- for (int j = 0; j < out.size(); ++j) {
+ queue_init(out.getQueue());
+ // queue_push2 because we are creating a selection, which contains pairs
+ // of <flags, Id>, SOLVER_SOOLVABLE_ALL is a special flag which includes
+ // all packages from specified pool, Id is ignored.
+ queue_push2(out.getQueue(), SOLVER_SOLVABLE_ALL, 0);
+
+ int flags = 0;
+ flags |= SELECTION_FILTER | SELECTION_WITH_ALL;
+ selection_make_matchsolvable(pool, out.getQueue(), id, flags, rco_key, 0);
+
+ // Queue from selection_make_matchsolvable is a selection, which means
+ // it conntains pairs <flags, Id>, flags refers to how was the Id
+ // matched, that is not important here, so skip it and iterate just
+ // over the Ids.
+ for (int j = 1; j < out.size(); j += 2) {
MAPSET(m, out[j]);
}
}
--
2.25.4

View File

@ -1,8 +1,11 @@
%global libsolv_version 0.7.7
%global libmodulemd_version 1.6.1
%global librepo_version 1.11.0
%global dnf_conflict 4.2.13
%global libmodulemd_version 2.5.0
%global librepo_version 1.12.0
%global dnf_conflict 4.2.23
%global swig_version 3.0.12
%global libdnf_major_version 0
%global libdnf_minor_version 48
%global libdnf_micro_version 0
# set sphinx package name according to distro
%global requires_python2_sphinx python2-sphinx
@ -43,25 +46,24 @@
%bcond_without zchunk
%endif
%bcond_with sanitizers
%global _cmake_opts \\\
-DENABLE_RHSM_SUPPORT=%{?with_rhsm:ON}%{!?with_rhsm:OFF} \\\
%{nil}
Name: libdnf
Version: 0.39.1
Release: 6%{?dist}
Version: %{libdnf_major_version}.%{libdnf_minor_version}.%{libdnf_micro_version}
Release: 5%{?dist}
Summary: Library providing simplified C and Python API to libsolv
License: LGPLv2+
URL: https://github.com/rpm-software-management/libdnf
Source0: %{url}/archive/%{version}/%{name}-%{version}.tar.gz
Patch1: 0001-user-agent-Drop-the-whitelist.patch
Patch2: 0002-context-wildcard-support-in-dnf_context_repo_set_data-RhBug1781420.patch
Patch3: 0003-Add-2-query-filters.patch
Patch4: 0004-Remove-killGpgAgent-function-RhBug1781601.patch
Patch5: 0005-Update-translations-from-zanata-RhBug-1754965.patch
Patch6: 0006-Fix-filtering-packages-by-advisory-RhBug-1770125.patch
# Includes Use libsolv selection for filtering DepSolvables (RhBug:1812596)
Patch7: 0007-Add-expanding-solvable-provides-for-dependency-matching-RhBug-1819172.patch
Patch1: 0001-history-Fix-dnf-history-rollback-when-a-package-was-removed-RhBug1683134.patch
Patch2: 0002-Add-log-file-level-main-config-option-RhBug-1802074.patch
Patch3: 0003-Accept-double-eq-as-an-operator-in-reldeps-RhBug-1847946.patch
Patch4: 0004-Update-translations-RhBug-1820548.patch
Patch5: 0005-Handle-exception-in-a-python-binding-by-the-proper-function-RhBug-1870492.patch
BuildRequires: cmake
BuildRequires: gcc
@ -85,11 +87,17 @@ BuildRequires: pkgconfig(sqlite3)
BuildRequires: pkgconfig(json-c)
BuildRequires: pkgconfig(cppunit)
BuildRequires: pkgconfig(libcrypto)
BuildRequires: pkgconfig(modulemd) >= %{libmodulemd_version}
BuildRequires: pkgconfig(modulemd-2.0) >= %{libmodulemd_version}
BuildRequires: pkgconfig(smartcols)
BuildRequires: gettext
BuildRequires: gpgme-devel
%if %{with sanitizers}
BuildRequires: libasan-static
BuildRequires: liblsan-static
BuildRequires: libubsan-static
%endif
Requires: libmodulemd%{?_isa} >= %{libmodulemd_version}
Requires: libsolv%{?_isa} >= %{libsolv_version}
Requires: librepo%{?_isa} >= %{librepo_version}
@ -132,7 +140,8 @@ BuildRequires: swig >= %{swig_version}
%description -n python2-%{name}
Python 2 bindings for the libdnf library.
%endif # with python2
%endif
# endif with python2
%if %{with python3}
%package -n python3-%{name}
@ -166,7 +175,8 @@ Conflicts: python-dnf < %{dnf_conflict}
%description -n python2-hawkey
Python 2 bindings for the hawkey library.
%endif # with python2
%endif
# endif with python2
%if %{with python3}
%package -n python3-hawkey
@ -190,7 +200,7 @@ Python 3 bindings for the hawkey library.
%autosetup -p1
%if %{with python2}
mkdir build-py2
%endif # with python2
%endif
%if %{with python3}
mkdir build-py3
%endif
@ -203,10 +213,12 @@ pushd build-py2
%define _cmake_builddir build-py2
%define __builddir build-py2
%endif
%cmake -DPYTHON_DESIRED:FILEPATH=%{__python2} -DWITH_MAN=OFF ../ %{!?with_zchunk:-DWITH_ZCHUNK=OFF} %{!?with_valgrind:-DDISABLE_VALGRIND=1} %{_cmake_opts}
%cmake -DPYTHON_DESIRED:FILEPATH=%{__python2} -DWITH_MAN=OFF ../ %{!?with_zchunk:-DWITH_ZCHUNK=OFF} %{!?with_valgrind:-DDISABLE_VALGRIND=1} %{_cmake_opts} -DLIBDNF_MAJOR_VERSION=%{libdnf_major_version} -DLIBDNF_MINOR_VERSION=%{libdnf_minor_version} -DLIBDNF_MICRO_VERSION=%{libdnf_micro_version} \
-DWITH_SANITIZERS=%{?with_sanitizers:ON}%{!?with_sanitizers:OFF}
%make_build
popd
%endif # with python2
%endif
# endif with python2
%if %{with python3}
pushd build-py3
@ -215,7 +227,8 @@ pushd build-py3
%define _cmake_builddir build-py3
%define __builddir build-py3
%endif
%cmake -DPYTHON_DESIRED:FILEPATH=%{__python3} -DWITH_GIR=0 -DWITH_MAN=0 -Dgtkdoc=0 ../ %{!?with_zchunk:-DWITH_ZCHUNK=OFF} %{!?with_valgrind:-DDISABLE_VALGRIND=1} %{_cmake_opts}
%cmake -DPYTHON_DESIRED:FILEPATH=%{__python3} -DWITH_GIR=0 -DWITH_MAN=0 -Dgtkdoc=0 ../ %{!?with_zchunk:-DWITH_ZCHUNK=OFF} %{!?with_valgrind:-DDISABLE_VALGRIND=1} %{_cmake_opts} -DLIBDNF_MAJOR_VERSION=%{libdnf_major_version} -DLIBDNF_MINOR_VERSION=%{libdnf_minor_version} -DLIBDNF_MICRO_VERSION=%{libdnf_micro_version} \
-DWITH_SANITIZERS=%{?with_sanitizers:ON}%{!?with_sanitizers:OFF}
%make_build
popd
%endif
@ -225,7 +238,7 @@ popd
pushd build-py2
make ARGS="-V" test
popd
%endif # with python2
%endif
%if %{with python3}
# If we didn't run the general tests yet, do it now.
%if %{without python2}
@ -247,7 +260,7 @@ popd
pushd build-py2
%make_install
popd
%endif # with python2
%endif
%if %{with python3}
pushd build-py3
%make_install
@ -280,7 +293,7 @@ popd
%if %{with python2}
%files -n python2-%{name}
%{python2_sitearch}/%{name}/
%endif # with python2
%endif
%if %{with python3}
%files -n python3-%{name}
@ -290,7 +303,7 @@ popd
%if %{with python2}
%files -n python2-hawkey
%{python2_sitearch}/hawkey/
%endif # with python2
%endif
%if %{with python3}
%files -n python3-hawkey
@ -298,8 +311,78 @@ popd
%endif
%changelog
* Wed May 06 2020 Nicola Sella <nsella@redhat.com> - 0.39.1-6
- Add expanding solvable provides for dependency matching (RhBug:1819172)
* Thu Aug 20 2020 Nicola Sella <nsella@redhat.com> - 0.48.0-5
- [covscan] Handle exception in a python binding by the proper function (RhBug:1870492)
* Tue Jul 28 2020 Marek Blaha <mblaha@redhat.com> - 0.48.0-4
- Update translations (RhBug:1820548)
* Fri Jul 17 2020 Nicola Sella <nsella@redhat.com> - 0.48.0-3
- Add log file level main config option (RhBug:1802074)
- Accept '==' as an operator in reldeps (RhBug:1847946)
* Wed Jun 10 2020 Ales Matej <amatej@redhat.com> - 0.48.0-2
- [history] Fix dnf history rollback when a package was removed (RhBug:1683134)
* Wed Jun 03 2020 Nicola Sella <nsella@redhat.com> - 0.48.0-1
- Update to 0.48.0
- swdb: Catch only SQLite3 exceptions and simplify the messages
- MergedTransaction list multiple comments (RhBug:1773679)
- Modify CMake to pull *.po files from weblate
- Optimize DependencyContainer creation from an existing queue
- fix a memory leak in dnf_package_get_requires()
- Fix memory leaks on g_build_filename()
- Fix memory leak in dnf_context_setup()
- Add `hy_goal_favor` and `hy_goal_disfavor`
- Define a cleanup function for `DnfPackageSet`
- dnf-repo: fix dnf_repo_get_public_keys double-free
- Do not cache RPMDB
- Use single-quotes around string literals used in SQL statements
- SQLite3: Do not close the database if it wasn't opened (RhBug:1761976)
- Don't create a new history DB connection for in-memory DB
- transaction/Swdb: Use a single logger variable in constructor
- utils: Add a safe version of pathExists()
- swdb: Handle the case when pathExists() fails on e.g. permission
- Repo: prepend "file://" if a local path is used as baseurl
- Move urlEncode() to utils
- utils: Add 'exclude' argument to urlEncode()
- Encode package URL for downloading through librepo (RhBug:1817130)
- Replace std::runtime_error with libdnf::RepoError
- Fixes and error handling improvements of the File class
- [context] Use ConfigRepo for gpgkey and baseurl (RhBug:1807864)
- [context] support "priority" option in .repo config file (RhBug:1797265)
* Fri Apr 03 2020 Ales Matej <amatej@redhat.com> - 0.47.0-1
- Update to 0.47.0
- Allow excluding packages with "excludepkgs" and globs
- Make parsing of reldeps more strict (RhBug:1788107)
- Add expanding solvable provides for dependency matching (RhBug:1534123)
- DnfRepo: fix module_hotfixes keyfile priority level
- Add custom exceptions to libdnf interface
- Port to libmodulemd-2 API (RhBug:1693683)
- Add prereq_ignoreinst & regular_requires properties for pkg (RhBug:1543449)
- Reset active modules when no module enabled or default (RhBug:1767351)
- Add comment option to transaction (RhBug:1773679)
- Baseurl is not exclusive with mirrorlist/metalink (RhBug:1775184)
- Add new function to reset all modules in C API (dnf_context_reset_all_modules)
- Handle situation when an unprivileged user cannot create history database (RhBug:1634385)
- Add query filter: latest by priority
- Add setter for running kernel protection setting
- Add DNF_NO_PROTECTED flag to allow empty list of protected packages
- Config options: only first empty value clears existing (RhBug:1788154)
- [conf] Set useful default colors when color is enabled
- [context] Use installonly_limit from global config (RhBug:1256108)
- [context] Add API to get/set "install_weak_deps"
- [context] Adds support for includepkgs in repository configuration.
- [context] Adds support for excludepkgs, exclude, includepkgs, and disable_excludes in main configuration.
- [context] Added function dnf_transaction_set_dont_solve_goal
- [context] Added functions dnf_context_get/set_config_file_path
- [context] Respect "plugins" global conf value
- [context] Add API to disable/enable plugins
- [context] Create new repo instead of reusing old one (RhBug:1795004)
- [context] Error when main config file can't be opened (RhBug:1794864)
- [context] Add function function dnf_context_is_set_config_file_path
- [context] Support repositories defined in main configuration file
* Tue Feb 18 2020 Ales Matej <amatej@redhat.com> - 0.39.1-5
- Fix filtering of packages by advisory (RhBug:1770125)