Compare commits

...

No commits in common. 'c9' and 'i10-beta' have entirely different histories.
c9 ... i10-beta

2
.gitignore vendored

@ -1 +1 @@
SOURCES/libdnf-0.69.0.tar.gz
SOURCES/libdnf-0.73.1.tar.gz

@ -1 +1 @@
744fc8ba2ad6906c87fc6d91cb953735d1f285e2 SOURCES/libdnf-0.69.0.tar.gz
317b564ada6b63d238865d657ff00f59ec6672df SOURCES/libdnf-0.73.1.tar.gz

@ -1,89 +0,0 @@
From 2834747bff215c6f8da4eef2820c29bc05e172e1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Wed, 7 Sep 2022 09:07:04 +0200
Subject: [PATCH] Allow change of arch during security updates with noarch
(RhBug:2124483)
This matches upgrade behaviour where upgrading from/to noarch is a
special case and architecture change of a package is allowed
automatically.
= changelog =
msg: Allow change of architecture for packages during security updates with noarch involved
type: security
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2124483
---
libdnf/sack/query.cpp | 34 ++++++++++++++++++++++++----------
1 file changed, 24 insertions(+), 10 deletions(-)
diff --git a/libdnf/sack/query.cpp b/libdnf/sack/query.cpp
index 8672275d..205439ec 100644
--- a/libdnf/sack/query.cpp
+++ b/libdnf/sack/query.cpp
@@ -189,6 +189,13 @@ NameArchSolvableComparator(const Solvable * first, const Solvable * second)
return first->arch < second->arch;
}
+static bool
+NameSolvableComparator(const Solvable * first, const Solvable * second)
+{
+ return first->name < second->name;
+}
+
+
static bool
NamePrioritySolvableKey(const Solvable * first, const Solvable * second)
{
@@ -1878,11 +1885,14 @@ Query::Impl::filterAdvisory(const Filter & f, Map *m, int keyname)
std::vector<Solvable *> installed_solvables;
if (cmp_type & HY_UPGRADE) {
- // When doing HY_UPGRADE consider only candidate pkgs that have matching Name and Arch with:
- // * some already installed pkg (in other words: some other version of the pkg is already installed)
- // or
- // * with pkg that obsoletes some already installed (or to be installed in this transaction) pkg
- // Otherwise a pkg with different Arch than installed can end up in upgrade set which is wrong.
+ // When doing HY_UPGRADE consider only candidate pkgs that:
+ // * have matching Name and Arch with some already installed pkg
+ // (in other words: some other version of the pkg is already installed)
+ // * have matching Name with some already installed pkg and either the candidate or the installed pkg is noarch.
+ // This matches upgrade behavior where we allow architecture change only when noarch is involved.
+ // Details: RhBug:2124483, RhBug:2101398 and RhBug:1171543
+ // * obsoletes some already installed (or to be installed in this transaction) pkg
+ // Otherwise a pkg with different Arch than installed (and than noarch) can end up in upgrade set which is wrong.
// It can result in dependency issues, reported as: RhBug:2088149.
Query installed(sack, ExcludeFlags::IGNORE_EXCLUDES);
@@ -1893,7 +1903,7 @@ Query::Impl::filterAdvisory(const Filter & f, Map *m, int keyname)
while ((installed_id = installed.pImpl->result->next(installed_id)) != -1) {
installed_solvables.push_back(pool_id2solvable(pool, installed_id));
}
- std::sort(installed_solvables.begin(), installed_solvables.end(), NameArchSolvableComparator);
+ std::sort(installed_solvables.begin(), installed_solvables.end(), NameSolvableComparator);
Query obsoletes(sack, ExcludeFlags::IGNORE_EXCLUDES);
obsoletes.addFilter(HY_PKG, HY_EQ, resultPset);
@@ -1915,12 +1925,16 @@ Query::Impl::filterAdvisory(const Filter & f, Map *m, int keyname)
}
Id id = -1;
- // Add to candidates resultPset pkgs that match name and arch with some already installed pkg
+ // Add to candidates resultPset pkgs that match name and arch with some already installed pkg or match name and either the installed or candidate are NOARCH
while ((id = resultPset->next(id)) != -1) {
Solvable * s = pool_id2solvable(pool, id);
- auto low = std::lower_bound(installed_solvables.begin(), installed_solvables.end(), s, NameArchSolvableComparator);
- if (low != installed_solvables.end() && s->name == (*low)->name && s->arch == (*low)->arch) {
- candidates.push_back(s);
+ auto low = std::lower_bound(installed_solvables.begin(), installed_solvables.end(), s, NameSolvableComparator);
+ while (low != installed_solvables.end() && (*low)->name == s->name) {
+ if (s->arch == (*low)->arch || s->arch == ARCH_NOARCH || (*low)->arch == ARCH_NOARCH) {
+ candidates.push_back(s);
+ break;
+ }
+ ++low;
}
}
--
2.37.3

@ -0,0 +1,229 @@
From 85432dfd048912083897ab687488087038a9ac96 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Mon, 8 Apr 2024 07:32:31 +0200
Subject: [PATCH] context: use `rpmtsAddReinstallElement()` when doing a
reinstall
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
`rpmtsAddInstallElement()` doesn't work for all reinstall cases, such as
when a package `Provides` and `Conflicts` with the same capability.
Fixes: https://github.com/rpm-software-management/microdnf/issues/137
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
libdnf/dnf-rpmts-private.hpp | 6 ++
libdnf/dnf-rpmts.cpp | 108 +++++++++++++++++++++++------------
libdnf/dnf-transaction.cpp | 8 ++-
3 files changed, 85 insertions(+), 37 deletions(-)
diff --git a/libdnf/dnf-rpmts-private.hpp b/libdnf/dnf-rpmts-private.hpp
index 94ad6b45..7a8f70fb 100644
--- a/libdnf/dnf-rpmts-private.hpp
+++ b/libdnf/dnf-rpmts-private.hpp
@@ -31,4 +31,10 @@ gboolean dnf_rpmts_add_install_filename2(rpmts ts,
DnfPackage *pkg,
GError **error);
+gboolean dnf_rpmts_add_reinstall_filename(rpmts ts,
+ const gchar *filename,
+ gboolean allow_untrusted,
+ GError **error);
+
+
#endif /* __DNF_RPMTS_PRIVATE_HPP */
diff --git a/libdnf/dnf-rpmts.cpp b/libdnf/dnf-rpmts.cpp
index ec3d3706..9c0152fc 100644
--- a/libdnf/dnf-rpmts.cpp
+++ b/libdnf/dnf-rpmts.cpp
@@ -88,94 +88,132 @@ test_fail_safe(Header * hdr, DnfPackage * pkg, GError **error)
return ret;
}
-gboolean
-dnf_rpmts_add_install_filename2(rpmts ts,
- const gchar *filename,
- gboolean allow_untrusted,
- gboolean is_update,
- DnfPackage * pkg,
- GError **error) try
-{
- gboolean ret = TRUE;
- gint res;
- Header hdr;
- FD_t fd;
-
- /* open this */
- fd = Fopen(filename, "r.ufdio");
- res = rpmReadPackageFile(ts, fd, filename, &hdr);
-
+static gboolean
+result_is_accepted(gint result, gboolean allow_untrusted, const gchar *filename, GError **error) {
/* be less strict when we're allowing untrusted transactions */
if (allow_untrusted) {
- switch(res) {
+ switch(result) {
case RPMRC_NOKEY:
case RPMRC_NOTFOUND:
case RPMRC_NOTTRUSTED:
case RPMRC_OK:
- break;
+ return TRUE;
case RPMRC_FAIL:
- ret = FALSE;
g_set_error(error,
DNF_ERROR,
DNF_ERROR_INTERNAL_ERROR,
_("signature does not verify for %s"),
filename);
- goto out;
+ return FALSE;
default:
- ret = FALSE;
g_set_error(error,
DNF_ERROR,
DNF_ERROR_INTERNAL_ERROR,
_("failed to open(generic error): %s"),
filename);
- goto out;
+ return FALSE;
}
} else {
- switch(res) {
+ switch(result) {
case RPMRC_OK:
- break;
+ return TRUE;
case RPMRC_NOTTRUSTED:
- ret = FALSE;
g_set_error(error,
DNF_ERROR,
DNF_ERROR_INTERNAL_ERROR,
_("failed to verify key for %s"),
filename);
- goto out;
+ return FALSE;
case RPMRC_NOKEY:
- ret = FALSE;
g_set_error(error,
DNF_ERROR,
DNF_ERROR_INTERNAL_ERROR,
_("public key unavailable for %s"),
filename);
- goto out;
+ return FALSE;
case RPMRC_NOTFOUND:
- ret = FALSE;
g_set_error(error,
DNF_ERROR,
DNF_ERROR_INTERNAL_ERROR,
_("signature not found for %s"),
filename);
- goto out;
+ return FALSE;
case RPMRC_FAIL:
- ret = FALSE;
g_set_error(error,
DNF_ERROR,
DNF_ERROR_INTERNAL_ERROR,
_("signature does not verify for %s"),
filename);
- goto out;
+ return FALSE;
default:
- ret = FALSE;
g_set_error(error,
DNF_ERROR,
DNF_ERROR_INTERNAL_ERROR,
_("failed to open(generic error): %s"),
filename);
- goto out;
+ return FALSE;
}
}
+}
+
+gboolean
+dnf_rpmts_add_reinstall_filename(rpmts ts,
+ const gchar *filename,
+ gboolean allow_untrusted,
+ GError **error) try
+{
+ gboolean ret = TRUE;
+ gint res;
+ Header hdr;
+ FD_t fd;
+
+ /* open this */
+ fd = Fopen(filename, "r.ufdio");
+ res = rpmReadPackageFile(ts, fd, filename, &hdr);
+
+ if (!result_is_accepted(res, allow_untrusted, filename, error)) {
+ ret = FALSE;
+ goto out;
+ }
+
+ /* add to the transaction */
+ res = rpmtsAddReinstallElement(ts, hdr, (fnpyKey) filename);
+ if (res != 0) {
+ ret = FALSE;
+ g_set_error(error,
+ DNF_ERROR,
+ DNF_ERROR_INTERNAL_ERROR,
+ _("failed to add reinstall element: %1$s [%2$i]"),
+ filename, res);
+ goto out;
+ }
+out:
+ Fclose(fd);
+ headerFree(hdr);
+ return ret;
+} CATCH_TO_GERROR(FALSE)
+
+gboolean
+dnf_rpmts_add_install_filename2(rpmts ts,
+ const gchar *filename,
+ gboolean allow_untrusted,
+ gboolean is_update,
+ DnfPackage * pkg,
+ GError **error) try
+{
+ gboolean ret = TRUE;
+ gint res;
+ Header hdr;
+ FD_t fd;
+
+ /* open this */
+ fd = Fopen(filename, "r.ufdio");
+ res = rpmReadPackageFile(ts, fd, filename, &hdr);
+
+ if (!result_is_accepted(res, allow_untrusted, filename, error)) {
+ ret = FALSE;
+ goto out;
+ }
if (pkg) {
if (!test_fail_safe(&hdr, pkg, error)) {
ret = FALSE;
diff --git a/libdnf/dnf-transaction.cpp b/libdnf/dnf-transaction.cpp
index c4c5e02b..35b2ff95 100644
--- a/libdnf/dnf-transaction.cpp
+++ b/libdnf/dnf-transaction.cpp
@@ -1222,8 +1222,12 @@ dnf_transaction_commit(DnfTransaction *transaction, HyGoal goal, DnfState *state
filename = dnf_package_get_filename(pkg);
allow_untrusted = (priv->flags & DNF_TRANSACTION_FLAG_ONLY_TRUSTED) == 0;
is_update = action == DNF_STATE_ACTION_UPDATE || action == DNF_STATE_ACTION_DOWNGRADE;
- ret = dnf_rpmts_add_install_filename2(
- priv->ts, filename, allow_untrusted, is_update, pkg, error);
+ if (action == DNF_STATE_ACTION_REINSTALL) {
+ ret = dnf_rpmts_add_reinstall_filename(priv->ts, filename, allow_untrusted, error);
+ } else {
+ ret = dnf_rpmts_add_install_filename2(
+ priv->ts, filename, allow_untrusted, is_update, pkg, error);
+ }
if (!ret)
goto out;
--
2.45.2

@ -0,0 +1,38 @@
From da3bb5fe0c7c72e1b837f41c92e86a7f790fe8a7 Mon Sep 17 00:00:00 2001
From: Sergey Cherevko <s.cherevko@msvsphere-os.ru>
Date: Wed, 18 Dec 2024 21:04:40 +0300
Subject: [PATCH] msvsphere bugtracker
---
docs/hawkey/conf.py | 2 +-
libdnf/conf/Const.hpp | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/hawkey/conf.py b/docs/hawkey/conf.py
index 93330c2..09d3b52 100644
--- a/docs/hawkey/conf.py
+++ b/docs/hawkey/conf.py
@@ -260,6 +260,6 @@ texinfo_documents = [
rst_prolog = """
.. default-domain:: py
.. _libsolv: https://github.com/openSUSE/libsolv
-.. _bugzilla: https://bugzilla.redhat.com/enter_bug.cgi?product=Fedora&component=hawkey
+.. _bugzilla: https://bugs.msvsphere-os.ru/
"""
diff --git a/libdnf/conf/Const.hpp b/libdnf/conf/Const.hpp
index ba21bbe..649a24b 100644
--- a/libdnf/conf/Const.hpp
+++ b/libdnf/conf/Const.hpp
@@ -41,7 +41,7 @@ const std::vector<std::string> INSTALLONLYPKGS{"kernel", "kernel-PAE",
"installonlypkg(vm)",
"multiversion(kernel)"};
-constexpr const char * BUGTRACKER="https://bugzilla.redhat.com/enter_bug.cgi?product=Fedora&component=dnf";
+constexpr const char * BUGTRACKER="https://bugs.msvsphere-os.ru/";
}
--
2.43.5

@ -1,316 +0,0 @@
From 659bc22f36c7bf21d86ceb298a1eaaccd5a2a880 Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Fri, 24 Mar 2023 13:22:41 +0100
Subject: [PATCH] Split modular packages to to repositories according their
origin
It will help to provide information about repository origin to libsolv
modular error messages.
---
libdnf/module/ModulePackageContainer.cpp | 42 ++++++++++++++----------
1 file changed, 24 insertions(+), 18 deletions(-)
diff --git a/libdnf/module/ModulePackageContainer.cpp b/libdnf/module/ModulePackageContainer.cpp
index ccfa249d..4879130f 100644
--- a/libdnf/module/ModulePackageContainer.cpp
+++ b/libdnf/module/ModulePackageContainer.cpp
@@ -286,13 +286,6 @@ ModulePackageContainer::ModulePackageContainer(bool allArch, std::string install
pImpl->persistDir = dir;
}
- Pool * pool = dnf_sack_get_pool(pImpl->moduleSack);
- HyRepo hrepo = hy_repo_create("available");
- auto repoImpl = libdnf::repoGetImpl(hrepo);
- LibsolvRepo *repo = repo_create(pool, "available");
- repo->appdata = hrepo;
- repoImpl->libsolvRepo = repo;
- repoImpl->needs_internalizing = 1;
pImpl->installRoot = installRoot;
g_autofree gchar * path = g_build_filename(pImpl->installRoot.c_str(),
"/etc/dnf/modules.d", NULL);
@@ -375,23 +368,36 @@ ModulePackageContainer::add(const std::string &fileContent, const std::string &
md.addMetadataFromString(fileContent, 0);
md.resolveAddedMetadata();
+ LibsolvRepo * repo = nullptr;
LibsolvRepo * r;
Id id;
+ // Search whether available repo was already created
FOR_REPOS(id, r) {
- if (strcmp(r->name, "available") == 0) {
- g_autofree gchar * path = g_build_filename(pImpl->installRoot.c_str(),
- "/etc/dnf/modules.d", NULL);
- auto packages = md.getAllModulePackages(pImpl->moduleSack, r, repoID, pImpl->modulesV2);
- for(auto const& modulePackagePtr: packages) {
- std::unique_ptr<ModulePackage> modulePackage(modulePackagePtr);
- pImpl->modules.insert(std::make_pair(modulePackage->getId(), std::move(modulePackage)));
- pImpl->persistor->insert(modulePackagePtr->getName(), path);
- }
-
- return;
+ if (strcmp(r->name, repoID.c_str()) == 0) {
+ repo = r;
}
}
+
+ // If not created yet, create it
+ if (!repo) {
+ Pool * pool = dnf_sack_get_pool(pImpl->moduleSack);
+ HyRepo hrepo = hy_repo_create(repoID.c_str());
+ auto repoImpl = libdnf::repoGetImpl(hrepo);
+ repo = repo_create(pool, repoID.c_str());
+ repo->appdata = hrepo;
+ repoImpl->libsolvRepo = repo;
+ repoImpl->needs_internalizing = 1;
+ }
+
+ // add all modules to repository and pass ownership to module container
+ g_autofree gchar * path = g_build_filename(pImpl->installRoot.c_str(), "/etc/dnf/modules.d", NULL);
+ auto packages = md.getAllModulePackages(pImpl->moduleSack, r, repoID, pImpl->modulesV2);
+ for(auto const& modulePackagePtr: packages) {
+ std::unique_ptr<ModulePackage> modulePackage(modulePackagePtr);
+ pImpl->modules.insert(std::make_pair(modulePackage->getId(), std::move(modulePackage)));
+ pImpl->persistor->insert(modulePackagePtr->getName(), path);
+ }
}
Id
--
2.40.1
From e86bc9082e226c7b784c820e9820537cd71afaa0 Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Tue, 21 Mar 2023 11:28:43 +0100
Subject: [PATCH] Add repoid to solver errors for RPMs (RhBug:2179413)
Repoid is very useful to find a source of the issue. It tells which
repositories contains problematic packages.
https://bugzilla.redhat.com/show_bug.cgi?id=2179413
---
libdnf/goal/Goal.cpp | 101 +++++++++++++----------
libdnf/module/ModulePackageContainer.cpp | 2 +-
tests/hawkey/test_goal.cpp | 14 ++--
3 files changed, 64 insertions(+), 53 deletions(-)
diff --git a/libdnf/goal/Goal.cpp b/libdnf/goal/Goal.cpp
index ebe2fbd1..7def8371 100644
--- a/libdnf/goal/Goal.cpp
+++ b/libdnf/goal/Goal.cpp
@@ -87,8 +87,8 @@ enum {RULE_DISTUPGRADE=1, RULE_INFARCH, RULE_UPDATE, RULE_JOB, RULE_JOB_UNSUPPOR
};
static const std::map<int, const char *> PKG_PROBLEMS_DICT = {
- {RULE_DISTUPGRADE, M_(" does not belong to a distupgrade repository")},
- {RULE_INFARCH, M_(" has inferior architecture")},
+ {RULE_DISTUPGRADE, M_("%s from %s does not belong to a distupgrade repository")},
+ {RULE_INFARCH, M_("%s from %s has inferior architecture")},
{RULE_UPDATE, M_("problem with installed package ")},
{RULE_JOB, M_("conflicting requests")},
{RULE_JOB_UNSUPPORTED, M_("unsupported request")},
@@ -98,24 +98,24 @@ static const std::map<int, const char *> PKG_PROBLEMS_DICT = {
{RULE_PKG, M_("some dependency problem")},
{RULE_BEST_1, M_("cannot install the best update candidate for package ")},
{RULE_BEST_2, M_("cannot install the best candidate for the job")},
- {RULE_PKG_NOT_INSTALLABLE_1, M_("package %s is filtered out by modular filtering")},
- {RULE_PKG_NOT_INSTALLABLE_2, M_("package %s does not have a compatible architecture")},
- {RULE_PKG_NOT_INSTALLABLE_3, M_("package %s is not installable")},
- {RULE_PKG_NOT_INSTALLABLE_4, M_("package %s is filtered out by exclude filtering")},
- {RULE_PKG_NOTHING_PROVIDES_DEP, M_("nothing provides %s needed by %s")},
- {RULE_PKG_SAME_NAME, M_("cannot install both %s and %s")},
- {RULE_PKG_CONFLICTS, M_("package %s conflicts with %s provided by %s")},
- {RULE_PKG_OBSOLETES, M_("package %s obsoletes %s provided by %s")},
- {RULE_PKG_INSTALLED_OBSOLETES, M_("installed package %s obsoletes %s provided by %s")},
- {RULE_PKG_IMPLICIT_OBSOLETES, M_("package %s implicitly obsoletes %s provided by %s")},
- {RULE_PKG_REQUIRES, M_("package %s requires %s, but none of the providers can be installed")},
- {RULE_PKG_SELF_CONFLICT, M_("package %s conflicts with %s provided by itself")},
- {RULE_YUMOBS, M_("both package %s and %s obsolete %s")}
+ {RULE_PKG_NOT_INSTALLABLE_1, M_("package %s from %s is filtered out by modular filtering")},
+ {RULE_PKG_NOT_INSTALLABLE_2, M_("package %s from %s does not have a compatible architecture")},
+ {RULE_PKG_NOT_INSTALLABLE_3, M_("package %s from %s is not installable")},
+ {RULE_PKG_NOT_INSTALLABLE_4, M_("package %s from %s is filtered out by exclude filtering")},
+ {RULE_PKG_NOTHING_PROVIDES_DEP, M_("nothing provides %s needed by %s from %s")},
+ {RULE_PKG_SAME_NAME, M_("cannot install both %s from %s and %s from %s")},
+ {RULE_PKG_CONFLICTS, M_("package %s from %s conflicts with %s provided by %s from %s")},
+ {RULE_PKG_OBSOLETES, M_("package %s from %s obsoletes %s provided by %s from %s")},
+ {RULE_PKG_INSTALLED_OBSOLETES, M_("installed package %s obsoletes %s provided by %s from %s")},
+ {RULE_PKG_IMPLICIT_OBSOLETES, M_("package %s from %s implicitly obsoletes %s provided by %s from %s")},
+ {RULE_PKG_REQUIRES, M_("package %s from %s requires %s, but none of the providers can be installed")},
+ {RULE_PKG_SELF_CONFLICT, M_("package %s from %s conflicts with %s provided by itself")},
+ {RULE_YUMOBS, M_("both package %s from %s and %s from %s obsolete %s")}
};
static const std::map<int, const char *> MODULE_PROBLEMS_DICT = {
- {RULE_DISTUPGRADE, M_(" does not belong to a distupgrade repository")},
- {RULE_INFARCH, M_(" has inferior architecture")},
+ {RULE_DISTUPGRADE, M_("%s from %s does not belong to a distupgrade repository")},
+ {RULE_INFARCH, M_("%s from %s has inferior architecture")},
{RULE_UPDATE, M_("problem with installed module ")},
{RULE_JOB, M_("conflicting requests")},
{RULE_JOB_UNSUPPORTED, M_("unsupported request")},
@@ -125,19 +125,19 @@ static const std::map<int, const char *> MODULE_PROBLEMS_DICT = {
{RULE_PKG, M_("some dependency problem")},
{RULE_BEST_1, M_("cannot install the best update candidate for module ")},
{RULE_BEST_2, M_("cannot install the best candidate for the job")},
- {RULE_PKG_NOT_INSTALLABLE_1, M_("module %s is disabled")},
- {RULE_PKG_NOT_INSTALLABLE_2, M_("module %s does not have a compatible architecture")},
- {RULE_PKG_NOT_INSTALLABLE_3, M_("module %s is not installable")},
- {RULE_PKG_NOT_INSTALLABLE_4, M_("module %s is disabled")},
- {RULE_PKG_NOTHING_PROVIDES_DEP, M_("nothing provides %s needed by module %s")},
- {RULE_PKG_SAME_NAME, M_("cannot install both modules %s and %s")},
- {RULE_PKG_CONFLICTS, M_("module %s conflicts with %s provided by %s")},
- {RULE_PKG_OBSOLETES, M_("module %s obsoletes %s provided by %s")},
- {RULE_PKG_INSTALLED_OBSOLETES, M_("installed module %s obsoletes %s provided by %s")},
- {RULE_PKG_IMPLICIT_OBSOLETES, M_("module %s implicitly obsoletes %s provided by %s")},
- {RULE_PKG_REQUIRES, M_("module %s requires %s, but none of the providers can be installed")},
- {RULE_PKG_SELF_CONFLICT, M_("module %s conflicts with %s provided by itself")},
- {RULE_YUMOBS, M_("both module %s and %s obsolete %s")}
+ {RULE_PKG_NOT_INSTALLABLE_1, M_("module %s from %s is disabled")},
+ {RULE_PKG_NOT_INSTALLABLE_2, M_("module %s from %s does not have a compatible architecture")},
+ {RULE_PKG_NOT_INSTALLABLE_3, M_("module %s from %s is not installable")},
+ {RULE_PKG_NOT_INSTALLABLE_4, M_("module %s from %s is disabled")},
+ {RULE_PKG_NOTHING_PROVIDES_DEP, M_("nothing provides %s needed by module %s from %s")},
+ {RULE_PKG_SAME_NAME, M_("cannot install both modules %s from %s and %s from %s")},
+ {RULE_PKG_CONFLICTS, M_("module %s from %s conflicts with %s provided by %s from %s")},
+ {RULE_PKG_OBSOLETES, M_("module %s from %s obsoletes %s provided by %s from %s")},
+ {RULE_PKG_INSTALLED_OBSOLETES, M_("installed module %s obsoletes %s provided by %s from %s")},
+ {RULE_PKG_IMPLICIT_OBSOLETES, M_("module %s from %s implicitly obsoletes %s provided by %s from %s")},
+ {RULE_PKG_REQUIRES, M_("module %s from %s requires %s, but none of the providers can be installed")},
+ {RULE_PKG_SELF_CONFLICT, M_("module %s from %s conflicts with %s provided by itself")},
+ {RULE_YUMOBS, M_("both module %s from %s and %s from %s obsolete %s")}
};
static std::string
@@ -151,9 +151,11 @@ libdnf_problemruleinfo2str(libdnf::PackageSet * modularExclude, Solver *solv, So
Solvable *ss;
switch (type) {
case SOLVER_RULE_DISTUPGRADE:
- return solvid2str(pool, source) + TM_(problemDict.at(RULE_DISTUPGRADE), 1);
+ return tfm::format(TM_(problemDict.at(RULE_DISTUPGRADE), 1), solvid2str(pool, source).c_str(),
+ pool_id2solvable(pool, source)->repo->name);
case SOLVER_RULE_INFARCH:
- return solvid2str(pool, source) + TM_(problemDict.at(RULE_INFARCH), 1);
+ return tfm::format(TM_(problemDict.at(RULE_DISTUPGRADE), 1), solvid2str(pool, source).c_str(),
+ pool_id2solvable(pool, source)->repo->name);
case SOLVER_RULE_UPDATE:
return std::string(TM_(problemDict.at(RULE_UPDATE), 1)) + solvid2str(pool, source);
case SOLVER_RULE_JOB:
@@ -176,44 +178,53 @@ libdnf_problemruleinfo2str(libdnf::PackageSet * modularExclude, Solver *solv, So
ss = pool->solvables + source;
if (pool_disabled_solvable(pool, ss)) {
if (modularExclude && modularExclude->has(source)) {
- return tfm::format(TM_(problemDict.at(RULE_PKG_NOT_INSTALLABLE_1), 1), solvid2str(pool, source).c_str());
+ return tfm::format(TM_(problemDict.at(RULE_PKG_NOT_INSTALLABLE_1), 1),
+ solvid2str(pool, source).c_str(), pool_id2solvable(pool, source)->repo->name);
} else {
- return tfm::format(TM_(problemDict.at(RULE_PKG_NOT_INSTALLABLE_4), 1), solvid2str(pool, source).c_str());
+ return tfm::format(TM_(problemDict.at(RULE_PKG_NOT_INSTALLABLE_4), 1),
+ solvid2str(pool, source).c_str(), pool_id2solvable(pool, source)->repo->name);
}
}
if (ss->arch && ss->arch != ARCH_SRC && ss->arch != ARCH_NOSRC &&
pool->id2arch && (ss->arch > pool->lastarch || !pool->id2arch[ss->arch]))
- return tfm::format(TM_(problemDict.at(RULE_PKG_NOT_INSTALLABLE_2), 1), solvid2str(pool, source).c_str());
- return tfm::format(TM_(problemDict.at(RULE_PKG_NOT_INSTALLABLE_3), 1), solvid2str(pool, source).c_str());
+ return tfm::format(TM_(problemDict.at(RULE_PKG_NOT_INSTALLABLE_2), 1), solvid2str(pool, source).c_str(),
+ pool_id2solvable(pool, source)->repo->name);
+ return tfm::format(TM_(problemDict.at(RULE_PKG_NOT_INSTALLABLE_3), 1), solvid2str(pool, source).c_str(),
+ pool_id2solvable(pool, source)->repo->name);
case SOLVER_RULE_PKG_NOTHING_PROVIDES_DEP:
return tfm::format(TM_(problemDict.at(RULE_PKG_NOTHING_PROVIDES_DEP), 1), pool_dep2str(pool, dep),
- solvid2str(pool, source).c_str());
+ solvid2str(pool, source).c_str(), pool_id2solvable(pool, source)->repo->name);
case SOLVER_RULE_PKG_SAME_NAME:
return tfm::format(TM_(problemDict.at(RULE_PKG_SAME_NAME), 1), solvid2str(pool, source).c_str(),
- solvid2str(pool, target).c_str());
+ pool_id2solvable(pool, source)->repo->name, solvid2str(pool, target).c_str(),
+ pool_id2solvable(pool, target)->repo->name);
case SOLVER_RULE_PKG_CONFLICTS:
return tfm::format(TM_(problemDict.at(RULE_PKG_CONFLICTS), 1), solvid2str(pool, source).c_str(),
- pool_dep2str(pool, dep), solvid2str(pool, target).c_str());
+ pool_id2solvable(pool, source)->repo->name, pool_dep2str(pool, dep),
+ solvid2str(pool, target).c_str(), pool_id2solvable(pool, target)->repo->name);
case SOLVER_RULE_PKG_OBSOLETES:
return tfm::format(TM_(problemDict.at(RULE_PKG_OBSOLETES), 1), solvid2str(pool, source).c_str(),
- pool_dep2str(pool, dep), solvid2str(pool, target).c_str());
+ pool_id2solvable(pool, source)->repo->name, pool_dep2str(pool, dep),
+ solvid2str(pool, target).c_str(), pool_id2solvable(pool, target)->repo->name);
case SOLVER_RULE_PKG_INSTALLED_OBSOLETES:
return tfm::format(TM_(problemDict.at(RULE_PKG_INSTALLED_OBSOLETES), 1),
solvid2str(pool, source).c_str(), pool_dep2str(pool, dep),
- solvid2str(pool, target).c_str());
+ solvid2str(pool, target).c_str(), pool_id2solvable(pool, target)->repo->name);
case SOLVER_RULE_PKG_IMPLICIT_OBSOLETES:
return tfm::format(TM_(problemDict.at(RULE_PKG_IMPLICIT_OBSOLETES), 1),
solvid2str(pool, source).c_str(), pool_dep2str(pool, dep),
- solvid2str(pool, target).c_str());
+ pool_id2solvable(pool, source)->repo->name, solvid2str(pool, target).c_str(),
+ pool_id2solvable(pool, target)->repo->name);
case SOLVER_RULE_PKG_REQUIRES:
return tfm::format(TM_(problemDict.at(RULE_PKG_REQUIRES), 1), solvid2str(pool, source).c_str(),
- pool_dep2str(pool, dep));
+ pool_id2solvable(pool, source)->repo->name, pool_dep2str(pool, dep));
case SOLVER_RULE_PKG_SELF_CONFLICT:
return tfm::format(TM_(problemDict.at(RULE_PKG_SELF_CONFLICT), 1), solvid2str(pool, source).c_str(),
- pool_dep2str(pool, dep));
+ pool_id2solvable(pool, source)->repo->name, pool_dep2str(pool, dep));
case SOLVER_RULE_YUMOBS:
return tfm::format(TM_(problemDict.at(RULE_YUMOBS), 1), solvid2str(pool, source).c_str(),
- solvid2str(pool, target).c_str(), pool_dep2str(pool, dep));
+ pool_id2solvable(pool, source)->repo->name, solvid2str(pool, target).c_str(),
+ pool_id2solvable(pool, target)->repo->name, pool_dep2str(pool, dep));
default:
return solver_problemruleinfo2str(solv, type, source, target, dep);
}
diff --git a/libdnf/module/ModulePackageContainer.cpp b/libdnf/module/ModulePackageContainer.cpp
index 4879130f..e4140748 100644
--- a/libdnf/module/ModulePackageContainer.cpp
+++ b/libdnf/module/ModulePackageContainer.cpp
@@ -392,7 +392,7 @@ ModulePackageContainer::add(const std::string &fileContent, const std::string &
// add all modules to repository and pass ownership to module container
g_autofree gchar * path = g_build_filename(pImpl->installRoot.c_str(), "/etc/dnf/modules.d", NULL);
- auto packages = md.getAllModulePackages(pImpl->moduleSack, r, repoID, pImpl->modulesV2);
+ auto packages = md.getAllModulePackages(pImpl->moduleSack, repo, repoID, pImpl->modulesV2);
for(auto const& modulePackagePtr: packages) {
std::unique_ptr<ModulePackage> modulePackage(modulePackagePtr);
pImpl->modules.insert(std::make_pair(modulePackage->getId(), std::move(modulePackage)));
diff --git a/tests/hawkey/test_goal.cpp b/tests/hawkey/test_goal.cpp
index f22e1c80..b2d7af9f 100644
--- a/tests/hawkey/test_goal.cpp
+++ b/tests/hawkey/test_goal.cpp
@@ -593,11 +593,11 @@ START_TEST(test_goal_describe_problem_rules)
auto problems = goal->describeProblemRules(0, true);
const char *expected[] = {
"conflicting requests",
- "nothing provides goodbye needed by hello-1-1.noarch"
+ "nothing provides goodbye needed by hello-1-1.noarch from main"
};
- fail_unless(problems.size() == 2);
- fail_unless(problems[0] == expected[0]);
- fail_unless(problems[1] == expected[1]);
+ ck_assert_int_eq(problems.size(), 2);
+ ck_assert_str_eq(problems[0].c_str(), expected[0]);
+ ck_assert_str_eq(problems[1].c_str(), expected[1]);
g_object_unref(pkg);
hy_goal_free(goal);
@@ -860,10 +860,10 @@ START_TEST(test_goal_lock)
auto problems = goal->describeProblemRules(0, true);
const char *expected[] = {
- "package bloop-ext-2.0-1.noarch requires bloop = 2.0-1, but none of the providers can be installed",
- "cannot install both bloop-2.0-1.noarch and bloop-1.0-1.noarch",
+ "package bloop-ext-2.0-1.noarch from updates requires bloop = 2.0-1, but none of the providers can be installed",
+ "cannot install both bloop-2.0-1.noarch from updates and bloop-1.0-1.noarch from @System",
"conflicting requests",
- "package bloop-ext-1.0-1.noarch is filtered out by exclude filtering"
+ "package bloop-ext-1.0-1.noarch from updates is filtered out by exclude filtering"
};
ck_assert_int_eq(problems.size(), 4);
ck_assert_str_eq(problems[0].c_str(), expected[0]);
--
2.40.1

@ -0,0 +1,78 @@
From bc371683ab69d51127952b037bde209a56e44105 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Fri, 3 May 2024 08:55:47 +0200
Subject: [PATCH] Since we use rpmtsAddReinstallElement rpm also uninstalls the
package
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
It calls callbacks for `RPMCALLBACK_INST_START` and
`RPMCALLBACK_INST_PROGRESS` just like before when the reinstall was done
through regural install (rpmtsAddInstallElement) but in addition it also
calls `RPMCALLBACK_UNINST_START` and `RPMCALLBACK_UNINST_PROGRESS`. To
ensure they find the `DnfPackage` add it to `remove_helper` array.
Unfortunaly this means that the reinstall action is reported twice to
the clients (one install and one uninstall). We could try to hide one of
the them but I think a better solution is to report what is actually
happening and report one install and one uninstall.
This is for the context part of libdnf (microdnf, packagekit, ...)
Fixes: https://github.com/rpm-software-management/libdnf/issues/1653
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
libdnf/dnf-transaction.cpp | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/libdnf/dnf-transaction.cpp b/libdnf/dnf-transaction.cpp
index 35b2ff95..fcb1152f 100644
--- a/libdnf/dnf-transaction.cpp
+++ b/libdnf/dnf-transaction.cpp
@@ -602,7 +602,7 @@ dnf_transaction_ts_progress_cb(const void *arg,
/* map to correct action code */
action = dnf_package_get_action(pkg);
- if (action == DNF_STATE_ACTION_UNKNOWN)
+ if (action == DNF_STATE_ACTION_UNKNOWN || action == DNF_STATE_ACTION_REINSTALL)
action = DNF_STATE_ACTION_INSTALL;
/* set the pkgid if not already set */
@@ -641,7 +641,7 @@ dnf_transaction_ts_progress_cb(const void *arg,
/* map to correct action code */
action = dnf_package_get_action(pkg);
- if (action == DNF_STATE_ACTION_UNKNOWN)
+ if (action == DNF_STATE_ACTION_UNKNOWN || action == DNF_STATE_ACTION_REINSTALL)
action = DNF_STATE_ACTION_REMOVE;
/* remove start */
@@ -716,7 +716,7 @@ dnf_transaction_ts_progress_cb(const void *arg,
/* map to correct action code */
action = dnf_package_get_action(pkg);
- if (action == DNF_STATE_ACTION_UNKNOWN)
+ if (action == DNF_STATE_ACTION_UNKNOWN || action == DNF_STATE_ACTION_REINSTALL)
action = DNF_STATE_ACTION_REMOVE;
dnf_state_set_package_progress(
@@ -1354,6 +1354,15 @@ dnf_transaction_commit(DnfTransaction *transaction, HyGoal goal, DnfState *state
g_ptr_array_unref(pkglist);
}
+ /* add reinstalled packages to a helper array which is used to
+ * map removed packages auto-added by rpm to actual DnfPackage's */
+ pkglist = dnf_goal_get_packages(goal, DNF_PACKAGE_INFO_REINSTALL, -1);
+ for (i = 0; i < pkglist->len; i++) {
+ pkg_tmp = static_cast< DnfPackage * >(g_ptr_array_index(pkglist, i));
+ g_ptr_array_add(priv->remove_helper, g_object_ref(pkg_tmp));
+ }
+ g_ptr_array_unref(pkglist);
+
/* this section done */
ret = dnf_state_done(state, error);
if (!ret)
--
2.45.2

@ -0,0 +1,91 @@
From 90d2ffad964a91a7a798b81e15c16eb1e840f257 Mon Sep 17 00:00:00 2001
From: Jan Kolarik <jkolarik@redhat.com>
Date: Tue, 23 Apr 2024 14:11:19 +0000
Subject: [PATCH] MergedTransaction: Fix invalid memory access when dropping
items
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
When an item is dropped from the merged transaction, the `ItemPair` reference becomes invalid and should no longer be used.
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
libdnf/transaction/MergedTransaction.cpp | 18 +++++++++++-------
libdnf/transaction/MergedTransaction.hpp | 2 +-
2 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/libdnf/transaction/MergedTransaction.cpp b/libdnf/transaction/MergedTransaction.cpp
index 8f26882f..75d2c1e7 100644
--- a/libdnf/transaction/MergedTransaction.cpp
+++ b/libdnf/transaction/MergedTransaction.cpp
@@ -264,14 +264,15 @@ getItemIdentifier(ItemPtr item)
/**
* Resolve the difference between RPMs in the first and second transaction item
- * and create a ItemPair of Upgrade, Downgrade or drop the item from the merged
- * transaction set in case of both packages are of the same version.
- * Method is called when original package is being removed and than installed again.
+ * and create a ItemPair of Upgrade, Downgrade or remove the item from the merged
+ * transaction set in case of both packages are the same.
+ * Method is called when original package is being removed and then installed again.
* \param itemPairMap merged transaction set
* \param previousItemPair original item pair
* \param mTransItem new transaction item
+ * \return true if the original and new transaction item differ
*/
-void
+bool
MergedTransaction::resolveRPMDifference(ItemPairMap &itemPairMap,
ItemPair &previousItemPair,
TransactionItemBasePtr mTransItem)
@@ -287,7 +288,7 @@ MergedTransaction::resolveRPMDifference(ItemPairMap &itemPairMap,
firstRPM->getRelease() == secondRPM->getRelease()) {
// Drop the item from merged transaction
itemPairMap.erase(getItemIdentifier(firstItem));
- return;
+ return false;
} else if ((*firstRPM) < (*secondRPM)) {
// Upgrade to secondRPM
previousItemPair.first->setAction(TransactionItemAction::UPGRADED);
@@ -298,6 +299,7 @@ MergedTransaction::resolveRPMDifference(ItemPairMap &itemPairMap,
mTransItem->setAction(TransactionItemAction::DOWNGRADE);
}
previousItemPair.second = mTransItem;
+ return true;
}
void
@@ -308,12 +310,14 @@ MergedTransaction::resolveErase(ItemPairMap &itemPairMap,
/*
* The original item has been removed - it has to be installed now unless the rpmdb
* has changed. Resolve the difference between packages and mark it as Upgrade,
- * Reinstall or Downgrade
+ * Downgrade or remove it from the transaction
*/
if (mTransItem->getAction() == TransactionItemAction::INSTALL) {
if (mTransItem->getItem()->getItemType() == ItemType::RPM) {
// resolve the difference between RPM packages
- resolveRPMDifference(itemPairMap, previousItemPair, mTransItem);
+ if (!resolveRPMDifference(itemPairMap, previousItemPair, mTransItem)) {
+ return;
+ }
} else {
// difference between comps can't be resolved
mTransItem->setAction(TransactionItemAction::REINSTALL);
diff --git a/libdnf/transaction/MergedTransaction.hpp b/libdnf/transaction/MergedTransaction.hpp
index f85b133a..50212159 100644
--- a/libdnf/transaction/MergedTransaction.hpp
+++ b/libdnf/transaction/MergedTransaction.hpp
@@ -76,7 +76,7 @@ protected:
typedef std::map< std::string, ItemPair > ItemPairMap;
void mergeItem(ItemPairMap &itemPairMap, TransactionItemBasePtr transItem);
- void resolveRPMDifference(ItemPairMap &itemPairMap, ItemPair &previousItemPair, TransactionItemBasePtr mTransItem);
+ bool resolveRPMDifference(ItemPairMap &itemPairMap, ItemPair &previousItemPair, TransactionItemBasePtr mTransItem);
void resolveErase(ItemPairMap &itemPairMap, ItemPair &previousItemPair, TransactionItemBasePtr mTransItem);
void resolveAltered(ItemPairMap &itemPairMap, ItemPair &previousItemPair, TransactionItemBasePtr mTransItem);
};
--
2.45.2

File diff suppressed because it is too large Load Diff

@ -0,0 +1,40 @@
From a6d89d66698f75c01539cd03c04a87ab52b6db7c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Tue, 25 Jun 2024 13:38:14 +0200
Subject: [PATCH] Set pool flag to fix pool_addfileprovides_queue() without
filelists.xml
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Since dnf4 now also conditionally load filelists it ran into the same
problem as dnf5 here: https://github.com/rpm-software-management/dnf5/issues/520
Additional details in: https://github.com/openSUSE/libsolv/pull/531
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
libdnf/dnf-sack.cpp | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/libdnf/dnf-sack.cpp b/libdnf/dnf-sack.cpp
index 3c3a7657..e95009fb 100644
--- a/libdnf/dnf-sack.cpp
+++ b/libdnf/dnf-sack.cpp
@@ -185,6 +185,13 @@ dnf_sack_init(DnfSack *sack)
DnfSackPrivate *priv = GET_PRIVATE(sack);
priv->pool = pool_create();
pool_set_flag(priv->pool, POOL_FLAG_WHATPROVIDESWITHDISABLED, 1);
+
+ // Configures the pool_addfileprovides_queue() method to only add files from primary.xml.
+ // This ensures the method works correctly even if filelist.xml metadata are not loaded.
+ // At the same time when filelist.xml are loaded libsolv is able to search them for required
+ // files if needed.
+ pool_set_flag(priv->pool, POOL_FLAG_ADDFILEPROVIDESFILTERED, 1);
+
priv->running_kernel_id = -1;
priv->running_kernel_fn = running_kernel;
priv->considered_uptodate = TRUE;
--
2.45.2

File diff suppressed because it is too large Load Diff

@ -0,0 +1,128 @@
From 1f6c2479260e2d26a861b871c443a5b960523a71 Mon Sep 17 00:00:00 2001
From: Evan Goode <mail@evangoo.de>
Date: Tue, 7 May 2024 16:33:03 +0000
Subject: [PATCH] ConfigParser: fix use-out-of-scope leaks
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
libdnf/conf/ConfigParser.cpp | 48 ++++++++++++++++++++++++------------
1 file changed, 32 insertions(+), 16 deletions(-)
diff --git a/libdnf/conf/ConfigParser.cpp b/libdnf/conf/ConfigParser.cpp
index 76e7f9cc..977da757 100644
--- a/libdnf/conf/ConfigParser.cpp
+++ b/libdnf/conf/ConfigParser.cpp
@@ -95,7 +95,9 @@ std::pair<std::string, size_t> ConfigParser::substitute_expression(const std::st
const auto & variable_key = res.substr(pos_variable, pos_after_variable - pos_variable);
const auto variable_mapping = substitutions.find(variable_key);
- const std::string * variable_value = nullptr;
+ // No std::optional here.
+ bool variable_value_has_value{false};
+ std::string variable_value{""};
if (variable_mapping == substitutions.end()) {
if (variable_key == "releasever_major" || variable_key == "releasever_minor") {
@@ -103,17 +105,22 @@ std::pair<std::string, size_t> ConfigParser::substitute_expression(const std::st
if (releasever_mapping != substitutions.end()) {
const auto & releasever_split = ConfigParser::split_releasever(releasever_mapping->second);
if (variable_key == "releasever_major") {
- variable_value = &std::get<0>(releasever_split);
+ variable_value = std::get<0>(releasever_split);
+ variable_value_has_value = true;
} else {
- variable_value = &std::get<1>(releasever_split);
+ variable_value = std::get<1>(releasever_split);
+ variable_value_has_value = true;
}
}
}
} else {
- variable_value = &variable_mapping->second;
+ variable_value = variable_mapping->second;
+ variable_value_has_value = true;
}
- const std::string * subst_str = nullptr;
+ // No std::optional here
+ std::string subst_str{""};
+ bool subst_str_has_value{false};
size_t pos_after_variable_expression;
@@ -153,20 +160,23 @@ std::pair<std::string, size_t> ConfigParser::substitute_expression(const std::st
// If variable is unset or empty, the expansion of word is
// substituted. Otherwise, the value of variable is
// substituted.
- if (variable_value == nullptr || variable_value->empty()) {
- subst_str = &expanded_word;
+ if (!variable_value_has_value || variable_value.empty()) {
+ subst_str = expanded_word;
+ subst_str_has_value = true;
} else {
subst_str = variable_value;
+ subst_str_has_value = true;
}
} else if (expansion_mode == '+') {
// ${variable:+word} (alternate value)
// If variable is unset or empty nothing is substituted.
// Otherwise, the expansion of word is substituted.
- if (variable_value == nullptr || variable_value->empty()) {
- const std::string empty{};
- subst_str = &empty;
+ if (!variable_value_has_value || variable_value.empty()) {
+ subst_str = "";
+ subst_str_has_value = true;
} else {
- subst_str = &expanded_word;
+ subst_str = expanded_word;
+ subst_str_has_value = true;
}
} else {
// Unknown expansion mode, continue after the ':'
@@ -176,7 +186,10 @@ std::pair<std::string, size_t> ConfigParser::substitute_expression(const std::st
pos_after_variable_expression = pos_after_word + 1;
} else if (res[pos_after_variable] == '}') {
// ${variable}
- subst_str = variable_value;
+ if (variable_value_has_value) {
+ subst_str = variable_value;
+ subst_str_has_value = true;
+ }
// Move past the closing '}'
pos_after_variable_expression = pos_after_variable + 1;
} else {
@@ -186,20 +199,23 @@ std::pair<std::string, size_t> ConfigParser::substitute_expression(const std::st
}
} else {
// No braces, we have a $variable
- subst_str = variable_value;
+ if (variable_value_has_value) {
+ subst_str = variable_value;
+ subst_str_has_value = true;
+ }
pos_after_variable_expression = pos_after_variable;
}
// If there is no substitution to make, move past the variable expression and continue.
- if (subst_str == nullptr) {
+ if (!subst_str_has_value) {
total_scanned += pos_after_variable_expression - pos;
pos = pos_after_variable_expression;
continue;
}
- res.replace(pos, pos_after_variable_expression - pos, *subst_str);
+ res.replace(pos, pos_after_variable_expression - pos, subst_str);
total_scanned += pos_after_variable_expression - pos;
- pos += subst_str->length();
+ pos += subst_str.length();
} else {
total_scanned += 1;
pos += 1;
--
2.45.2

@ -1,37 +0,0 @@
From ccd66a3cb4ddb7a0f0d914ee06eed58121dbe7ce Mon Sep 17 00:00:00 2001
From: Aleš Matěj <amatej@redhat.com>
Date: Tue, 27 Jun 2023 07:24:28 +0200
Subject: [PATCH] filterAdvisory: match installed_solvables sort with lower_bound (RhBug:2212838)
`std::lower_bound` expects that the range it operates on is sorted by
the provided comparator.
`lower_bound()` is used on `installed_solvables` twice, first with
comparator `NameSolvableComparator` and later with
`SolvableCompareAdvisoryPkgNameArch` to cover both we need to sort
`installed_solvables` by name and arch.
Otherwise this can lead to problems if multiple architectures of a pkg
are installed.
For: https://bugzilla.redhat.com/show_bug.cgi?id=2212838
---
libdnf/sack/query.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libdnf/sack/query.cpp b/libdnf/sack/query.cpp
index b7b1560..7937770 100644
--- a/libdnf/sack/query.cpp
+++ b/libdnf/sack/query.cpp
@@ -1903,7 +1903,7 @@ Query::Impl::filterAdvisory(const Filter & f, Map *m, int keyname)
while ((installed_id = installed.pImpl->result->next(installed_id)) != -1) {
installed_solvables.push_back(pool_id2solvable(pool, installed_id));
}
- std::sort(installed_solvables.begin(), installed_solvables.end(), NameSolvableComparator);
+ std::sort(installed_solvables.begin(), installed_solvables.end(), NameArchSolvableComparator);
Query obsoletes(sack, ExcludeFlags::IGNORE_EXCLUDES);
obsoletes.addFilter(HY_PKG, HY_EQ, resultPset);
--
libgit2 1.6.4

@ -0,0 +1,42 @@
From 18f49a49be14f80233613710e84dda47c5958252 Mon Sep 17 00:00:00 2001
From: Evan Goode <mail@evangoo.de>
Date: Tue, 7 May 2024 16:28:59 +0000
Subject: [PATCH] Add tests for shell-style variable expansion
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
tests/libdnf/conf/ConfigParserTest.cpp | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/tests/libdnf/conf/ConfigParserTest.cpp b/tests/libdnf/conf/ConfigParserTest.cpp
index 70278196..1448d8d3 100644
--- a/tests/libdnf/conf/ConfigParserTest.cpp
+++ b/tests/libdnf/conf/ConfigParserTest.cpp
@@ -30,4 +30,21 @@ void ConfigParserTest::testConfigParserReleasever()
libdnf::ConfigParser::substitute(text, substitutions);
CPPUNIT_ASSERT(text == "major: , minor: ");
}
+ {
+ std::map<std::string, std::string> substitutions = {
+ {"var1", "value123"},
+ {"var2", "456"},
+ };
+ std::string text = "foo$var1-bar";
+ libdnf::ConfigParser::substitute(text, substitutions);
+ CPPUNIT_ASSERT(text == "foovalue123-bar");
+
+ text = "${var1:+alternate}-${unset:-default}-${nn:+n${nn:-${nnn:}";
+ libdnf::ConfigParser::substitute(text, substitutions);
+ CPPUNIT_ASSERT(text == "alternate-default-${nn:+n${nn:-${nnn:}");
+
+ text = "${unset:-${var1:+${var2:+$var2}}}";
+ libdnf::ConfigParser::substitute(text, substitutions);
+ CPPUNIT_ASSERT(text == "456");
+ }
}
--
2.45.2

@ -1,84 +0,0 @@
From dadfe65ce753ba8a8bdb5e38d7929135526edbd5 Mon Sep 17 00:00:00 2001
From: Marek Blaha <mblaha@redhat.com>
Date: Thu, 31 Aug 2023 13:18:03 +0200
Subject: [PATCH] hawkey.subject: get_best_selectors only obsoleters of latest
In situation where a package exists in multiple versions and some older
version is being obsoleted, any of obsoleters was considered a valid
solution.
The result could be really misleading. For example let's have this package set:
systemd-udev-1.0
systemd-udev-2.0
Obsoletes: systemd-udev < 2
systemd-boot-unsigned-2.0
Obsoletes: systemd-udev < 2
In this case `dnf install systemd-udev` may lead to installation of
systemd-boot-unsigned which is probably not what the user expected. The
reason is the split in the upgrade-path created by obsolete and both
branches - systemd-udev-2.0 and systemd-boot-unsigned-2.0 are considered
valid.
With this patch install command takes into account only obsoleters of
the best version of the package so the `dnf install systemd-udev`
results in correct installation of systemd-udev-2.0 package.
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2183279
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2176263
---
python/hawkey/__init__.py | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/python/hawkey/__init__.py b/python/hawkey/__init__.py
index 45bdc3a..1ec1ef4 100644
--- a/python/hawkey/__init__.py
+++ b/python/hawkey/__init__.py
@@ -291,13 +291,13 @@ class Subject(_hawkey.Subject):
# after movement of base.install() or base.distro_sync()
return []
+ installed_query = q.installed()
if not self._filename_pattern and is_glob_pattern(self.pattern) \
or solution['nevra'] and solution['nevra'].name is None:
with_obsoletes = False
if obsoletes and solution['nevra'] and solution['nevra'].has_just_name():
with_obsoletes = True
- installed_query = q.installed()
if reponame:
q = q.filter(reponame=reponame)
available_query = q.available()
@@ -309,13 +309,24 @@ class Subject(_hawkey.Subject):
sltrs = []
for name, pkgs_list in q._name_dict().items():
if with_obsoletes:
+ # If there is no installed package in the pkgs_list, add only
+ # obsoleters of the latest versions. Otherwise behave consistently
+ # with upgrade and add all obsoleters.
+ # See https://bugzilla.redhat.com/show_bug.cgi?id=2176263
+ # for details of the problem.
+ obsoletes_query = base.sack.query().filterm(pkg=pkgs_list)
+ if not obsoletes_query.installed():
+ obsoletes_query.filterm(latest_per_arch_by_priority=True)
pkgs_list = pkgs_list + base.sack.query().filter(
- obsoletes=pkgs_list).run()
+ obsoletes=obsoletes_query).run()
sltrs.append(self._list_or_query_to_selector(base.sack, pkgs_list))
return sltrs
else:
if obsoletes and solution['nevra'] and solution['nevra'].has_just_name():
- q = q.union(base.sack.query().filter(obsoletes=q))
+ if installed_query:
+ q = q.union(base.sack.query().filter(obsoletes=q))
+ else:
+ q = q.union(base.sack.query().filter(obsoletes=q.filter(latest_per_arch_by_priority=True)))
installed_query = q.installed()
if reports:
--
libgit2 1.6.4

@ -1,99 +0,0 @@
From 2ffe58595baa2a51700a1210b1d3a2124f805756 Mon Sep 17 00:00:00 2001
From: Aleš Matěj <amatej@redhat.com>
Date: Mon, 25 Sep 2023 08:24:40 +0200
Subject: [PATCH] Avoid reinstalling installonly packages marked for ERASE
Without this patch reinstalling installonly pkg marked for ERASE might
be a valid smallest solution to our job.
For example when user wants to install through a provide we select all
packages that provide it and put them inside a `job install oneof ...`
if one of the providers is also marked for ERASE due to installonly
limit libsolv might decide to reinstall it.
To make sure it doesn't happen mark the available package also as ERASE.
https://github.com/openSUSE/libsolv/issues/540
https://issues.redhat.com/browse/RHEL-1253
(https://bugzilla.redhat.com/show_bug.cgi?id=2163474)
---
libdnf/goal/Goal.cpp | 35 +++++++++++++++++++++++++++++++++--
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/libdnf/goal/Goal.cpp b/libdnf/goal/Goal.cpp
index 7def837..ba938e1 100644
--- a/libdnf/goal/Goal.cpp
+++ b/libdnf/goal/Goal.cpp
@@ -643,6 +643,12 @@ erase_flags2libsolv(int flags)
return ret;
}
+static bool
+NameSolvableComparator(const Solvable * first, const Solvable * second)
+{
+ return first->name < second->name;
+}
+
Goal::Goal(const Goal & goal_src) : pImpl(new Impl(*goal_src.pImpl)) {}
Goal::Impl::Impl(const Goal::Impl & goal_src)
@@ -1436,10 +1442,24 @@ Goal::Impl::limitInstallonlyPackages(Solver *solv, Queue *job)
for (int i = 0; i < onlies->count; ++i) {
Id p, pp;
IdQueue q, installing;
+ std::vector<Solvable *> available_unused_providers;
+ // Add all providers of installonly provides that are marked for install
+ // to `q` IdQueue those that are not marked for install and are not already
+ // installed are added to available_unused_providers.
FOR_PKG_PROVIDES(p, pp, onlies->elements[i])
- if (solver_get_decisionlevel(solv, p) > 0)
+ // According to libsolv-bindings the decision level is positive for installs
+ // and negative for conflicts (conflicts with another package or dependency
+ // conflicts = dependencies cannot be met).
+ if (solver_get_decisionlevel(solv, p) > 0) {
q.pushBack(p);
+ } else {
+ Solvable *s = pool_id2solvable(pool, p);
+ if (s->repo != pool->installed) {
+ available_unused_providers.push_back(s);
+ }
+ }
+
if (q.size() <= (int) dnf_sack_get_installonly_limit(sack)) {
continue;
}
@@ -1457,17 +1477,28 @@ Goal::Impl::limitInstallonlyPackages(Solver *solv, Queue *job)
struct InstallonliesSortCallback s_cb = {pool, dnf_sack_running_kernel(sack)};
solv_sort(q.data(), q.size(), sizeof(q[0]), sort_packages, &s_cb);
+ std::sort(available_unused_providers.begin(), available_unused_providers.end(), NameSolvableComparator);
IdQueue same_names;
while (q.size() > 0) {
same_name_subqueue(pool, q.getQueue(), same_names.getQueue());
if (same_names.size() <= (int) dnf_sack_get_installonly_limit(sack))
continue;
reresolve = 1;
for (int j = 0; j < same_names.size(); ++j) {
Id id = same_names[j];
Id action = SOLVER_ERASE;
- if (j < (int) dnf_sack_get_installonly_limit(sack))
+ if (j < (int) dnf_sack_get_installonly_limit(sack)) {
action = SOLVER_INSTALL;
+ } else {
+ // We want to avoid reinstalling packages marked for ERASE, therefore
+ // if some unused provider is also available we need to mark it ERASE as well.
+ Solvable *s = pool_id2solvable(pool, id);
+ auto low = std::lower_bound(available_unused_providers.begin(), available_unused_providers.end(), s, NameSolvableComparator);
+ while (low != available_unused_providers.end() && (*low)->name == s->name) {
+ queue_push2(job, SOLVER_ERASE | SOLVER_SOLVABLE, pool_solvable2id(pool, *low));
+ ++low;
+ }
+ }
queue_push2(job, action | SOLVER_SOLVABLE, id);
}
}
--
libgit2 1.6.4

@ -1,338 +0,0 @@
From 7529d06dbe7ac4c1cb41a4fb8e32e3b96be72075 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
Date: Wed, 4 Oct 2023 16:38:12 +0200
Subject: [PATCH] PGP: Set a default creation SELinux labels on GnuPG
directories
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
libdnf used to precreate the directory in /run/user to make sure
a GnuPG agent executed by GPGME library places its socket there.
The directories there are normally created and removed by systemd
(logind PAM session). libdnf created them for a case when a package
manager is invoked out of systemd session, before the super user logs
in. E.g. by a timer job to cache repository metadata.
A problem was when this out-of-session process was a SELinux-confined
process creating files with its own SELinux label different from a DNF
program. Then the directory was created with a SELinux label different
from the one expected by systemd and when logging out a corresponding
user, the mismatching label clashed with systemd.
The same issue was with temporary GnuPG home directories created by
libdnf under /tmp.
This patch fixes both the isseus by restoring a SELinux label of those
directories to the label defined in a default SELinux file context
database.
Obviously the database cannot have a record for a nonspecific
/tmp/tmpdir.XXXXXX (a mkdtemp() template) directory names. Therefore
I changed their names to more specific /tmp/libdnf.XXXXXX. Once
a SELinux policy updates the database, directories under /tmp will get
a correct label.
There is yet another problem with accessing /var/cache/dnf/*/pubring,
but that seems to be pure SELinux policy problem.
This patch adds a new -DENABLE_SELINUX=OFF CMake option to disable the
new dependency on libselinux. A default behavior is to support SELinux.
Implementation details:
I used selabel_lookup() + setfscreatecon() + mkdtemp()
+ setfscreatecon() sequence instead of mkdtemp()
+ selinux_restorecon() sequence because the later polutes stderr if
a SELinux policy does not define the default context. One could
supress stderr messages with selinux_set_callback(), but its effect
cannot be restored.
I also kept the sequence in one function and reused it for creating
/run/user/$PID directories because the code is simpler than spliting
the function into three parts.
https://issues.redhat.com/browse/RHEL-6421
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
CMakeLists.txt | 7 +++
libdnf.spec | 11 +++-
libdnf/CMakeLists.txt | 4 ++
libdnf/repo/Repo.cpp | 124 ++++++++++++++++++++++++++++++++++++++----
4 files changed, 132 insertions(+), 14 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 405dc4e8..cc550ddb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -35,6 +35,7 @@ option(WITH_ZCHUNK "Build with zchunk support" ON)
option(ENABLE_RHSM_SUPPORT "Build with Red Hat Subscription Manager support?" OFF)
option(ENABLE_SOLV_URPMREORDER "Build with support for URPM-like solution reordering?" OFF)
option(WITH_TESTS "Enables unit tests" ON)
+option(ENABLE_SELINUX "Restore SELinux labels on GnuPG directories" ON)
# build options - debugging
@@ -83,6 +84,12 @@ if(ENABLE_RHSM_SUPPORT)
include_directories(${RHSM_INCLUDE_DIRS})
endif()
+if(ENABLE_SELINUX)
+ pkg_check_modules(SELINUX REQUIRED libselinux)
+ include_directories(${SELINUX_INCLUDE_DIRS})
+ add_definitions(-DENABLE_SELINUX=1)
+endif()
+
# glibc: check if fnmatch.h has FNM_CASEFOLD symbol
include(CheckSymbolExists)
diff --git a/libdnf.spec b/libdnf.spec
index 41df982c..09b5a89d 100644
--- a/libdnf.spec
+++ b/libdnf.spec
@@ -42,6 +42,8 @@
%bcond_with rhsm
%endif
+%bcond_without selinux
+
%if 0%{?rhel}
%bcond_with zchunk
%else
@@ -83,6 +85,9 @@ BuildRequires: pkgconfig(zck) >= 0.9.11
BuildRequires: pkgconfig(sqlite3)
BuildRequires: pkgconfig(json-c)
BuildRequires: pkgconfig(cppunit)
+%if %{with selinux}
+BuildRequires: pkgconfig(libselinux)
+%endif
BuildRequires: pkgconfig(modulemd-2.0) >= %{libmodulemd_version}
BuildRequires: pkgconfig(smartcols)
BuildRequires: gettext
@@ -204,7 +209,8 @@ pushd 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} -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}
+ -DWITH_SANITIZERS=%{?with_sanitizers:ON}%{!?with_sanitizers:OFF} \
+ -DENABLE_SELINUX=%{?with_selinux:ON}%{!?with_selinux:OFF}
%make_build
popd
%endif
@@ -218,7 +224,8 @@ pushd 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} -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}
+ -DWITH_SANITIZERS=%{?with_sanitizers:ON}%{!?with_sanitizers:OFF} \
+ -DENABLE_SELINUX=%{?with_selinux:ON}%{!?with_selinux:OFF}
%make_build
popd
%endif
diff --git a/libdnf/CMakeLists.txt b/libdnf/CMakeLists.txt
index 9e71d139..3c82ec3a 100644
--- a/libdnf/CMakeLists.txt
+++ b/libdnf/CMakeLists.txt
@@ -88,6 +88,10 @@ if(ENABLE_RHSM_SUPPORT)
target_link_libraries(libdnf ${RHSM_LIBRARIES})
endif()
+if(ENABLE_SELINUX)
+ target_link_libraries(libdnf ${SELINUX_LIBRARIES})
+endif()
+
set(DNF_SO_VERSION 2)
set_target_properties(libdnf PROPERTIES OUTPUT_NAME "dnf")
set_target_properties(libdnf PROPERTIES SOVERSION ${DNF_SO_VERSION})
diff --git a/libdnf/repo/Repo.cpp b/libdnf/repo/Repo.cpp
index 9959a73a..16f15195 100644
--- a/libdnf/repo/Repo.cpp
+++ b/libdnf/repo/Repo.cpp
@@ -51,6 +51,11 @@
#include <gpgme.h>
+#if ENABLE_SELINUX
+#include <selinux/selinux.h>
+#include <selinux/label.h>
+#endif
+
#include <solv/chksum.h>
#include <solv/repo.h>
#include <solv/util.h>
@@ -651,6 +656,81 @@ std::unique_ptr<LrHandle> Repo::Impl::lrHandleInitRemote(const char *destdir)
return h;
}
+/*
+ * @brief Create a temporary directory.
+ *
+ * Creates a temporary directory with 0700 mode attempting to set a proper
+ * SELinux file context. Encountered errors are logged at debug level to
+ * a global logger.
+ *
+ * @param name_template As an input value it is a template according to
+ * mkdtemp(3). As an output value it will contain the created directory name.
+ *
+ * @return 0 if the directory was created, -1 if it wasn't. SELinux failures
+ * are not considered an error.
+ */
+static int create_temporary_directory(char *name_template) {
+ auto logger(Log::getLogger());
+ int saved_errno = errno;
+ int retval = 0;
+#if ENABLE_SELINUX
+ char *old_default_context = NULL;
+ char *new_default_context = NULL;
+ int old_default_context_was_retrieved = 0;
+ struct selabel_handle *labeling_handle = NULL;
+
+ /* A purpose of this piece of code is to deal with applications whose
+ * security policy overrides a file context for temporary files but don't
+ * know that libdnf executes GnuPG which expects a default file context. */
+ if (0 == getfscreatecon(&old_default_context)) {
+ old_default_context_was_retrieved = 1;
+ } else {
+ logger->debug(tfm::format("Failed to retrieve a default SELinux context"));
+ }
+
+ labeling_handle = selabel_open(SELABEL_CTX_FILE, NULL, 0);
+ if (NULL == labeling_handle) {
+ logger->debug(tfm::format("Failed to open a SELinux labeling handle: %s",
+ strerror(errno)));
+ } else {
+ if (selabel_lookup(labeling_handle, &new_default_context, name_template, 0700)) {
+ /* Here we could hard-code "system_u:object_r:user_tmp_t:s0", but
+ * that value should be really defined in default file context
+ * SELinux policy. Only log that the policy is incpomplete. */
+ logger->debug(tfm::format("Failed to look up a default SELinux label for \"%s\"",
+ name_template));
+ } else {
+ if (setfscreatecon(new_default_context)) {
+ logger->debug(tfm::format("Failed to set default SELinux context to \"%s\"",
+ new_default_context));
+ }
+ freecon(new_default_context);
+ }
+ selabel_close(labeling_handle);
+ }
+#endif
+
+ /* mkdtemp() assures 0700 mode. */
+ if (NULL == mkdtemp(name_template)) {
+ saved_errno = errno;
+ logger->debug(tfm::format("Failed to create a directory \"%s\": %s",
+ name_template, strerror(errno)));
+ retval = -1;
+ }
+
+#if ENABLE_SELINUX
+ if (old_default_context_was_retrieved) {
+ if (setfscreatecon(old_default_context)) {
+ logger->debug(tfm::format("Failed to restore a default SELinux context"));
+ }
+ }
+ freecon(old_default_context);
+#endif
+
+ errno = saved_errno;
+ return retval;
+}
+
static void gpgImportKey(gpgme_ctx_t context, int keyFd)
{
auto logger(Log::getLogger());
@@ -705,8 +785,8 @@ static std::vector<Key> rawkey2infos(int fd) {
std::unique_ptr<std::remove_pointer<gpgme_ctx_t>::type> context(ctx);
// set GPG home dir
- char tmpdir[] = "/tmp/tmpdir.XXXXXX";
- if (!mkdtemp(tmpdir)) {
+ char tmpdir[] = "/tmp/libdnf.XXXXXX";
+ if (create_temporary_directory(tmpdir)) {
const char * errTxt = strerror(errno);
throw RepoError(tfm::format(_("Cannot create repo temporary directory \"%s\": %s"),
tmpdir, errTxt));
@@ -859,6 +939,13 @@ std::vector<Key> Repo::Impl::retrieve(const std::string & url)
* would cause a race condition with calling gpgme_release(), see [2], [3],
* [4].
*
+ * Current solution precreating /run/user/$UID showed problematic when this
+ * library was used out of a systemd-logind session from a programm with an
+ * unexpected SELinux context. Then /run/user/$UID, normally maintained by
+ * systemd, was assigned a SELinux label unexpected by systemd causing errors
+ * on a user logout [5]. We remedy it by restoring the label according to
+ * a file context policy.
+ *
* 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.
@@ -867,14 +954,27 @@ std::vector<Key> Repo::Impl::retrieve(const std::string & url)
* [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
+ * [5] https://issues.redhat.com/browse/RHEL-6421
*/
static void ensure_socket_dir_exists() {
auto logger(Log::getLogger());
+ char tmpdir[] = "/run/user/libdnf.XXXXXX";
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)));
+
+ /* create_temporary_directory() assures 0700 mode and tries its best to
+ * correct a SELinux label. */
+ if (create_temporary_directory(tmpdir)) {
+ return;
+ }
+
+ /* Set the desired name. */
+ if (rename(tmpdir, dirname.c_str())) {
+ if (errno != EEXIST && errno != ENOTEMPTY && errno != EBUSY) {
+ logger->debug(tfm::format("Failed to rename \"%s\" directory to \"%s\": %s",
+ tmpdir, dirname, strerror(errno)));
+ }
+ rmdir(tmpdir);
+ return;
}
}
@@ -1163,8 +1263,8 @@ void Repo::Impl::addCountmeFlag(LrHandle *handle) {
bool Repo::Impl::isMetalinkInSync()
{
auto logger(Log::getLogger());
- char tmpdir[] = "/tmp/tmpdir.XXXXXX";
- if (!mkdtemp(tmpdir)) {
+ char tmpdir[] = "/tmp/libdnf.XXXXXX";
+ if (create_temporary_directory(tmpdir)) {
const char * errTxt = strerror(errno);
throw RepoError(tfm::format(_("Cannot create repo temporary directory \"%s\": %s"),
tmpdir, errTxt));
@@ -1237,8 +1337,8 @@ bool Repo::Impl::isRepomdInSync()
{
auto logger(Log::getLogger());
LrYumRepo *yum_repo;
- char tmpdir[] = "/tmp/tmpdir.XXXXXX";
- if (!mkdtemp(tmpdir)) {
+ char tmpdir[] = "/tmp/libdnf.XXXXXX";
+ if (create_temporary_directory(tmpdir)) {
const char * errTxt = strerror(errno);
throw RepoError(tfm::format(_("Cannot create repo temporary directory \"%s\": %s"),
tmpdir, errTxt));
@@ -1280,8 +1380,8 @@ void Repo::Impl::fetch(const std::string & destdir, std::unique_ptr<LrHandle> &&
throw RepoError(tfm::format(_("Cannot create repo destination directory \"%s\": %s"),
destdir, errTxt));
}
- auto tmpdir = destdir + "/tmpdir.XXXXXX";
- if (!mkdtemp(&tmpdir.front())) {
+ auto tmpdir = destdir + "/libdnf.XXXXXX";
+ if (create_temporary_directory(&tmpdir.front())) {
const char * errTxt = strerror(errno);
throw RepoError(tfm::format(_("Cannot create repo temporary directory \"%s\": %s"),
tmpdir.c_str(), errTxt));
--
2.41.0

@ -1,93 +0,0 @@
From a0a32b4c2e2a03ff6ffcb6b7285905ec50892798 Mon Sep 17 00:00:00 2001
From: Colin Walters <walters@verbum.org>
Date: Tue, 4 Jun 2024 06:57:19 -0400
Subject: [PATCH] repo: Don't try to perform labeling if SELinux is disabled
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The default for container execution is that `/sys/fs/selinux`
is not mounted, and the libselinux library function `is_selinux_enabled`
should be used to dynamically check if the system should attempt to perform SELinux labeling.
This is how it's done by rpm, ostree, and systemd for example.
But this code unconditionally tries to label if it finds a policy,
which breaks in an obscure corner case
when executed inside a container that includes policy files (e.g.
fedora/rhel-bootc) but when we're not using overlayfs for the backend
(with BUILDAH_BACKEND=vfs).
Signed-off-by: Petr Písař <ppisar@redhat.com>
---
libdnf/repo/Repo.cpp | 50 +++++++++++++++++++++++---------------------
1 file changed, 26 insertions(+), 24 deletions(-)
diff --git a/libdnf/repo/Repo.cpp b/libdnf/repo/Repo.cpp
index 16f15195..10b88813 100644
--- a/libdnf/repo/Repo.cpp
+++ b/libdnf/repo/Repo.cpp
@@ -679,34 +679,36 @@ static int create_temporary_directory(char *name_template) {
int old_default_context_was_retrieved = 0;
struct selabel_handle *labeling_handle = NULL;
- /* A purpose of this piece of code is to deal with applications whose
- * security policy overrides a file context for temporary files but don't
- * know that libdnf executes GnuPG which expects a default file context. */
- if (0 == getfscreatecon(&old_default_context)) {
- old_default_context_was_retrieved = 1;
- } else {
- logger->debug(tfm::format("Failed to retrieve a default SELinux context"));
- }
+ if (is_selinux_enabled()) {
+ /* A purpose of this piece of code is to deal with applications whose
+ * security policy overrides a file context for temporary files but don't
+ * know that libdnf executes GnuPG which expects a default file context. */
+ if (0 == getfscreatecon(&old_default_context)) {
+ old_default_context_was_retrieved = 1;
+ } else {
+ logger->debug(tfm::format("Failed to retrieve a default SELinux context"));
+ }
- labeling_handle = selabel_open(SELABEL_CTX_FILE, NULL, 0);
- if (NULL == labeling_handle) {
- logger->debug(tfm::format("Failed to open a SELinux labeling handle: %s",
- strerror(errno)));
- } else {
- if (selabel_lookup(labeling_handle, &new_default_context, name_template, 0700)) {
- /* Here we could hard-code "system_u:object_r:user_tmp_t:s0", but
- * that value should be really defined in default file context
- * SELinux policy. Only log that the policy is incpomplete. */
- logger->debug(tfm::format("Failed to look up a default SELinux label for \"%s\"",
- name_template));
+ labeling_handle = selabel_open(SELABEL_CTX_FILE, NULL, 0);
+ if (NULL == labeling_handle) {
+ logger->debug(tfm::format("Failed to open a SELinux labeling handle: %s",
+ strerror(errno)));
} else {
- if (setfscreatecon(new_default_context)) {
- logger->debug(tfm::format("Failed to set default SELinux context to \"%s\"",
- new_default_context));
+ if (selabel_lookup(labeling_handle, &new_default_context, name_template, 0700)) {
+ /* Here we could hard-code "system_u:object_r:user_tmp_t:s0", but
+ * that value should be really defined in default file context
+ * SELinux policy. Only log that the policy is incpomplete. */
+ logger->debug(tfm::format("Failed to look up a default SELinux label for \"%s\"",
+ name_template));
+ } else {
+ if (setfscreatecon(new_default_context)) {
+ logger->debug(tfm::format("Failed to set default SELinux context to \"%s\"",
+ new_default_context));
+ }
+ freecon(new_default_context);
}
- freecon(new_default_context);
+ selabel_close(labeling_handle);
}
- selabel_close(labeling_handle);
}
#endif
--
2.45.2

@ -1,11 +1,11 @@
%global libsolv_version 0.7.21
%global libmodulemd_version 2.13.0
%global librepo_version 1.13.1
%global dnf_conflict 4.10.0-4
%global librepo_version 1.15.0
%global dnf_conflict 4.11.0
%global swig_version 3.0.12
%global libdnf_major_version 0
%global libdnf_minor_version 69
%global libdnf_micro_version 0
%global libdnf_minor_version 73
%global libdnf_micro_version 1
%define __cmake_in_source_build 1
@ -42,8 +42,6 @@
%bcond_with rhsm
%endif
%bcond_without selinux
%if 0%{?rhel}
%bcond_with zchunk
%else
@ -58,21 +56,20 @@
Name: libdnf
Version: %{libdnf_major_version}.%{libdnf_minor_version}.%{libdnf_micro_version}
Release: 8%{?dist}.1
Release: 5%{?dist}.inferit
Summary: Library providing simplified C and Python API to libsolv
License: LGPLv2+
License: LGPL-2.1-or-later
URL: https://github.com/rpm-software-management/libdnf
Source0: %{url}/archive/%{version}/%{name}-%{version}.tar.gz
Patch1: 0001-Allow-change-of-arch-during-security-updates-with-no.patch
Patch2: 0002-Add-repoid-to-solver-error-messages.patch
Patch3: 0003-Update-translations-RHEL-9-2.patch
Patch4: 0004-Update-translations-RHEL-9.3.patch
Patch5: 0005-filterAdvisory-installed_solvables-sort-RhBug2212838.patch
Patch6: 0006-hawkeysubject-get_best_selectors-only-obsol-oflatest.patch
Patch7: 0007-Avoid-reinstal-installonly-packages-marked-for-ERASE.patch
Patch8: 0008-PGP-Set-a-default-creation-SELinux-labels-on-GnuPG-d.patch
Patch9: 0009-repo-Don-t-try-to-perform-labeling-if-SELinux-is-dis.patch
Patch1: 0001-context-use-rpmtsAddReinstallElement-when-doing-a-re.patch
Patch2: 0002-Since-we-use-rpmtsAddReinstallElement-rpm-also-unins.patch
Patch3: 0003-MergedTransaction-Fix-invalid-memory-access-when-dro.patch
Patch4: 0004-Set-pool-flag-to-fix-pool_addfileprovides_queue-with.patch
Patch5: 0005-ConfigParser-fix-use-out-of-scope-leaks.patch
Patch6: 0006-Add-tests-for-shell-style-variable-expansion.patch
# MSVSphere
Patch100: 0001-msvsphere-bugtracker.patch
BuildRequires: cmake
BuildRequires: gcc
@ -95,13 +92,9 @@ BuildRequires: pkgconfig(zck) >= 0.9.11
BuildRequires: pkgconfig(sqlite3)
BuildRequires: pkgconfig(json-c)
BuildRequires: pkgconfig(cppunit)
%if %{with selinux}
BuildRequires: pkgconfig(libselinux)
%endif
BuildRequires: pkgconfig(modulemd-2.0) >= %{libmodulemd_version}
BuildRequires: pkgconfig(smartcols)
BuildRequires: gettext
BuildRequires: gpgme-devel
%if %{with sanitizers}
BuildRequires: libasan
@ -219,8 +212,7 @@ pushd 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} -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} \
-DENABLE_SELINUX=%{?with_selinux:ON}%{!?with_selinux:OFF}
-DWITH_SANITIZERS=%{?with_sanitizers:ON}%{!?with_sanitizers:OFF}
%make_build
popd
%endif
@ -234,8 +226,7 @@ pushd 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} -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} \
-DENABLE_SELINUX=%{?with_selinux:ON}%{!?with_selinux:OFF}
-DWITH_SANITIZERS=%{?with_sanitizers:ON}%{!?with_sanitizers:OFF}
%make_build
popd
%endif
@ -307,6 +298,7 @@ popd
%if %{with python3}
%files -n python3-%{name}
%{python3_sitearch}/%{name}-*.dist-info
%{python3_sitearch}/%{name}/
%endif
@ -321,108 +313,196 @@ popd
%endif
%changelog
* Fri Jun 21 2024 Petr Pisar <ppisar@redhat.com> - 0.69.0-8.1
- Do not set a default SELinux creation context if SELinux appears to be
disabled (RHEL-39796)
* Wed Oct 25 2023 Petr Pisar <ppisar@redhat.com> - 0.69.0-8
- Set default SELinux labels on GnuPG directories (RHEL-11238)
* Wed Oct 25 2023 Jaroslav Rohel <jrohel@redhat.com> - 0.69.0-7
- filterAdvisory: match installed_solvables sort with lower_bound (RhBug:2212838, RHEL-12123)
- hawkey.subject: get_best_selectors only obsoleters of latest (RhBug:2183279, RHEL-6304)
- Avoid reinstalling installonly packages marked for ERASE (RhBug:2163474, RHEL-12124)
* Fri Sep 08 2023 Marek Blaha <mblaha@redhat.com> - 0.69.0-6
* Wed Dec 18 2024 Sergey Cherevko <s.cherevko@msvsphere-os.ru> - 0.73.1-5.inferit
- Changed bug tracker URL to https://bugs.msvsphere-os.ru/
* Tue Nov 26 2024 MSVSphere Packaging Team <packager@msvsphere-os.ru> - 0.73.1-5
- Rebuilt for MSVSphere 10
* Tue Jul 16 2024 Petr Pisar <ppisar@redhat.com> - 0.73.1-5
- Fix invalid memory uses in libdnf::ConfigParser::substitute_expression() (RHEL-36777)
* Tue Jul 02 2024 Petr Pisar <ppisar@redhat.com> - 0.73.1-4
- Fix sack initialization to enable postponed addition of filelists (RHEL-12355)
* Mon Jun 24 2024 Troy Dawson <tdawson@redhat.com> - 0.73.1-3
- Bump release for June 2024 mass rebuild
* Tue Jun 11 2024 Petr Pisar <ppisar@redhat.com> - 0.73.1-2
- Fix reinstalling packages which conflicts with themselves in
dnf_transaction_commit() (RHEL-32919)
- Fix an invalid memory access when dropping an item in MergedTransaction
class (RHEL-33541)
* Thu Mar 28 2024 Evan Goode <egoode@redhat.com> - 0.73.1-1
- Update to 0.73.1 (RHEL-38831)
- Fix https://issues.redhat.com/browse/RHEL-27657 (RHEL-32935)
- subject-py: Fix memory leak (RHEL-32924)
- MergedTransaction: Calculate RPM difference between two same versions as
no-op (RHEL-33541)
- Onboard packit tests
- Add virtual destructor to TransactionItem (RHEL-32943)
* Thu Feb 08 2024 Fedora Release Engineering <releng@fedoraproject.org> - 0.73.0-1
- Update to 0.73.0
- filelists metadata loading on demand
- deltarpm disabled on Fedora
- conf: Introduce new optional_metadata_types option to load filelists on demand
- goal: Method for detecting file dependency problems
* Thu Jan 25 2024 Fedora Release Engineering <releng@fedoraproject.org> - 0.72.0-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
* Sun Jan 21 2024 Fedora Release Engineering <releng@fedoraproject.org> - 0.72.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
* Wed Oct 18 2023 Jan Kolarik <jkolarik@redhat.com> - 0.72.0-1
- Update to 0.72.0
- Avoid reinstalling installonly packages marked for ERASE (RhBug:2163474)
- transaction: Save the reason for installing (RhBug:1733274)
- hawkey.subject: get_best_selectors only obsoleters of latest (RhBug:2183279,2176263)
- conf: Add limited shell-style variable expansion (RhBug:1789346)
- conf: Add support for $releasever_major, $releasever_minor (RhBug:1789346)
- repo: Don't download the repository if the local cache is up to date
- Allow DNF to be removed by DNF 5 (RhBug:2221907)
- Include dist-info for python3-libdnf
- bindings: Load all modules with RTLD_GLOBAL
- Update translations
* Mon May 22 2023 Nicola Sella <nsella@redhat.com> - 0.69.0-5
- Fix specfile and bump release
* Mon May 22 2023 Nicola Sella <nsella@redhat.com> - 0.69.0-4
- Update translations
* Sun May 14 2023 Jaroslav Rohel <jrohel@redhat.com> - 0.69.0-3
- Add repoid to solver error messages (RhBug:2179409,2179413)
* Mon Oct 31 2022 Nicola Sella <nsella@redhat.com> - 0.69.0-2
- Allow change of arch during security updates with noarch
* Thu Sep 22 2022 Lukas Hrazky <lhrazky@redhat.com> - 0.69.0-1
- Update to 0.69.0
- Expose librepo max_downloads_per_mirror configuration
- Fix listing a repository without cpeid (RhBug:2066334)
- Gracefully handle failure to open repo primary file
- context: Fix doc dnf_context_install/remove/update/distrosync
- context: dnf_context_remove accepts `<package-spec>` as dnf, unify code
* Wed Sep 20 2023 Adam Williamson <awilliam@redhat.com> - 0.71.0-2
- Rebuild with no changes for Bodhi reasons
* Fri Sep 01 2023 Jan Kolarik <jkolarik@redhat.com> - 0.71.0-1
- Update to 0.71.0
- PGP: Use new librepo PGP API, remove gpgme dependency
- API: Basic support for OpenPGP public keys
- Avoid using GNU extensions in the dependency splitter regex
- filterAdvisory: match installed_solvables sort with lower_bound (RhBug:2212838)
- Make code C++20 compatible
* Fri Jul 28 2023 Nicola Sella <nsella@redhat.com> - 0.70.2-1
- Update to 0.70.2
- Support "proxy=none" in main config (RhBug:2155713)
- Fix #1558: Don't assume inclusion of cstdint
- Disconnect monitors in dnf_repo_loader_finalize() (RhBug:2070153)
* Thu Jul 20 2023 Fedora Release Engineering <releng@fedoraproject.org> - 0.70.1-5
- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild
* Wed Jun 14 2023 Python Maint <python-maint@redhat.com> - 0.70.1-4
- Rebuilt for Python 3.12
* Wed May 17 2023 Jan Kolarik <jkolarik@redhat.com> - 0.70.1-3
- Rebuild for rpm-4.18.90-4
* Tue May 16 2023 Jan Kolarik <jkolarik@redhat.com> - 0.70.1-2
- Rebuild for rpm-4.18.90
* Mon May 15 2023 Jan Kolarik <jkolarik@redhat.com> - 0.70.1-1
- Update to 0.70.1
- Add repoid to solver errors for RPMs (RhBug:2179413)
- Avoid using obsolete RPM API and drop redundant calls
- Remove DNF from list of protected packages
* Fri Mar 03 2023 Jan Kolarik <jkolarik@redhat.com> - 0.70.0-1
- Update to 0.70.0
- Allow change of architecture for packages during security updates with noarch involved (RhBug:2124483)
- "dnf_keyring_add_public_keys": reset localError to NULL after free (RhBug:2121222)
- context: Get RPM db path from RPM
- Fix memory leak of SolvUserdata
* Thu Jan 19 2023 Fedora Release Engineering <releng@fedoraproject.org> - 0.68.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild
* Tue Aug 16 2022 Jaroslav Rohel <jrohel@redhat.com> - 0.68.0-1
- Update to 0.68.0
- context: Support <package-spec> (NEVRA forms, provides, file provides) including globs in the dnf_context_remove func (RhBug:2084602)
- dnf-context: Disconnect signal handler before dropping file monitor ref
- Filter out advisory pkgs with different arch during advisory upgrade, fixes possible problems in dependency resulution (RhBug:2088149)
- Gracefully handle failure to open repo primary file
- Fix listing a repository without cpeid (RhBug:2066334)
* Thu Sep 15 2022 Marek Blaha <mblaha@redhat.com> - 0.67.0-3
- Update translations
* Thu Jul 21 2022 Fedora Release Engineering <releng@fedoraproject.org> - 0.67.0-4
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
* Thu Jul 21 2022 Lukas Hrazky <lhrazky@redhat.com> - 0.67.0-2
- Add obsoletes to filtering for advisory candidates
- advisory upgrade: filter out advPkgs with different arch
* Mon Jun 13 2022 Python Maint <python-maint@redhat.com> - 0.67.0-3
- Rebuilt for Python 3.11
* Thu Apr 28 2022 Pavla Kratochvilova <pkratoch@redhat.com> - 0.67.0-1
- Fix handling transaction id in resolveTransactionItemReason (RhBug:2010259,2053014)
- Remove deprecated assertions (RhBug:2027383)
- Skip rich deps for autodetection of unmet dependencies (RhBug:2033130, 2048394)
- Increase required rpm version since we use `rpmdbCookie()`
* Thu May 05 2022 Jaroslav Rohel <jrohel@redhat.com> - 0.67.0-2
- Increase required libsolv version for cache versioning to 0.7.21
* Thu May 05 2022 Jaroslav Rohel <jrohel@redhat.com> - 0.67.0-1
- Update to 0.67.0
- Add 'loongarch' support
- Use dnf solv userdata to check versions and checksum (RhBug:2027445)
- context: Substitute all repository config options (RhBug:2076853)
- Add more specific error handling for loading repomd and primary
* Mon Feb 07 2022 Pavla Kratochvilova <pkratoch@redhat.com> - 0.65.0-3
* Mon Mar 14 2022 Pavla Kratochvilova <pkratoch@redhat.com> - 0.66.0-1
- Use `rpmdbCookie` from librpm, remove `hawkey.Sack._rpmdb_version`
- Fix handling transaction id in resolveTransactionItemReason (RhBug:2010259,2053014)
- Remove deprecated assertions (RhBug:2027383)
- Increase required rpm version since we use `rpmdbCookie()`
* Mon Feb 21 2022 Pavla Kratochvilova <pkratoch@redhat.com> - 0.65.0-3
- Skip rich deps for autodetection of unmet dependencies (RhBug:2033130)
* Thu Dec 09 2021 Pavla Kratochvilova <pkratoch@redhat.com> - 0.65.0-2
- Rebuilt with json-c-0.14-11.el9 (RhBug:2023320)
* Thu Jan 20 2022 Fedora Release Engineering <releng@fedoraproject.org> - 0.65.0-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild
* Mon Oct 25 2021 Pavla Kratochvilova <pkratoch@redhat.com> - 0.65.0-1
* Thu Oct 21 2021 Pavla Kratochvilova <pkratoch@redhat.com> - 0.65.0-1
- Update to 0.65.0
- Add support for excluding packages to be installed as weak dependencies
- Add support for autodetecting packages to be excluded from being installed as weak dependencies
- Turn off strict validation of modulemd documents (RhBug:2004853,2007166,2007167)
* Thu Sep 23 2021 Pavla Kratochvilova <pkratoch@redhat.com> - 0.64.0-1
- Update to 0.64.0
- Implement logic for demodularization of modular rpms (RhBug:1805260)
- DnfContext: fix handling of default module profiles
- ModuleMetadata: gracefully handle modules with no defaults
- Remove failovermethod config option (RhBug:1961083)
- Add support for excluding packages to be installed as weak dependencies
- Add support for autodetecting packages to be excluded from being installed as weak dependencies
- Turn off strict validation of modulemd documents (RhBug:2004853,2007166,2007167)
* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 0.63.0-4
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
* Tue Sep 14 2021 Sahana Prasad <sahana@redhat.com> - 0.63.1-4
- Rebuilt with OpenSSL 3.0.0
* Tue Jul 27 2021 Pavla Kratochvilova <pkratoch@redhat.com> - 0.63.0-3
- Fix some covscan warnings
* Thu Jul 22 2021 Fedora Release Engineering <releng@fedoraproject.org> - 0.63.1-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild
* Wed Jun 16 2021 Mohan Boddu <mboddu@redhat.com> - 0.63.0-2
- Rebuilt for RHEL 9 BETA for openssl 3.0
Related: rhbz#1971065
* Sat Jul 10 2021 Björn Esser <besser82@fedoraproject.org> - 0.63.1-2
- Rebuild for versioned symbols in json-c
* Wed Jun 02 2021 Pavla Kratochvilova <pkratoch@redhat.com> - 0.63.0-1
* Tue Jun 15 2021 Pavla Kratochvilova <pkratoch@redhat.com> - 0.63.1-1
- Update to 0.63.1
- ModuleProfile: add isDefault()
- ModulePackage: add getDefaultProfile()
- Add new dnf_context_module_install() C API
- Fix a crash when [media] section in .treeinfo is missing for bootable media (RhBug:1946024)
- Add hy_query_get_advisory_pkgs to C API (RhBug:1960561)
- Add dnf_advisorypkg_get_advisory()
- DNF does not fail on non UTF-8 file names in a package (RhBug:1893176)
- Improve error-reporting for modular functions
* Thu Jun 03 2021 Python Maint <python-maint@redhat.com> - 0.62.0-2
- Rebuilt for Python 3.10
* Thu Apr 15 2021 Nicola Sella <nsella@redhat.com> - 0.62.0-1
- Fix: Fully set ssl in newHandle function
- [conf] Add options for working with certificates used with proxy
- lock: Switch return-if-fail to assert to quiet gcc -fanalyzer
- Modify module NSVCA parsing - context definition (RhBug:1926771)
- libdnf.h: Remove overall extern "C"
- [context] Fix: dnf_package_is_installonly (RhBug:1928056)
- Fix problematic language
- Add getApplicablePackages to advisory and isApplicable to advisorymodule
- Keep isAdvisoryApplicable to preserve API
- Run ModulePackageContainerTest tests in tmpdir, merge interdependent
- [context] Support config file option "proxy_auth_method", defaults "any"
- Hardening: add signature check with rpmcliVerifySignatures (RhBug:1932079)
- Do not allow 1 as installonly_limit value (RhBug:1926261)
- do not allow 1 as installonly_limit value (RhBug:1926261)
- Add a config option to check TLS certificate revocation status (using OCSP stapling), defaults to false (RhBug:1814383)
- ModuleProfile: add isDefault()
- ModulePackage: add getDefaultProfile()
- Add new dnf_context_module_install() C API
- Fix a crash when [media] section in .treeinfo is missing for bootable media (RhBug:1946024)
* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 0.60.0-2
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
* Tue Mar 02 2021 Nicola Sella <nsella@redhat.com> - 0.60.0-1
- Update to 0.60.0
- Fix repo.fresh() implementation
- build-sys: Add ENABLE_STATIC option
- Fix: Fully set ssl in newHandle function

Loading…
Cancel
Save