import libdnf-0.63.0-19.el8

i8c-beta changed/i8c-beta/libdnf-0.63.0-19.el8
MSVSphere Packaging Team 9 months ago
commit 7615e61e13

1
.gitignore vendored

@ -0,0 +1 @@
SOURCES/libdnf-0.63.0.tar.gz

@ -0,0 +1 @@
5bb88aae1c1b8c104e34916c7509b04fcf7b4de9 SOURCES/libdnf-0.63.0.tar.gz

@ -0,0 +1,32 @@
From 293e10c58dadc023070f959b08999b6bc2efb1b2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Sun, 25 Apr 2021 19:47:51 +0200
Subject: [PATCH 01/19] Revert "Improve performance for module query"
This reverts commit 38942d42b6980216e5d5e2e5798664cd08deb3ba.
---
libdnf/module/ModulePackageContainer.cpp | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/libdnf/module/ModulePackageContainer.cpp b/libdnf/module/ModulePackageContainer.cpp
index 1d5070ca..edb7e9ec 100644
--- a/libdnf/module/ModulePackageContainer.cpp
+++ b/libdnf/module/ModulePackageContainer.cpp
@@ -775,11 +775,9 @@ ModulePackageContainer::query(std::string name, std::string stream, std::string
Query query(pImpl->moduleSack, Query::ExcludeFlags::IGNORE_EXCLUDES);
// platform modules are installed and not in modules std::Map.
query.available();
- if (!name.empty() || !stream.empty()) {
- std::ostringstream ss;
- ss << stringFormater(name) << ":" << stringFormater(stream);
- query.addFilter(HY_PKG_DESCRIPTION, HY_GLOB, ss.str().c_str());
- }
+ std::ostringstream ss;
+ ss << stringFormater(name) << ":" << stringFormater(stream);
+ query.addFilter(HY_PKG_DESCRIPTION, HY_GLOB, ss.str().c_str());
if (!context.empty()) {
query.addFilter(HY_PKG_SUMMARY, HY_GLOB, context.c_str());
}
--
2.31.1

@ -0,0 +1,26 @@
From fe466856f54ed2cd261a863b2c929a064ae5e945 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Sun, 25 Apr 2021 19:47:51 +0200
Subject: [PATCH 02/19] Revert "Enhance description of modular solvables"
This reverts commit 943d9a1ba905f2e10975b16edff0684964c135b6.
---
libdnf/module/ModulePackage.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/libdnf/module/ModulePackage.cpp b/libdnf/module/ModulePackage.cpp
index 3757f6ad..d0017877 100644
--- a/libdnf/module/ModulePackage.cpp
+++ b/libdnf/module/ModulePackage.cpp
@@ -50,8 +50,6 @@ namespace libdnf {
* Arch: $arch (If arch is not defined, set "noarch")
* Provides: module($name)
* Provides: module($name:$stream)
- * Summary: original_context
- * Description: name:stream
*/
static void setSovable(Pool * pool, Solvable * solvable, const std::string & name,
const std::string & stream, const std::string & version, const std::string & context, const char * arch, const std::string & original_context)
--
2.31.1

@ -0,0 +1,26 @@
From adf159cce65fa5b15f81dd3ee319e551f01def1a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Sun, 25 Apr 2021 19:47:51 +0200
Subject: [PATCH 03/19] Revert "Fix typo: lates -> latest"
This reverts commit 2a7a315cda61355d60fc0dd0fae9ccd48079a9c5.
---
libdnf/dnf-context.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libdnf/dnf-context.cpp b/libdnf/dnf-context.cpp
index 926681c2..ccb6fe83 100644
--- a/libdnf/dnf-context.cpp
+++ b/libdnf/dnf-context.cpp
@@ -3253,7 +3253,7 @@ report_problems(const std::vector<std::tuple<libdnf::ModulePackageContainer::Mod
logger->warning(tfm::format(_("Modular dependency problem with Defaults: %s"), report.c_str()));
break;
case libdnf::ModulePackageContainer::ModuleErrorType::ERROR_IN_LATEST:
- logger->warning(tfm::format(_("Modular dependency problem with the latest modules: %s"),
+ logger->warning(tfm::format(_("Modular dependency problem with the lates modules: %s"),
report.c_str()));
break;
case libdnf::ModulePackageContainer::ModuleErrorType::ERROR:
--
2.31.1

@ -0,0 +1,39 @@
From 291f0393b54b31228c7a4c8c112003b64632967b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Sun, 25 Apr 2021 19:47:52 +0200
Subject: [PATCH 04/19] Revert "Remove unused code bump version"
This reverts commit f0fde46c42f2424135617b29fdfbcbf9e17fc79a.
---
libdnf/module/ModulePackageContainer.cpp | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/libdnf/module/ModulePackageContainer.cpp b/libdnf/module/ModulePackageContainer.cpp
index edb7e9ec..1bfdd8c1 100644
--- a/libdnf/module/ModulePackageContainer.cpp
+++ b/libdnf/module/ModulePackageContainer.cpp
@@ -1014,6 +1014,21 @@ modulePackageLatestPerRepoSorter(DnfSack * sack, const ModulePackage * first, co
return first->getVersionNum() > second->getVersionNum();
}
+static bool
+modulePackageLatestSorter(DnfSack * sack, const ModulePackage * first, const ModulePackage * second)
+{
+ int cmp = g_strcmp0(first->getNameCStr(), second->getNameCStr());
+ if (cmp != 0)
+ return cmp < 0;
+ cmp = dnf_sack_evr_cmp(sack, first->getStreamCStr(), second->getStreamCStr());
+ if (cmp != 0)
+ return cmp < 0;
+ cmp = g_strcmp0(first->getArchCStr(), second->getArchCStr());
+ if (cmp != 0)
+ return cmp < 0;
+ return first->getVersionNum() > second->getVersionNum();
+}
+
std::vector<std::vector<std::vector<ModulePackage *>>>
ModulePackageContainer::getLatestModulesPerRepo(ModuleState moduleFilter,
std::vector<ModulePackage *> modulePackages)
--
2.31.1

@ -0,0 +1,89 @@
From ce301450c39ebbd9fc5ec0897af2df766015e1bd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Sun, 25 Apr 2021 19:47:53 +0200
Subject: [PATCH 05/19] Revert "Report a new type of the module resolve error"
This reverts commit 9235436672fa413d5ac94f52a534b5abe90b5c7f.
---
libdnf/dnf-context.cpp | 4 ----
libdnf/module/ModulePackageContainer.cpp | 17 ++++++++++++-----
libdnf/module/ModulePackageContainer.hpp | 10 ++++------
3 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/libdnf/dnf-context.cpp b/libdnf/dnf-context.cpp
index ccb6fe83..55af2b26 100644
--- a/libdnf/dnf-context.cpp
+++ b/libdnf/dnf-context.cpp
@@ -3252,10 +3252,6 @@ report_problems(const std::vector<std::tuple<libdnf::ModulePackageContainer::Mod
case libdnf::ModulePackageContainer::ModuleErrorType::ERROR_IN_DEFAULTS:
logger->warning(tfm::format(_("Modular dependency problem with Defaults: %s"), report.c_str()));
break;
- case libdnf::ModulePackageContainer::ModuleErrorType::ERROR_IN_LATEST:
- logger->warning(tfm::format(_("Modular dependency problem with the lates modules: %s"),
- report.c_str()));
- break;
case libdnf::ModulePackageContainer::ModuleErrorType::ERROR:
logger->error(tfm::format(_("Modular dependency problem: %s"), report.c_str()));
return_error = true;
diff --git a/libdnf/module/ModulePackageContainer.cpp b/libdnf/module/ModulePackageContainer.cpp
index 1bfdd8c1..ee90056c 100644
--- a/libdnf/module/ModulePackageContainer.cpp
+++ b/libdnf/module/ModulePackageContainer.cpp
@@ -725,16 +725,23 @@ ModulePackageContainer::Impl::moduleSolve(const std::vector<ModulePackage *> & m
goal2name_query(goalWeak, query);
activatedModules.reset(new PackageSet(*query.runSet()));
}
- return make_pair(problems, problemType);
+ } else {
+ problemType = ModulePackageContainer::ModuleErrorType::ERROR_IN_DEFAULTS;
+ Query query(moduleSack, Query::ExcludeFlags::IGNORE_EXCLUDES);
+ goal2name_query(goal, query);
+ activatedModules.reset(new PackageSet(*query.runSet()));
}
- problemType = ModulePackageContainer::ModuleErrorType::ERROR_IN_LATEST;
} else {
problemType = ModulePackageContainer::ModuleErrorType::ERROR_IN_DEFAULTS;
+ Query query(moduleSack, Query::ExcludeFlags::IGNORE_EXCLUDES);
+ goal2name_query(goal, query);
+ activatedModules.reset(new PackageSet(*query.runSet()));
}
+ } else {
+ Query query(moduleSack, Query::ExcludeFlags::IGNORE_EXCLUDES);
+ goal2name_query(goal, query);
+ activatedModules.reset(new PackageSet(*query.runSet()));
}
- Query query(moduleSack, Query::ExcludeFlags::IGNORE_EXCLUDES);
- goal2name_query(goal, query);
- activatedModules.reset(new PackageSet(*query.runSet()));
return make_pair(problems, problemType);
}
diff --git a/libdnf/module/ModulePackageContainer.hpp b/libdnf/module/ModulePackageContainer.hpp
index f19c60fd..99fc0677 100644
--- a/libdnf/module/ModulePackageContainer.hpp
+++ b/libdnf/module/ModulePackageContainer.hpp
@@ -48,17 +48,15 @@ public:
enum class ModuleErrorType {
NO_ERROR = 0,
INFO,
- /// Error in module defaults detected during resolvement of module dependencies
+ /// Error in module defaults detected during resovement of module dependencies
ERROR_IN_DEFAULTS,
- /// Error detected during resolvement of module dependencies
+ /// Error detected during resovement of module dependencies
ERROR,
- /// Error detected during resolvement of module dependencies - Unexpected error!!!
+ /// Error detected during resovement of module dependencies - Unexpected error!!!
CANNOT_RESOLVE_MODULES,
CANNOT_RESOLVE_MODULE_SPEC,
CANNOT_ENABLE_MULTIPLE_STREAMS,
- CANNOT_MODIFY_MULTIPLE_TIMES_MODULE_STATE,
- /// Problem with latest modules during resolvement of module dependencies
- ERROR_IN_LATEST
+ CANNOT_MODIFY_MULTIPLE_TIMES_MODULE_STATE
};
struct Exception : public std::runtime_error
--
2.31.1

@ -0,0 +1,62 @@
From 15a06ef27466f42a8dc39823385f0ca655e80b12 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Sun, 25 Apr 2021 19:47:53 +0200
Subject: [PATCH 06/19] Revert "Add additional fallback for module resolve"
This reverts commit fc98ce725181a77bbe0ab157d40443467612c0c0.
---
libdnf/module/ModulePackageContainer.cpp | 32 ++++++++----------------
1 file changed, 11 insertions(+), 21 deletions(-)
diff --git a/libdnf/module/ModulePackageContainer.cpp b/libdnf/module/ModulePackageContainer.cpp
index ee90056c..e19db08b 100644
--- a/libdnf/module/ModulePackageContainer.cpp
+++ b/libdnf/module/ModulePackageContainer.cpp
@@ -702,33 +702,23 @@ ModulePackageContainer::Impl::moduleSolve(const std::vector<ModulePackage *> & m
std::vector<std::vector<std::string>> problems;
auto problemType = ModulePackageContainer::ModuleErrorType::NO_ERROR;
if (ret) {
- // Goal run ignor problem in defaults
problems = goal.describeAllProblemRules(false);
ret = goal.run(DNF_FORCE_BEST);
if (ret) {
- // Goal run ignor problem in defaults and in latest
- ret = goal.run(DNF_NONE);
+ // Conflicting modules has to be removed otherwice it could result than one of them will
+ // be active
+ auto conflictingPkgs = goal.listConflictPkgs(DNF_PACKAGE_STATE_AVAILABLE);
+ dnf_sack_add_excludes(moduleSack, conflictingPkgs.get());
+ ret = goalWeak.run(DNF_NONE);
if (ret) {
- // Conflicting modules has to be removed otherwice it could result than one of them will
- // be active
- auto conflictingPkgs = goal.listConflictPkgs(DNF_PACKAGE_STATE_AVAILABLE);
- dnf_sack_add_excludes(moduleSack, conflictingPkgs.get());
- ret = goalWeak.run(DNF_NONE);
- if (ret) {
- auto logger(Log::getLogger());
- logger->critical("Modularity filtering totally broken\n");
- problemType = ModulePackageContainer::ModuleErrorType::CANNOT_RESOLVE_MODULES;
- activatedModules.reset();
- } else {
- problemType = ModulePackageContainer::ModuleErrorType::ERROR;
- Query query(moduleSack, Query::ExcludeFlags::IGNORE_EXCLUDES);
- goal2name_query(goalWeak, query);
- activatedModules.reset(new PackageSet(*query.runSet()));
- }
+ auto logger(Log::getLogger());
+ logger->critical("Modularity filtering totally broken\n");
+ problemType = ModulePackageContainer::ModuleErrorType::CANNOT_RESOLVE_MODULES;
+ activatedModules.reset();
} else {
- problemType = ModulePackageContainer::ModuleErrorType::ERROR_IN_DEFAULTS;
+ problemType = ModulePackageContainer::ModuleErrorType::ERROR;
Query query(moduleSack, Query::ExcludeFlags::IGNORE_EXCLUDES);
- goal2name_query(goal, query);
+ goal2name_query(goalWeak, query);
activatedModules.reset(new PackageSet(*query.runSet()));
}
} else {
--
2.31.1

@ -0,0 +1,27 @@
From 0a92554dc2df3d2241b289bb796bc997c2959aaa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Sun, 25 Apr 2021 19:47:53 +0200
Subject: [PATCH 07/19] Revert "Decide how to handle context according to
static_context value"
This reverts commit 66439ed5a57373dfd106379637a9400b107e160c.
---
libdnf/module/modulemd/ModuleMetadata.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libdnf/module/modulemd/ModuleMetadata.cpp b/libdnf/module/modulemd/ModuleMetadata.cpp
index ee6834c6..07817ce1 100644
--- a/libdnf/module/modulemd/ModuleMetadata.cpp
+++ b/libdnf/module/modulemd/ModuleMetadata.cpp
@@ -142,7 +142,7 @@ std::vector<ModulePackage *> ModuleMetadata::getAllModulePackages(DnfSack * modu
//GPtrArray * streams = modulemd_module_index_search_streams_by_nsvca_glob(resultingModuleIndex, NULL);
for (unsigned int i = 0; i < streams->len; i++){
ModulemdModuleStream * moduleMdStream = static_cast<ModulemdModuleStream *>(g_ptr_array_index(streams, i));
- if (modulemd_module_stream_v2_is_static_context((ModulemdModuleStreamV2 *) moduleMdStream)) {
+ if (modulemd_module_stream_get_mdversion(moduleMdStream) > 2) {
result.push_back(new ModulePackage(moduleSack, repo, moduleMdStream, repoID));
} else {
g_object_ref(moduleMdStream);
--
2.31.1

@ -0,0 +1,76 @@
From 140168ce29d2425ebf2b4b5b25926611a189cd84 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Sun, 25 Apr 2021 19:47:53 +0200
Subject: [PATCH 08/19] Revert "Fix load/update FailSafe"
This reverts commit 244a37d772fcd5a5969085edab544fb1e7b68aad.
---
libdnf/module/ModulePackageContainer.cpp | 38 ++++++++++++++++++------
1 file changed, 29 insertions(+), 9 deletions(-)
diff --git a/libdnf/module/ModulePackageContainer.cpp b/libdnf/module/ModulePackageContainer.cpp
index e19db08b..97c84c01 100644
--- a/libdnf/module/ModulePackageContainer.cpp
+++ b/libdnf/module/ModulePackageContainer.cpp
@@ -1641,7 +1641,6 @@ ModulePackageContainer::Impl::ModulePersistor::getRemovedProfiles()
void ModulePackageContainer::loadFailSafeData()
{
- pImpl->addVersion2Modules();
auto persistor = pImpl->persistor->configs;
std::map<std::string, std::pair<std::string, bool>> enabledStreams;
@@ -1696,21 +1695,42 @@ void ModulePackageContainer::loadFailSafeData()
std::vector<ModulePackage *> ModulePackageContainer::Impl::getLatestActiveEnabledModules()
{
- Query query(moduleSack, Query::ExcludeFlags::IGNORE_EXCLUDES);
- query.addFilter(HY_PKG, HY_EQ, activatedModules.get());
- query.addFilter(HY_PKG_REPONAME, HY_NEQ, HY_SYSTEM_REPO_NAME);
- query.addFilter(HY_PKG_LATEST_PER_ARCH, HY_EQ, 1);
- auto set = query.runSet();
-
std::vector<ModulePackage *> activeModules;
Id moduleId = -1;
- while ((moduleId = set->next(moduleId)) != -1) {
+ while ((moduleId = activatedModules->next(moduleId)) != -1) {
auto modulePackage = modules.at(moduleId).get();
if (isEnabled(modulePackage->getName(), modulePackage->getStream())) {
activeModules.push_back(modulePackage);
}
}
- return activeModules;
+ if (activeModules.empty()) {
+ return {};
+ }
+ auto sack = moduleSack;
+ std::sort(activeModules.begin(), activeModules.end(),
+ [sack](const ModulePackage * first, const ModulePackage * second)
+ {return modulePackageLatestSorter(sack, first, second);});
+
+ auto packageFirst = activeModules[0];
+ std::vector<ModulePackage *> latest;
+ auto vectorSize = activeModules.size();
+ latest.push_back(packageFirst);
+ auto name = packageFirst->getNameCStr();
+ auto stream = packageFirst->getStreamCStr();
+ auto arch = packageFirst->getArchCStr();
+
+ for (unsigned int index = 1; index < vectorSize; ++index) {
+ auto & package = activeModules[index];
+ if (g_strcmp0(package->getNameCStr(), name) != 0 ||
+ g_strcmp0(package->getStreamCStr(), stream) != 0 ||
+ g_strcmp0(package->getArchCStr(), arch) != 0) {
+ name = package->getNameCStr();
+ stream = package->getStreamCStr();
+ arch = package->getArchCStr();
+ latest.push_back(package);
+ }
+ }
+ return latest;
}
void ModulePackageContainer::Impl::addVersion2Modules()
--
2.31.1

@ -0,0 +1,78 @@
From e43ef244e78d8563eb3cb7ff6a6074946f60c877 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Sun, 25 Apr 2021 19:47:53 +0200
Subject: [PATCH 09/19] Revert "Change mechanism of module conflicts"
This reverts commit 49600ba05b474bc29651aa122a9116b5ada69f4d.
---
libdnf/dnf-sack.cpp | 1 +
libdnf/module/ModulePackage.cpp | 2 --
libdnf/module/ModulePackage.hpp | 1 -
libdnf/module/ModulePackageContainer.cpp | 1 -
libdnf/module/ModulePackageContainer.hpp | 1 -
5 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/libdnf/dnf-sack.cpp b/libdnf/dnf-sack.cpp
index b5c7edc0..b9baeaef 100644
--- a/libdnf/dnf-sack.cpp
+++ b/libdnf/dnf-sack.cpp
@@ -2297,6 +2297,7 @@ void readModuleMetadataFromRepo(DnfSack * sack, libdnf::ModulePackageContainer *
modulePackages->add(sack);
modulePackages->loadFailSafeData();
if (!modulePackages->empty()) {
+ modulePackages->createConflictsBetweenStreams();
// TODO remove hard-coded path
try {
std::vector<std::string> paths{"/etc/os-release", "/usr/lib/os-release"};
diff --git a/libdnf/module/ModulePackage.cpp b/libdnf/module/ModulePackage.cpp
index d0017877..d644eca6 100644
--- a/libdnf/module/ModulePackage.cpp
+++ b/libdnf/module/ModulePackage.cpp
@@ -75,8 +75,6 @@ static void setSovable(Pool * pool, Solvable * solvable, const std::string & nam
ss << "module(" << name << ")";
auto depId = pool_str2id(pool, ss.str().c_str(), 1);
solvable_add_deparray(solvable, SOLVABLE_PROVIDES, depId, -1);
- // create Conflicts: module($name)
- solvable_add_deparray(solvable, SOLVABLE_CONFLICTS, depId, 0);
// create Provide: module($name:$stream)
ss.str(std::string());
diff --git a/libdnf/module/ModulePackage.hpp b/libdnf/module/ModulePackage.hpp
index b618df58..145c6d63 100644
--- a/libdnf/module/ModulePackage.hpp
+++ b/libdnf/module/ModulePackage.hpp
@@ -71,7 +71,6 @@ public:
std::vector<ModuleDependencies> getModuleDependencies() const;
- ///DEPRECATED
void addStreamConflict(const ModulePackage * package);
Id getId() const { return id; };
diff --git a/libdnf/module/ModulePackageContainer.cpp b/libdnf/module/ModulePackageContainer.cpp
index 97c84c01..893b839a 100644
--- a/libdnf/module/ModulePackageContainer.cpp
+++ b/libdnf/module/ModulePackageContainer.cpp
@@ -204,7 +204,6 @@ private:
/// solvable.arch = <moduleArch>
/// solvable.summary = <moduleContext>
/// solvable.description = <moduleName>:<moduleStream>
- /// solvable.conflicts = module(<moduleName>)
DnfSack * moduleSack;
std::unique_ptr<PackageSet> activatedModules;
std::string installRoot;
diff --git a/libdnf/module/ModulePackageContainer.hpp b/libdnf/module/ModulePackageContainer.hpp
index 99fc0677..c1001fce 100644
--- a/libdnf/module/ModulePackageContainer.hpp
+++ b/libdnf/module/ModulePackageContainer.hpp
@@ -115,7 +115,6 @@ public:
Id addPlatformPackage(const std::string &osReleasePath, const char * platformModule);
Id addPlatformPackage(DnfSack * sack,
const std::vector<std::string> & osReleasePath, const char * platformModule);
- /// DEPRECATED
void createConflictsBetweenStreams();
/**
--
2.31.1

@ -0,0 +1,214 @@
From 058b6112374f5feb5ee57488ac3fdbc7666a2016 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Sun, 25 Apr 2021 19:47:53 +0200
Subject: [PATCH 10/19] Revert "Call addVersion2Modules(); as late as possible"
This reverts commit fe27dba67384e549a3be2a91c4a6cf1151113157.
---
libdnf/module/ModulePackageContainer.cpp | 28 +++---------------------
1 file changed, 3 insertions(+), 25 deletions(-)
diff --git a/libdnf/module/ModulePackageContainer.cpp b/libdnf/module/ModulePackageContainer.cpp
index 893b839a..6ee2b68f 100644
--- a/libdnf/module/ModulePackageContainer.cpp
+++ b/libdnf/module/ModulePackageContainer.cpp
@@ -346,6 +346,7 @@ ModulePackageContainer::add(DnfSack * sack)
exception.what()));
}
}
+ pImpl->addVersion2Modules();
}
void ModulePackageContainer::addDefaultsFromDisk()
@@ -427,7 +428,6 @@ void ModulePackageContainer::createConflictsBetweenStreams()
bool ModulePackageContainer::empty() const noexcept
{
- pImpl->addVersion2Modules();
return pImpl->modules.empty();
}
@@ -521,13 +521,11 @@ bool ModulePackageContainer::isDisabled(const ModulePackage * module)
std::vector<std::string> ModulePackageContainer::getDefaultProfiles(std::string moduleName,
std::string moduleStream)
{
- pImpl->addVersion2Modules();
return pImpl->moduleMetadata.getDefaultProfiles(moduleName, moduleStream);
}
const std::string & ModulePackageContainer::getDefaultStream(const std::string &name) const
{
- pImpl->addVersion2Modules();
auto it = pImpl->moduleDefaults.find(name);
if (it == pImpl->moduleDefaults.end()) {
return EMPTY_RESULT;
@@ -537,7 +535,6 @@ const std::string & ModulePackageContainer::getDefaultStream(const std::string &
const std::string & ModulePackageContainer::getEnabledStream(const std::string &name)
{
- pImpl->addVersion2Modules();
return pImpl->persistor->getStream(name);
}
@@ -547,7 +544,6 @@ const std::string & ModulePackageContainer::getEnabledStream(const std::string &
bool
ModulePackageContainer::enable(const std::string &name, const std::string & stream, const bool count)
{
- pImpl->addVersion2Modules();
if (count) {
pImpl->persistor->getEntry(name).second.streamChangesNum++;
}
@@ -573,7 +569,6 @@ ModulePackageContainer::enable(const ModulePackage * module, const bool count)
*/
void ModulePackageContainer::disable(const std::string & name, const bool count)
{
- pImpl->addVersion2Modules();
if (count) {
pImpl->persistor->getEntry(name).second.streamChangesNum++;
}
@@ -594,11 +589,11 @@ void ModulePackageContainer::disable(const ModulePackage * module, const bool co
*/
void ModulePackageContainer::reset(const std::string & name, const bool count)
{
- pImpl->addVersion2Modules();
if (count) {
pImpl->persistor->getEntry(name).second.streamChangesNum++;
}
pImpl->persistor->changeState(name, ModuleState::UNKNOWN);
+
pImpl->persistor->changeStream(name, "");
auto & profiles = pImpl->persistor->getEntry(name).second.profiles;
profiles.clear();
@@ -638,7 +633,6 @@ bool ModulePackageContainer::isChanged()
void ModulePackageContainer::install(const std::string &name, const std::string &stream,
const std::string &profile)
{
- pImpl->addVersion2Modules();
for (const auto &iter : pImpl->modules) {
auto modulePackage = iter.second.get();
if (modulePackage->getName() == name && modulePackage->getStream() == stream) {
@@ -656,7 +650,6 @@ void ModulePackageContainer::install(const ModulePackage * module, const std::st
void ModulePackageContainer::uninstall(const std::string &name, const std::string &stream,
const std::string &profile)
{
- pImpl->addVersion2Modules();
for (const auto &iter : pImpl->modules) {
auto modulePackage = iter.second.get();
if (modulePackage->getName() == name && modulePackage->getStream() == stream) {
@@ -744,7 +737,6 @@ ModulePackageContainer::query(Nsvcap& moduleNevra)
std::vector<ModulePackage *>
ModulePackageContainer::query(std::string subject)
{
- pImpl->addVersion2Modules();
// Alternatively a search using module provides could be performed
std::vector<ModulePackage *> result;
Query query(pImpl->moduleSack, Query::ExcludeFlags::IGNORE_EXCLUDES);
@@ -765,7 +757,6 @@ std::vector<ModulePackage *>
ModulePackageContainer::query(std::string name, std::string stream, std::string version,
std::string context, std::string arch)
{
- pImpl->addVersion2Modules();
// Alternatively a search using module provides could be performed
std::vector<ModulePackage *> result;
Query query(pImpl->moduleSack, Query::ExcludeFlags::IGNORE_EXCLUDES);
@@ -847,7 +838,6 @@ ModulePackageContainer::getModuleState(const std::string& name)
std::set<std::string> ModulePackageContainer::getInstalledPkgNames()
{
- pImpl->addVersion2Modules();
auto moduleNames = pImpl->persistor->getAllModuleNames();
std::set<std::string> pkgNames;
for (auto & moduleName: moduleNames) {
@@ -1029,7 +1019,6 @@ std::vector<std::vector<std::vector<ModulePackage *>>>
ModulePackageContainer::getLatestModulesPerRepo(ModuleState moduleFilter,
std::vector<ModulePackage *> modulePackages)
{
- pImpl->addVersion2Modules();
if (modulePackages.empty()) {
return {};
}
@@ -1113,7 +1102,6 @@ ModulePackageContainer::getLatestModulesPerRepo(ModuleState moduleFilter,
std::pair<std::vector<std::vector<std::string>>, ModulePackageContainer::ModuleErrorType>
ModulePackageContainer::resolveActiveModulePackages(bool debugSolver)
{
- pImpl->addVersion2Modules();
dnf_sack_reset_excludes(pImpl->moduleSack);
std::vector<ModulePackage *> packages;
@@ -1164,7 +1152,6 @@ bool ModulePackageContainer::isModuleActive(const ModulePackage * modulePackage)
std::vector<ModulePackage *> ModulePackageContainer::getModulePackages()
{
- pImpl->addVersion2Modules();
std::vector<ModulePackage *> values;
const auto & modules = pImpl->modules;
std::transform(
@@ -1186,56 +1173,47 @@ void ModulePackageContainer::rollback()
std::map<std::string, std::string> ModulePackageContainer::getEnabledStreams()
{
- pImpl->addVersion2Modules();
return pImpl->persistor->getEnabledStreams();
}
std::vector<std::string> ModulePackageContainer::getDisabledModules()
{
- pImpl->addVersion2Modules();
return pImpl->persistor->getDisabledModules();
}
std::map<std::string, std::string> ModulePackageContainer::getDisabledStreams()
{
- pImpl->addVersion2Modules();
return pImpl->persistor->getDisabledStreams();
}
std::vector<std::string> ModulePackageContainer::getResetModules()
{
- pImpl->addVersion2Modules();
return pImpl->persistor->getResetModules();
}
std::map<std::string, std::string> ModulePackageContainer::getResetStreams()
{
- pImpl->addVersion2Modules();
return pImpl->persistor->getResetStreams();
}
std::map<std::string, std::pair<std::string, std::string>>
ModulePackageContainer::getSwitchedStreams()
{
- pImpl->addVersion2Modules();
return pImpl->persistor->getSwitchedStreams();
}
std::map<std::string, std::vector<std::string>> ModulePackageContainer::getInstalledProfiles()
{
- pImpl->addVersion2Modules();
return pImpl->persistor->getInstalledProfiles();
}
std::vector<std::string> ModulePackageContainer::getInstalledProfiles(std::string moduleName)
{
- pImpl->addVersion2Modules();
return pImpl->persistor->getProfiles(moduleName);
}
std::map<std::string, std::vector<std::string>> ModulePackageContainer::getRemovedProfiles()
{
- pImpl->addVersion2Modules();
return pImpl->persistor->getRemovedProfiles();
}
const std::string &
@@ -1641,7 +1619,7 @@ ModulePackageContainer::Impl::ModulePersistor::getRemovedProfiles()
void ModulePackageContainer::loadFailSafeData()
{
auto persistor = pImpl->persistor->configs;
-
+
std::map<std::string, std::pair<std::string, bool>> enabledStreams;
for (auto & nameConfig: persistor) {
if (nameConfig.second.second.state == ModuleState::ENABLED) {
--
2.31.1

@ -0,0 +1,108 @@
From 83703689de978cbb5e38f04fb1d9f554026de5ba Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Sun, 25 Apr 2021 19:47:53 +0200
Subject: [PATCH 11/19] Revert "Fix modular queries with the new solver"
This reverts commit a9f99a4969831f5d0e21d0f2b2b088ff6546604b.
---
libdnf/module/ModulePackage.cpp | 17 ++++-------------
libdnf/module/ModulePackageContainer.cpp | 13 ++-----------
libdnf/module/ModulePackageContainer.hpp | 2 +-
3 files changed, 7 insertions(+), 25 deletions(-)
diff --git a/libdnf/module/ModulePackage.cpp b/libdnf/module/ModulePackage.cpp
index d644eca6..63ee1656 100644
--- a/libdnf/module/ModulePackage.cpp
+++ b/libdnf/module/ModulePackage.cpp
@@ -52,7 +52,7 @@ namespace libdnf {
* Provides: module($name:$stream)
*/
static void setSovable(Pool * pool, Solvable * solvable, const std::string & name,
- const std::string & stream, const std::string & version, const std::string & context, const char * arch, const std::string & original_context)
+ const std::string & stream, const std::string & version, const std::string & context, const char * arch)
{
std::ostringstream ss;
// Name: $name:$stream:$context
@@ -62,14 +62,6 @@ static void setSovable(Pool * pool, Solvable * solvable, const std::string & nam
// TODO Test can be remove when modules will be always with arch
solvable_set_str(solvable, SOLVABLE_ARCH, arch ? arch : "noarch");
- // store original context in summary
- solvable_set_str(solvable, SOLVABLE_SUMMARY, original_context.c_str());
-
- // store original name:stream in description
- ss.str(std::string());
- ss << name << ":" << stream;
- solvable_set_str(solvable, SOLVABLE_DESCRIPTION, ss.str().c_str());
-
// create Provide: module($name)
ss.str(std::string());
ss << "module(" << name << ")";
@@ -105,9 +97,8 @@ ModulePackage::ModulePackage(DnfSack * moduleSack, LibsolvRepo * repo,
Pool * pool = dnf_sack_get_pool(moduleSack);
id = repo_add_solvable(repo);
Solvable *solvable = pool_id2solvable(pool, id);
- std::string original_context = getContext();
- setSovable(pool, solvable, getName(), getStream(), getVersion(), context.empty() ? original_context : context,
- getArchCStr(), original_context);
+
+ setSovable(pool, solvable, getName(), getStream(), getVersion(), context.empty() ? getContext() : context, getArchCStr());
createDependencies(solvable);
HyRepo hyRepo = static_cast<HyRepo>(repo->appdata);
libdnf::repoGetImpl(hyRepo)->needs_internalizing = 1;
@@ -649,7 +640,7 @@ ModulePackage::createPlatformSolvable(DnfSack * sack, DnfSack * moduleSack,
repoImpl->needs_internalizing = 1;
Id id = repo_add_solvable(repo);
Solvable *solvable = pool_id2solvable(pool, id);
- setSovable(pool, solvable, name, stream, version, context, "noarch", context);
+ setSovable(pool, solvable, name, stream, version, context, "noarch");
repoImpl->needs_internalizing = 1;
dnf_sack_set_provides_not_ready(moduleSack);
dnf_sack_set_considered_to_update(moduleSack);
diff --git a/libdnf/module/ModulePackageContainer.cpp b/libdnf/module/ModulePackageContainer.cpp
index 6ee2b68f..3f30037e 100644
--- a/libdnf/module/ModulePackageContainer.cpp
+++ b/libdnf/module/ModulePackageContainer.cpp
@@ -197,13 +197,6 @@ private:
class ModulePersistor;
std::unique_ptr<ModulePersistor> persistor;
std::map<Id, std::unique_ptr<ModulePackage>> modules;
- /// Internal sack with module solvables
- /// resolveContext = <moduleContext> if moduleMdVersion > 2, else generated from requires
- /// solvable.name = <moduleName>:<moduleStream>:<resolveContext>
- /// solvable.evr = <moduleVersion>
- /// solvable.arch = <moduleArch>
- /// solvable.summary = <moduleContext>
- /// solvable.description = <moduleName>:<moduleStream>
DnfSack * moduleSack;
std::unique_ptr<PackageSet> activatedModules;
std::string installRoot;
@@ -764,10 +757,8 @@ ModulePackageContainer::query(std::string name, std::string stream, std::string
query.available();
std::ostringstream ss;
ss << stringFormater(name) << ":" << stringFormater(stream);
- query.addFilter(HY_PKG_DESCRIPTION, HY_GLOB, ss.str().c_str());
- if (!context.empty()) {
- query.addFilter(HY_PKG_SUMMARY, HY_GLOB, context.c_str());
- }
+ ss << ":" << stringFormater(context);
+ query.addFilter(HY_PKG_NAME, HY_GLOB, ss.str().c_str());
if (!arch.empty()) {
query.addFilter(HY_PKG_ARCH, HY_GLOB, arch.c_str());
}
diff --git a/libdnf/module/ModulePackageContainer.hpp b/libdnf/module/ModulePackageContainer.hpp
index c1001fce..7e5071b2 100644
--- a/libdnf/module/ModulePackageContainer.hpp
+++ b/libdnf/module/ModulePackageContainer.hpp
@@ -270,7 +270,7 @@ public:
*/
std::vector<ModulePackage *> query(libdnf::Nsvcap & moduleNevra);
/**
- * @brief Requiers subject in format <name>, <name>:<stream>, or <name>:<stream>:<contex>
+ * @brief Requiers subject in format <name>, <name>:<stream>, or <name>:<stream>:<version>
*
* @param subject p_subject:...
* @return std::vector<ModulePackage *>
--
2.31.1

@ -0,0 +1,171 @@
From 833966d8a8a6c87a3d51447f2adf2aa76190ecd8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Sun, 25 Apr 2021 19:47:53 +0200
Subject: [PATCH 12/19] Revert "Add compatible layer for MdDocuments v2"
This reverts commit 32ccf6743cb9ce1579ff88804855a94f30876860.
---
libdnf/module/ModulePackageContainer.cpp | 68 +----------------------
libdnf/module/modulemd/ModuleMetadata.cpp | 11 +---
libdnf/module/modulemd/ModuleMetadata.hpp | 2 +-
3 files changed, 4 insertions(+), 77 deletions(-)
diff --git a/libdnf/module/ModulePackageContainer.cpp b/libdnf/module/ModulePackageContainer.cpp
index 3f30037e..6e6134d2 100644
--- a/libdnf/module/ModulePackageContainer.cpp
+++ b/libdnf/module/ModulePackageContainer.cpp
@@ -69,23 +69,6 @@ void goal2name_query(libdnf::Goal & goal, libdnf::Query & query)
query.addFilter(HY_PKG_NAME, HY_EQ, module_names.data());
}
-/**
- * @brief In python => ";".join(list.sort())
- */
-std::string concentrateVectorString(std::vector<std::string> & list)
-{
- if (list.empty()) {
- return {};
- }
- std::sort(list.begin(), list.end());
- std::ostringstream ss;
- ss << *list.begin();
- for (auto require = std::next(list.begin()); require != list.end(); ++require) {
- ss << ";" << *require;
- }
- return ss.str();
-}
-
}
namespace std {
@@ -189,8 +172,6 @@ public:
const std::vector<ModulePackage *> & modules, bool debugSolver);
bool insert(const std::string &moduleName, const char *path);
std::vector<ModulePackage *> getLatestActiveEnabledModules();
- /// Required to call after all modules v3 are in metadata
- void addVersion2Modules();
private:
friend struct ModulePackageContainer;
@@ -204,8 +185,6 @@ private:
ModuleMetadata moduleMetadata;
std::map<std::string, std::string> moduleDefaults;
- std::vector<std::tuple<LibsolvRepo *, ModulemdModuleStream *, std::string>> modulesV2;
-
bool isEnabled(const std::string &name, const std::string &stream);
};
@@ -339,7 +318,6 @@ ModulePackageContainer::add(DnfSack * sack)
exception.what()));
}
}
- pImpl->addVersion2Modules();
}
void ModulePackageContainer::addDefaultsFromDisk()
@@ -375,7 +353,7 @@ ModulePackageContainer::add(const std::string &fileContent, const std::string &
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);
+ std::vector<ModulePackage *> packages = md.getAllModulePackages(pImpl->moduleSack, r, repoID);
for(auto const& modulePackagePtr: packages) {
std::unique_ptr<ModulePackage> modulePackage(modulePackagePtr);
pImpl->modules.insert(std::make_pair(modulePackage->getId(), std::move(modulePackage)));
@@ -1701,50 +1679,6 @@ std::vector<ModulePackage *> ModulePackageContainer::Impl::getLatestActiveEnable
return latest;
}
-void ModulePackageContainer::Impl::addVersion2Modules()
-{
- if (modulesV2.empty()) {
- return;
- }
- std::map<std::string, std::map<std::string, std::vector<ModulePackage *>>> v3_context_map;
- for (auto const & module_pair : modules) {
- auto * module = module_pair.second.get();
- auto requires = module->getRequires(true);
- auto concentratedRequires = concentrateVectorString(requires);
- v3_context_map[module->getNameStream()][concentratedRequires].push_back(module);
- }
- libdnf::LibsolvRepo * repo;
- ModulemdModuleStream * mdStream;
- std::string repoID;
- g_autofree gchar * path = g_build_filename(installRoot.c_str(), "/etc/dnf/modules.d", NULL);
- for (auto & module_tuple : modulesV2) {
- std::tie(repo, mdStream, repoID) = module_tuple;
- auto nameStream = ModulePackage::getNameStream(mdStream);
- auto requires = ModulePackage::getRequires(mdStream, true);
- auto concentratedRequires = concentrateVectorString(requires);
- auto streamIterator = v3_context_map.find(nameStream);
- if (streamIterator != v3_context_map.end()) {
- auto contextIterator = streamIterator->second.find(concentratedRequires);
- if (contextIterator != streamIterator->second.end()) {
- auto v3_context = contextIterator->second[0]->getContext();
- std::unique_ptr<ModulePackage> modulePackage(new ModulePackage(moduleSack, repo, mdStream, repoID, v3_context));
- persistor->insert(modulePackage->getName(), path);
- modules.insert(std::make_pair(modulePackage->getId(), std::move(modulePackage)));
- g_object_unref(mdStream);
- continue;
- }
- }
- if (concentratedRequires.empty()) {
- concentratedRequires.append("NoRequires");
- }
- std::unique_ptr<ModulePackage> modulePackage(new ModulePackage(moduleSack, repo, mdStream, repoID, concentratedRequires));
- persistor->insert(modulePackage->getName(), path);
- modules.insert(std::make_pair(modulePackage->getId(), std::move(modulePackage)));
- g_object_unref(mdStream);
- }
- modulesV2.clear();
-}
-
void ModulePackageContainer::updateFailSafeData()
{
auto fileNames = getYamlFilenames(pImpl->persistDir.c_str());
diff --git a/libdnf/module/modulemd/ModuleMetadata.cpp b/libdnf/module/modulemd/ModuleMetadata.cpp
index 07817ce1..fbdd8a13 100644
--- a/libdnf/module/modulemd/ModuleMetadata.cpp
+++ b/libdnf/module/modulemd/ModuleMetadata.cpp
@@ -126,8 +126,7 @@ void ModuleMetadata::resolveAddedMetadata()
std::vector<ModulePackage *> ModuleMetadata::getAllModulePackages(DnfSack * moduleSack,
LibsolvRepo * repo,
- const std::string & repoID,
- std::vector<std::tuple<LibsolvRepo *, ModulemdModuleStream *, std::string>> & modulesV2)
+ const std::string & repoID)
{
std::vector<ModulePackage *> result;
if (!resultingModuleIndex)
@@ -141,13 +140,7 @@ std::vector<ModulePackage *> ModuleMetadata::getAllModulePackages(DnfSack * modu
//TODO(amatej): replace with
//GPtrArray * streams = modulemd_module_index_search_streams_by_nsvca_glob(resultingModuleIndex, NULL);
for (unsigned int i = 0; i < streams->len; i++){
- ModulemdModuleStream * moduleMdStream = static_cast<ModulemdModuleStream *>(g_ptr_array_index(streams, i));
- if (modulemd_module_stream_get_mdversion(moduleMdStream) > 2) {
- result.push_back(new ModulePackage(moduleSack, repo, moduleMdStream, repoID));
- } else {
- g_object_ref(moduleMdStream);
- modulesV2.push_back(std::make_tuple(repo, moduleMdStream, repoID));
- }
+ result.push_back(new ModulePackage(moduleSack, repo, (ModulemdModuleStream *) g_ptr_array_index(streams, i), repoID));
}
}
diff --git a/libdnf/module/modulemd/ModuleMetadata.hpp b/libdnf/module/modulemd/ModuleMetadata.hpp
index 901d7402..df753b11 100644
--- a/libdnf/module/modulemd/ModuleMetadata.hpp
+++ b/libdnf/module/modulemd/ModuleMetadata.hpp
@@ -36,7 +36,7 @@ public:
~ModuleMetadata();
void addMetadataFromString(const std::string & yaml, int priority);
void resolveAddedMetadata();
- std::vector<ModulePackage *> getAllModulePackages(DnfSack * moduleSack, LibsolvRepo * repo, const std::string & repoID, std::vector<std::tuple<LibsolvRepo *, ModulemdModuleStream *, std::string>> & modulesV2);
+ std::vector<ModulePackage *> getAllModulePackages(DnfSack * moduleSack, LibsolvRepo * repo, const std::string & repoID);
std::map<std::string, std::string> getDefaultStreams();
std::vector<std::string> getDefaultProfiles(std::string moduleName, std::string moduleStream);
ModulemdObsoletes * getNewestActiveObsolete(ModulePackage *p);
--
2.31.1

@ -0,0 +1,77 @@
From b1ed6e111ce05f8f1fe7b35afc1a3ef6f0731f7c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Sun, 25 Apr 2021 19:47:53 +0200
Subject: [PATCH 13/19] Revert "Add an alternative constructor for
ModulePackage"
This reverts commit d05bb263de6822c13ac4bd5cca3628318f5c7ce7.
---
libdnf/module/ModulePackage.cpp | 24 ++++++++++++------------
libdnf/module/ModulePackage.hpp | 2 +-
2 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/libdnf/module/ModulePackage.cpp b/libdnf/module/ModulePackage.cpp
index 63ee1656..8126bcaa 100644
--- a/libdnf/module/ModulePackage.cpp
+++ b/libdnf/module/ModulePackage.cpp
@@ -43,16 +43,16 @@ extern "C" {
namespace libdnf {
-/**
- * @brief create solvable with:
- * Name: $name:$stream:$context
- * Version: $version
- * Arch: $arch (If arch is not defined, set "noarch")
- * Provides: module($name)
- * Provides: module($name:$stream)
- */
-static void setSovable(Pool * pool, Solvable * solvable, const std::string & name,
- const std::string & stream, const std::string & version, const std::string & context, const char * arch)
+ /**
+ * @brief create solvable with:
+ * Name: $name:$stream:$context
+ * Version: $version
+ * Arch: $arch (If arch is not defined, set "noarch")
+ * Provides: module($name)
+ * Provides: module($name:$stream)
+ */
+ static void setSovable(Pool * pool, Solvable *solvable, std::string & name,
+ std::string & stream, std::string & version, std::string & context, const char * arch)
{
std::ostringstream ss;
// Name: $name:$stream:$context
@@ -86,7 +86,7 @@ static std::pair<std::string, std::string> parsePlatform(const std::string & pla
}
ModulePackage::ModulePackage(DnfSack * moduleSack, LibsolvRepo * repo,
- ModulemdModuleStream * mdStream, const std::string & repoID, const std::string & context)
+ ModulemdModuleStream * mdStream, const std::string & repoID)
: mdStream(mdStream)
, moduleSack(moduleSack)
, repoID(repoID)
@@ -98,7 +98,7 @@ ModulePackage::ModulePackage(DnfSack * moduleSack, LibsolvRepo * repo,
id = repo_add_solvable(repo);
Solvable *solvable = pool_id2solvable(pool, id);
- setSovable(pool, solvable, getName(), getStream(), getVersion(), context.empty() ? getContext() : context, getArchCStr());
+ setSovable(pool, solvable, getName(), getStream(), getVersion(), getContext(), getArchCStr());
createDependencies(solvable);
HyRepo hyRepo = static_cast<HyRepo>(repo->appdata);
libdnf::repoGetImpl(hyRepo)->needs_internalizing = 1;
diff --git a/libdnf/module/ModulePackage.hpp b/libdnf/module/ModulePackage.hpp
index 145c6d63..47cc995c 100644
--- a/libdnf/module/ModulePackage.hpp
+++ b/libdnf/module/ModulePackage.hpp
@@ -95,7 +95,7 @@ private:
friend struct ModuleMetadata;
ModulePackage(DnfSack * moduleSack, LibsolvRepo * repo,
- ModulemdModuleStream * mdStream, const std::string & repoID, const std::string & context = {});
+ ModulemdModuleStream * mdStream, const std::string & repoID);
ModulePackage(const ModulePackage & mpkg);
ModulePackage & operator=(const ModulePackage & mpkg);
--
2.31.1

@ -0,0 +1,113 @@
From 6c9540be5ac3e3bc3f9a60133b402945705b934f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Sun, 25 Apr 2021 19:47:53 +0200
Subject: [PATCH 14/19] Revert "Adjust modular solver to new context type"
This reverts commit 921d4db62cda41f7999aff67882ad0c01c766916.
---
libdnf/module/ModulePackageContainer.cpp | 46 +++++-------------------
1 file changed, 8 insertions(+), 38 deletions(-)
diff --git a/libdnf/module/ModulePackageContainer.cpp b/libdnf/module/ModulePackageContainer.cpp
index 6e6134d2..c0ad1260 100644
--- a/libdnf/module/ModulePackageContainer.cpp
+++ b/libdnf/module/ModulePackageContainer.cpp
@@ -49,28 +49,6 @@ extern "C" {
#include "modulemd/ModuleMetadata.hpp"
#include "modulemd/ModuleProfile.hpp"
-
-namespace {
-
-/// Requires resolved goal
-/// Takes listInstalls() from goal and keep solvables with the solvable-name (<name>:<stream>:<context>) in query
-void goal2name_query(libdnf::Goal & goal, libdnf::Query & query)
-{
- auto pool = dnf_sack_get_pool(goal.getSack());
- auto installList = goal.listInstalls();
- std::vector<const char *> module_names;
- Id id = -1;
- while ((id = installList.next(id)) != -1) {
- Solvable * s = pool_id2solvable(pool, id);
- const char * name = pool_id2str(pool, s->name);
- module_names.push_back(name);
- }
- module_names.push_back(nullptr);
- query.addFilter(HY_PKG_NAME, HY_EQ, module_names.data());
-}
-
-}
-
namespace std {
template<>
@@ -651,14 +629,14 @@ ModulePackageContainer::Impl::moduleSolve(const std::vector<ModulePackage *> & m
for (const auto &module : modules) {
std::ostringstream ss;
auto name = module->getName();
- ss << "module(" << name << ":" << module->getStream() << ")";
+ ss << "module(" << name << ":" << module->getStream() << ":" << module->getVersion() << ")";
Selector selector(moduleSack);
bool optional = persistor->getState(name) == ModuleState::DEFAULT;
selector.set(HY_PKG_PROVIDES, HY_EQ, ss.str().c_str());
goal.install(&selector, optional);
goalWeak.install(&selector, true);
}
- auto ret = goal.run(static_cast<DnfGoalActions>(DNF_IGNORE_WEAK | DNF_FORCE_BEST));
+ auto ret = goal.run(DNF_IGNORE_WEAK);
if (debugSolver) {
goal.writeDebugdata("debugdata/modules");
}
@@ -666,7 +644,7 @@ ModulePackageContainer::Impl::moduleSolve(const std::vector<ModulePackage *> & m
auto problemType = ModulePackageContainer::ModuleErrorType::NO_ERROR;
if (ret) {
problems = goal.describeAllProblemRules(false);
- ret = goal.run(DNF_FORCE_BEST);
+ ret = goal.run(DNF_NONE);
if (ret) {
// Conflicting modules has to be removed otherwice it could result than one of them will
// be active
@@ -680,20 +658,14 @@ ModulePackageContainer::Impl::moduleSolve(const std::vector<ModulePackage *> & m
activatedModules.reset();
} else {
problemType = ModulePackageContainer::ModuleErrorType::ERROR;
- Query query(moduleSack, Query::ExcludeFlags::IGNORE_EXCLUDES);
- goal2name_query(goalWeak, query);
- activatedModules.reset(new PackageSet(*query.runSet()));
+ activatedModules.reset(new PackageSet(std::move(goalWeak.listInstalls())));
}
} else {
problemType = ModulePackageContainer::ModuleErrorType::ERROR_IN_DEFAULTS;
- Query query(moduleSack, Query::ExcludeFlags::IGNORE_EXCLUDES);
- goal2name_query(goal, query);
- activatedModules.reset(new PackageSet(*query.runSet()));
+ activatedModules.reset(new PackageSet(std::move(goal.listInstalls())));
}
} else {
- Query query(moduleSack, Query::ExcludeFlags::IGNORE_EXCLUDES);
- goal2name_query(goal, query);
- activatedModules.reset(new PackageSet(*query.runSet()));
+ activatedModules.reset(new PackageSet(std::move(goal.listInstalls())));
}
return make_pair(problems, problemType);
}
@@ -735,14 +707,12 @@ ModulePackageContainer::query(std::string name, std::string stream, std::string
query.available();
std::ostringstream ss;
ss << stringFormater(name) << ":" << stringFormater(stream);
- ss << ":" << stringFormater(context);
+ ss << ":" << stringFormater(version) << ":";
+ ss << stringFormater(context);
query.addFilter(HY_PKG_NAME, HY_GLOB, ss.str().c_str());
if (!arch.empty()) {
query.addFilter(HY_PKG_ARCH, HY_GLOB, arch.c_str());
}
- if (!version.empty()) {
- query.addFilter(HY_PKG_VERSION, HY_GLOB, version.c_str());
- }
auto pset = query.runSet();
Id moduleId = -1;
while ((moduleId = pset->next(moduleId)) != -1) {
--
2.31.1

@ -0,0 +1,65 @@
From 50aa9f29dbfc1523a3b6aea41c6caa37f30c1bf0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Sun, 25 Apr 2021 19:47:53 +0200
Subject: [PATCH 15/19] Revert "Change usage of context and version in modular
solver"
This reverts commit 1f4c5b2a37ec333b23a12b882b046fac858155aa.
---
libdnf/module/ModulePackage.cpp | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/libdnf/module/ModulePackage.cpp b/libdnf/module/ModulePackage.cpp
index 8126bcaa..eea4a8b5 100644
--- a/libdnf/module/ModulePackage.cpp
+++ b/libdnf/module/ModulePackage.cpp
@@ -43,25 +43,19 @@ extern "C" {
namespace libdnf {
- /**
- * @brief create solvable with:
- * Name: $name:$stream:$context
- * Version: $version
- * Arch: $arch (If arch is not defined, set "noarch")
- * Provides: module($name)
- * Provides: module($name:$stream)
- */
- static void setSovable(Pool * pool, Solvable *solvable, std::string & name,
- std::string & stream, std::string & version, std::string & context, const char * arch)
+static void setSovable(Pool * pool, Solvable *solvable, std::string name,
+ std::string stream, std::string version, std::string context, const char * arch)
{
std::ostringstream ss;
- // Name: $name:$stream:$context
- ss << name << ":" << stream << ":" << context;
+ // create solvable with:
+ // Name: $name:$stream:$version:$context
+ // Version: 0
+ // Arch: $arch
+ ss << name << ":" << stream << ":" << version << ":" << context;
solvable_set_str(solvable, SOLVABLE_NAME, ss.str().c_str());
- solvable_set_str(solvable, SOLVABLE_EVR, version.c_str());
+ solvable_set_str(solvable, SOLVABLE_EVR, "0");
// TODO Test can be remove when modules will be always with arch
solvable_set_str(solvable, SOLVABLE_ARCH, arch ? arch : "noarch");
-
// create Provide: module($name)
ss.str(std::string());
ss << "module(" << name << ")";
@@ -73,6 +67,12 @@ namespace libdnf {
ss << "module(" << name << ":" << stream << ")";
depId = pool_str2id(pool, ss.str().c_str(), 1);
solvable_add_deparray(solvable, SOLVABLE_PROVIDES, depId, -1);
+
+ // create Provide: module($name:$stream:$version)
+ ss.str(std::string());
+ ss << "module(" << name << ":" << stream << ":" << version << ")";
+ depId = pool_str2id(pool, ss.str().c_str(), 1);
+ solvable_add_deparray(solvable, SOLVABLE_PROVIDES, depId, -1);
}
--
2.31.1

@ -0,0 +1,34 @@
From faaa64a51445b6edffe6f1e65c465dea63f11bf7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Tue, 27 Apr 2021 10:24:53 +0200
Subject: [PATCH 16/19] Fix failing unittest, caused by the revert of new
modular implementation
The problem is not caused by advisory filtering which we are testing
here, the `query` is already created with just one package.
---
tests/libdnf/sack/QueryTest.cpp | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/tests/libdnf/sack/QueryTest.cpp b/tests/libdnf/sack/QueryTest.cpp
index ee9eeaf4..7c3a22af 100644
--- a/tests/libdnf/sack/QueryTest.cpp
+++ b/tests/libdnf/sack/QueryTest.cpp
@@ -139,13 +139,10 @@ void QueryTest::testQueryFilterAdvisory()
dnf_sack_filter_modules_v2(sack, modules, nullptr, tmpdir, nullptr, true, false, false);
query = new libdnf::Query(sack);
query->addFilter(HY_PKG_ADVISORY_TYPE, HY_EQ, "enhancement");
- CPPUNIT_ASSERT(query->size() == 2);
+ CPPUNIT_ASSERT(query->size() == 1);
libdnf::PackageSet pset2 = *(query->getResultPset());
pkg = dnf_package_new(sack, pset2[0]);
CPPUNIT_ASSERT(!g_strcmp0(dnf_package_get_name(pkg), "test-perl-DBI"));
g_object_unref(pkg);
- pkg = dnf_package_new(sack, pset2[1]);
- CPPUNIT_ASSERT(!g_strcmp0(dnf_package_get_name(pkg), "test-perl-DBI"));
- g_object_unref(pkg);
delete query;
}
--
2.31.1

@ -0,0 +1,274 @@
From a61b0105aafeea8487902463f789e6ed00021eb3 Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Wed, 5 May 2021 15:55:43 +0200
Subject: [PATCH 17/19] Modify unit test after change of handling advisories
The patch modifies also yaml with multicollection situation by adding
module requires.
---
data/tests/advisories/modules.yaml | 6 +++++
.../tests/advisories/repodata/modules.yaml.gz | Bin 300 -> 332 bytes
data/tests/advisories/repodata/primary.xml.gz | Bin 743 -> 743 bytes
data/tests/advisories/repodata/repomd.xml | 24 +++++++++---------
tests/libdnf/sack/AdvisoryTest.cpp | 22 ++++++----------
tests/libdnf/sack/QueryTest.cpp | 24 ++++++++----------
6 files changed, 37 insertions(+), 39 deletions(-)
diff --git a/data/tests/advisories/modules.yaml b/data/tests/advisories/modules.yaml
index 6db5053a..b5f23f7d 100644
--- a/data/tests/advisories/modules.yaml
+++ b/data/tests/advisories/modules.yaml
@@ -32,6 +32,9 @@ data:
license:
module:
- MIT
+ dependencies:
+ - requires:
+ perl: ["5.23"]
profiles:
default:
rpms: ["test-perl-DBI"]
@@ -52,6 +55,9 @@ data:
license:
module:
- MIT
+ dependencies:
+ - requires:
+ perl: ["5.25"]
profiles:
default:
rpms: ["test-perl-DBI"]
diff --git a/data/tests/advisories/repodata/modules.yaml.gz b/data/tests/advisories/repodata/modules.yaml.gz
index 7158e6c515720c87373762d722e9c438ac7fd8d3..ed39532dfcdec084a661d51d86e07bd3e4246f69 100644
GIT binary patch
literal 332
zcmV-S0ki%eiwFP!000001I>{=Ps1<}hWGr6Q`gE7ag#Rnz<^jfATh8ZR2}w3Sc;us
zJE;77+&V2`Kt&yZ?cV$H`F$8;nd;<V$OZwXQ$tHeWpCuX?yLZwDGVqw0E>nM^yJzo
zd~k$Dz^uyoVipspfg%do*+9Fv4>2lq@<qU|UT&A=esnMf-MfJMv`UeePWRz3ea&J9
zj-^&hvYx~tmu^cjgS*W`jC$8Kx+R~oiW(f+kOYA1jX%Z=0{Otk>(K?>pbTUAvvJbK
zu0;G>$%;HZyrs6DS4GX|H7^S!#q;q?d7fwN0vp-w&1Pz)K_AF{F_TZt<j-f!92b6P
z=vY2$s-m8(A}e(=mVu+!K|4CRxxZe(<DUJ~g%rkPencX+Mj8d<QxwapUd`9_YK@Jn
eejSDUe<-TIL$NBWgd)&lisAzcI?AeD1ONa}51~l_
literal 300
zcmV+{0n`2;iwFP!000001Kp56Ps1<}#rJ%QQ`g85ar4LZz<^jfATh94hka2a*-2zO
zsC;`&okAE82nhzZd++X^&p*akrbjhf8iE8n>e-Oh*%LY6kAnoBX$&YcfB`K@n8=wZ
zd~k$T!lo|xb`y=ag)#~?4uMWF4>2lq>L}qPnnP2)uFlq?dzNsYqBMEs`YD{ZuUT~9
z(lWiG!IM0D>9$lexZ6L(YI0-O8}iB3)ZuJG5&&+p{!%jt<O5r-M;H1IRan~ZgR3!i
zCF9>JRu<{u0~wLmrQo^XRf(i|v3#j0ij4gLBfGuXuTfg`f!qg}d<~O7egSg{{0!*Q
y{uQW8_P4;s(FnI>d`-5gMVs$LyTi`ae@<5YXR>WoC$fRIYqBpd!@UUm0{{Tgm5(X_
diff --git a/data/tests/advisories/repodata/primary.xml.gz b/data/tests/advisories/repodata/primary.xml.gz
index da9ffaf08328659c47be8721a9c478ff64ba0a4d..96cbaa2a5a2361b1e5cd59ddb7de937339982c5f 100644
GIT binary patch
literal 743
zcmV<D0vP=tiwFP!000001Lao9Zrd;rz2_?ko>~O9B%0I`ND2@%1#&3RBI%*0fTBhg
zVQr-(BktFi)Dqj>k`zsgpnzeM!#6X0Z#V;o=XYg+wxC*BR}prWHbzj1I+fKr!XIzm
zE_{3*pM)iJJmnon8eX*#&bzKTv#df^{oOL{H?V}Xw`P<j>awgWJfhE3Q$FaSF&H&m
zZ1@^<e1dh-X^XmD0}(ce_ynP_;w8i#wB4csRV?0IT!q$PGlyJ>JihbYTbG8`urbz&
zAcCeAd4x4dZP9cwQc&n@%d$@U0&b!3PhIAFr-APUJW~u?gTKf@Y}&q@uF~e5FjwDq
zvzBRuKV4qqc$Eb!8hEKs2%}j*IQ0ebAY}{^!F=%3#H9{l`Y>@gB?&m5V>{r|AoIZ2
zx1Ey=8TD_;)o$Ra)1ddG7NIpC7*GnWP_pSXwfN*Fmo3sCj%Hbqah^pDts}Jdo(@zT
zTK7w1?^U5q=G*K#Spv#rp=moVv3)HJ)zp(-7Mi-ld=@yAIAl_)m0w^^8DZD<DMqqt
zJ6;r!4$7ON$gK%S=;Tz?f}3lhTtOD$quMT<#m~#L94oyvZ(|IV)vDy3S?Y~8pA}L-
z)k6I4>L#=f4SUEIs<bvT9BlTdYgPA6e7$QsDA8rLm8z~vs5<L{w=nvQkiE+wPF}ZN
zY?u{hH3IhsdvII#N`PL)PvG4uVMvcr_Yw9{bKohch2oWNAT7V@B21Z0O?#)NFw`Cu
zoA8aQw^F~5(KHz~OSMC$x4tO~Mp?nvx=$}Z;NNYkhqJuW)m^ys^`FT$YIV$W$gkjY
zFV$nH|LP)aIX~w))nVMwnjhwUv;DgP=TSDQ)4}TT1CDdwag)qW1VF|-lF*b;;bZ|1
zAaQI#T&4p%e8n;rxT^$g0fA4l#Lc{bQ1?X-INM$QwE=fnp8sjU9r1o~1Md5#dd>m&
ZqioMV;M}JUxcmQi@mJ$x7+z@#006pgY0dxu
literal 743
zcmV<D0vP=tiwFP!000001LamrZ`&{ozV}xMI&CNtTZ-gIVY@)F4(MUPhIWUY3R$LO
zBYsV`gJ!>ek{?a7SKDFTPz(qXk^D&NBSj*?`CVC{EvPoHs}Pf=jS*C`PV#CU;*U3P
z7al&3PJ$9Tk%&$p4X@e|XI<BvSyqu({oOL@H?V}Hw`P<j>$0pXJfhE3Q$FaSF&H&M
zZp0dNe2R6_NkrYQfe;%+bb?S&i4vj?+HTQ+Di&`pt^#Y&8KY1#i|#z<)?tA)2u3>*
zM9|bS3$Z4tHJUC)3JRTVS=LEkz%3Nsslz?@)c0Ipq>5u}@Ru3LP1~2#RoYBY?&$k&
z)_D@*PnXv?TBZJq`EKG-%311D!8}P_NH~XBau2*Db{L^t8)G6Eje)qtCg3nXb-~lO
zos$e1^=~QEZs4iYp!Z`f0&6xHPy($~dDCfX(aBAgw@7~kn#+QW^IX)xIznsj$)KXZ
zx<49yuL`X)-$v^45>T2Knl^C=^<0m+ntI&lg{Drp$9=*mp;M*W{0qz}L+scd!zi!X
zP80<sL*-3V@~sI++2mBzQkZL@OhFprquwsa;^*yIj-6hbw=srFYgLNQ9JQd;XGJcd
zY9V@ebrV>JialftRZ^QW90+^sTGf3MUGLfsN_1Imb5&O*RGoDpS{Qvs$lhfrPFA;F
zWSAA^Gy?aAJ-DrVB|)E}C-82SG^EF<`w07}8HfbbLWxQbkS@RKLd>|$%y=iJG0Yw-
zHsKppZ*%=ZM%AR$EY%K~+4`m_7^Q_+>p8vrfPZ(W9?tSgcX#2i*MBD4SgT{6Lw*IH
z`&>PS`mZj+m-BO;Qys<)todQy58J<6a4zFxbvjr*e!&Uh5hqUVSOTQnr7=q=lO*+p
z4>7SNb+`^p#EPffcUCdj5`2%Qv6H$!WzLIUaJIAhYYXnMJ^#~!JL3J~7Totk^_&at
ZN7<f#!8uP|aQFZ3qOUfbJ%VWp006EqV{!lh
diff --git a/data/tests/advisories/repodata/repomd.xml b/data/tests/advisories/repodata/repomd.xml
index 21630e04..c9468e82 100644
--- a/data/tests/advisories/repodata/repomd.xml
+++ b/data/tests/advisories/repodata/repomd.xml
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<repomd xmlns="http://linux.duke.edu/metadata/repo" xmlns:rpm="http://linux.duke.edu/metadata/rpm">
- <revision>1612879414</revision>
+ <revision>1620890113</revision>
<data type="primary">
- <checksum type="sha256">b69e4467719314fdb155872cf9c8e895d5b169c0506c5180c512d693c48f0f4b</checksum>
- <open-checksum type="sha256">8606d1f777859f167f7bd0bf8a1d532abedcb4db143b719e631e1040800fd1f0</open-checksum>
+ <checksum type="sha256">f2f306a22a157730d2f13f09fc36c425b9bedfc0ecaf74d8b60d98222ebb3274</checksum>
+ <open-checksum type="sha256">ef20a9175429f9f223c4bdcd634fc218bdd85799095438d349efea159cfd2bdf</open-checksum>
<location href="repodata/primary.xml.gz"/>
- <timestamp>1612879414</timestamp>
+ <timestamp>1620890113</timestamp>
<size>743</size>
<open-size>2665</open-size>
</data>
@@ -13,7 +13,7 @@
<checksum type="sha256">efbf7f021163a3c7698a257351e327102c60bb39a7bdceee77c421f064205e99</checksum>
<open-checksum type="sha256">ca5620e2734574d04d3c01ae5a72f865313369954698d71776076b9cbd831bbd</open-checksum>
<location href="repodata/filelists.xml.gz"/>
- <timestamp>1612879414</timestamp>
+ <timestamp>1620890113</timestamp>
<size>311</size>
<open-size>511</open-size>
</data>
@@ -21,23 +21,23 @@
<checksum type="sha256">6673953e1f28f55b9d4c3f38a9e3c0e0ff88ad06fb693b7f15eb241a81b80d71</checksum>
<open-checksum type="sha256">0997c242bf1b96372d7a625a73de23dced68cae9375baff0c73215a07693b3f4</open-checksum>
<location href="repodata/other.xml.gz"/>
- <timestamp>1612879414</timestamp>
+ <timestamp>1620890113</timestamp>
<size>310</size>
<open-size>507</open-size>
</data>
<data type="modules">
- <checksum type="sha256">a815d0669b15b97dd6260713405c79045eeda10aedb6460a0f742b86cc236cca</checksum>
- <open-checksum type="sha256">0d1063b74e3a7cb4c7cdc3b2080b1901c347693140765534f8c5c3d8b964778a</open-checksum>
+ <checksum type="sha256">df1abc1ab7dacc6ea2bc16c2b14abeb32d0ec9d9ed01378488cec22540f9607b</checksum>
+ <open-checksum type="sha256">f088c4096bfc4acad99a20e06d0d4381872c10f0f27ff8bbfe1bada658ff7afd</open-checksum>
<location href="repodata/modules.yaml.gz"/>
- <timestamp>1612879414</timestamp>
- <size>300</size>
- <open-size>1019</open-size>
+ <timestamp>1620890113</timestamp>
+ <size>332</size>
+ <open-size>1117</open-size>
</data>
<data type="updateinfo">
<checksum type="sha256">9d791d16c2adc2d7d4c85b45f2a704edac62a926b09fc20df73207f4190acd49</checksum>
<open-checksum type="sha256">3cf7df860860ac7a4a8e64a1a2d71c1ec43225dacbfe09a0cff80f28be3825da</open-checksum>
<location href="repodata/updateinfo.xml.gz"/>
- <timestamp>1612879414</timestamp>
+ <timestamp>1620890113</timestamp>
<size>708</size>
<open-size>2414</open-size>
</data>
diff --git a/tests/libdnf/sack/AdvisoryTest.cpp b/tests/libdnf/sack/AdvisoryTest.cpp
index 805c35da..1abf1a95 100644
--- a/tests/libdnf/sack/AdvisoryTest.cpp
+++ b/tests/libdnf/sack/AdvisoryTest.cpp
@@ -97,11 +97,9 @@ void AdvisoryTest::testGetApplicablePackagesModulesNotSetup()
// When modules are not setup all advisory collections are applicable and we get all packages
advisory->getApplicablePackages(pkgsvector);
- CPPUNIT_ASSERT(pkgsvector.size() == 4);
+ CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(pkgsvector.size()));
CPPUNIT_ASSERT(!g_strcmp0(pkgsvector[0].getNameString(), "test-perl-DBI"));
- CPPUNIT_ASSERT(!g_strcmp0(pkgsvector[1].getNameString(), "test-perl-DBI-new-collection-override"));
- CPPUNIT_ASSERT(!g_strcmp0(pkgsvector[2].getNameString(), "test-perl-DBI"));
- CPPUNIT_ASSERT(!g_strcmp0(pkgsvector[3].getNameString(), "not-present"));
+ CPPUNIT_ASSERT(!g_strcmp0(pkgsvector[1].getNameString(), "not-present"));
}
void AdvisoryTest::testGetApplicablePackagesModulesSetupNoneEnabled()
@@ -122,16 +120,14 @@ void AdvisoryTest::testGetApplicablePackagesOneApplicableCollection()
{
std::vector<libdnf::AdvisoryPkg> pkgsvector;
- // When I keep enabled only perl-DBI module I get packages from all collections that contain that module
+ // When I keep enabled only perl module I get packages from all collections that contain that module
libdnf::ModulePackageContainer * modules = dnf_sack_get_module_container(sack);
- modules->reset("perl");
+ modules->reset("perl-DBI");
dnf_sack_filter_modules_v2(sack, modules, nullptr, tmpdir, nullptr, true, false, false);
advisory->getApplicablePackages(pkgsvector);
- CPPUNIT_ASSERT(pkgsvector.size() == 3);
- CPPUNIT_ASSERT(!g_strcmp0(pkgsvector[0].getNameString(), "test-perl-DBI"));
- CPPUNIT_ASSERT(!g_strcmp0(pkgsvector[1].getNameString(), "test-perl-DBI-new-collection-override"));
- CPPUNIT_ASSERT(!g_strcmp0(pkgsvector[2].getNameString(), "test-perl-DBI"));
+ CPPUNIT_ASSERT(pkgsvector.size() == 1);
+ CPPUNIT_ASSERT(!g_strcmp0(pkgsvector[0].getNameString(), "not-present"));
}
void AdvisoryTest::testGetApplicablePackagesMultipleApplicableCollections()
@@ -141,11 +137,9 @@ void AdvisoryTest::testGetApplicablePackagesMultipleApplicableCollections()
// When I enable modules from multiple collections -> I get packages from all applicable collections
// Enabled - "perl-DBI:master", "perl:5.23"
advisory->getApplicablePackages(pkgsvector);
- CPPUNIT_ASSERT(pkgsvector.size() == 4);
+ CPPUNIT_ASSERT(pkgsvector.size() == 2);
CPPUNIT_ASSERT(!g_strcmp0(pkgsvector[0].getNameString(), "test-perl-DBI"));
- CPPUNIT_ASSERT(!g_strcmp0(pkgsvector[1].getNameString(), "test-perl-DBI-new-collection-override"));
- CPPUNIT_ASSERT(!g_strcmp0(pkgsvector[2].getNameString(), "test-perl-DBI"));
- CPPUNIT_ASSERT(!g_strcmp0(pkgsvector[3].getNameString(), "not-present"));
+ CPPUNIT_ASSERT(!g_strcmp0(pkgsvector[1].getNameString(), "not-present"));
}
void AdvisoryTest::testGetModules()
diff --git a/tests/libdnf/sack/QueryTest.cpp b/tests/libdnf/sack/QueryTest.cpp
index 7c3a22af..d4cc28c2 100644
--- a/tests/libdnf/sack/QueryTest.cpp
+++ b/tests/libdnf/sack/QueryTest.cpp
@@ -59,12 +59,13 @@ void QueryTest::testQueryGetAdvisoryPkgs()
HyQuery query = new libdnf::Query(sack);
std::vector<libdnf::AdvisoryPkg> advisoryPkgs;
- // When modules are not setup all advisory collections are applicable
+ // Apply advisory only from active context - receave advisory package only from releted collection
query->getAdvisoryPkgs(HY_EQ, advisoryPkgs);
- CPPUNIT_ASSERT(advisoryPkgs.size() == 2);
- // We get test-perl-DBI twice because its in two collections
- CPPUNIT_ASSERT(!g_strcmp0(advisoryPkgs[0].getNameString(), "test-perl-DBI"));
- CPPUNIT_ASSERT(!g_strcmp0(advisoryPkgs[1].getNameString(), "test-perl-DBI"));
+ CPPUNIT_ASSERT(advisoryPkgs.size() == 1);
+
+ CPPUNIT_ASSERT_EQUAL(std::string("test-perl-DBI"), std::string(advisoryPkgs[0].getNameString()));
+ CPPUNIT_ASSERT_EQUAL(std::string("1-2.module_el8+6587+9879afr5"), std::string(advisoryPkgs[0].getEVRString()));
+ //CPPUNIT_ASSERT(!g_strcmp0(advisoryPkgs[1].getNameString(), "test-perl-DBI"));
// When modules are setup but none are enabled all collections are not applicable - no enabled module
libdnf::ModulePackageContainer * modules = dnf_sack_get_module_container(sack);
@@ -84,15 +85,15 @@ void QueryTest::testQueryGetAdvisoryPkgs()
query->getAdvisoryPkgs(HY_EQ, advisoryPkgs);
CPPUNIT_ASSERT(advisoryPkgs.size() == 0);
- // When I enable a module from multiple collections that contain a present package I get them
+ // When I enable a module with multiple collections I will receave advisory packages only for active context
CPPUNIT_ASSERT(modules->enable("perl-DBI", "master", false));
dnf_sack_filter_modules_v2(sack, modules, nullptr, tmpdir, nullptr, true, false, false);
advisoryPkgs.clear();
query->getAdvisoryPkgs(HY_EQ, advisoryPkgs);
- CPPUNIT_ASSERT(advisoryPkgs.size() == 2);
- CPPUNIT_ASSERT(!g_strcmp0(advisoryPkgs[0].getNameString(), "test-perl-DBI"));
- CPPUNIT_ASSERT(!g_strcmp0(advisoryPkgs[1].getNameString(), "test-perl-DBI"));
+ CPPUNIT_ASSERT(advisoryPkgs.size() == 1);
+ CPPUNIT_ASSERT_EQUAL(std::string("test-perl-DBI"), std::string(advisoryPkgs[0].getNameString()));
+ CPPUNIT_ASSERT_EQUAL(std::string("1-2.module_el8+6587+9879afr5"), std::string(advisoryPkgs[0].getEVRString()));
delete query;
}
@@ -102,16 +103,13 @@ void QueryTest::testQueryFilterAdvisory()
// When modules are not setup all advisory collections are applicable and there is no modular filtering
HyQuery query = new libdnf::Query(sack);
query->addFilter(HY_PKG_ADVISORY_TYPE, HY_EQ, "enhancement");
- CPPUNIT_ASSERT(query->size() == 2);
+ CPPUNIT_ASSERT(query->size() == 1);
// We get test-perl-DBI twice because its in two collections
libdnf::PackageSet pset = *(query->getResultPset());
DnfPackage *pkg = dnf_package_new(sack, pset[0]);
CPPUNIT_ASSERT(!g_strcmp0(dnf_package_get_name(pkg), "test-perl-DBI"));
g_object_unref(pkg);
- pkg = dnf_package_new(sack, pset[1]);
- CPPUNIT_ASSERT(!g_strcmp0(dnf_package_get_name(pkg), "test-perl-DBI"));
- g_object_unref(pkg);
delete query;
// When module are setup but none are enabled all collections are not applicable - no enabled module
--
2.31.1

@ -0,0 +1,34 @@
From c7f0b13bf32cfba63a2db6257c50ae1ba5c8f9ba Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Thu, 6 May 2021 11:18:20 +0200
Subject: [PATCH 18/19] Adjust module error formatting function for original
modular solver
The new solver uses libsolv solvable by another way. The revert requires
also change in formatting function.
---
libdnf/goal/Goal.cpp | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/libdnf/goal/Goal.cpp b/libdnf/goal/Goal.cpp
index a6f11a4f..6b2f91a2 100644
--- a/libdnf/goal/Goal.cpp
+++ b/libdnf/goal/Goal.cpp
@@ -58,12 +58,8 @@ std::string moduleSolvid2str(Pool * pool, Id source)
{
std::ostringstream ss;
auto * solvable = pool_id2solvable(pool, source);
- // Add name:stream
- ss << solvable_lookup_str(solvable, SOLVABLE_DESCRIPTION);
- //Add version
- ss << ":" << pool_id2str(pool, solvable->evr);
- // Add original context
- ss << ":" << solvable_lookup_str(solvable, SOLVABLE_SUMMARY);
+ // Add name:stream:version:context
+ ss << pool_id2str(pool, solvable->name);
ss << "." << pool_id2str(pool, solvable->arch);
return ss.str();
}
--
2.31.1

@ -0,0 +1,57 @@
From eb7217d0a71b92ac0d8c3773caa1a2d3a2c20071 Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Thu, 13 May 2021 09:10:42 +0200
Subject: [PATCH 19/19] Remove redundant test
The test is identical to
testGetApplicablePackagesMultipleApplicableCollections().
---
tests/libdnf/sack/AdvisoryTest.cpp | 11 -----------
tests/libdnf/sack/AdvisoryTest.hpp | 2 --
2 files changed, 13 deletions(-)
diff --git a/tests/libdnf/sack/AdvisoryTest.cpp b/tests/libdnf/sack/AdvisoryTest.cpp
index 1abf1a95..f5892634 100644
--- a/tests/libdnf/sack/AdvisoryTest.cpp
+++ b/tests/libdnf/sack/AdvisoryTest.cpp
@@ -91,17 +91,6 @@ void AdvisoryTest::testGetPackages()
CPPUNIT_ASSERT(pkgsvector.size() == 4);
}
-void AdvisoryTest::testGetApplicablePackagesModulesNotSetup()
-{
- std::vector<libdnf::AdvisoryPkg> pkgsvector;
-
- // When modules are not setup all advisory collections are applicable and we get all packages
- advisory->getApplicablePackages(pkgsvector);
- CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(pkgsvector.size()));
- CPPUNIT_ASSERT(!g_strcmp0(pkgsvector[0].getNameString(), "test-perl-DBI"));
- CPPUNIT_ASSERT(!g_strcmp0(pkgsvector[1].getNameString(), "not-present"));
-}
-
void AdvisoryTest::testGetApplicablePackagesModulesSetupNoneEnabled()
{
std::vector<libdnf::AdvisoryPkg> pkgsvector;
diff --git a/tests/libdnf/sack/AdvisoryTest.hpp b/tests/libdnf/sack/AdvisoryTest.hpp
index 6eb25a57..cb0d8c05 100644
--- a/tests/libdnf/sack/AdvisoryTest.hpp
+++ b/tests/libdnf/sack/AdvisoryTest.hpp
@@ -19,7 +19,6 @@ class AdvisoryTest : public CppUnit::TestCase
CPPUNIT_TEST(testGetSeverity);
CPPUNIT_TEST(testGetTitle);
CPPUNIT_TEST(testGetPackages);
- CPPUNIT_TEST(testGetApplicablePackagesModulesNotSetup);
CPPUNIT_TEST(testGetApplicablePackagesModulesSetupNoneEnabled);
CPPUNIT_TEST(testGetApplicablePackagesOneApplicableCollection);
CPPUNIT_TEST(testGetApplicablePackagesMultipleApplicableCollections);
@@ -38,7 +37,6 @@ public:
void testGetSeverity();
void testGetTitle();
void testGetPackages();
- void testGetApplicablePackagesModulesNotSetup();
void testGetApplicablePackagesModulesSetupNoneEnabled();
void testGetApplicablePackagesOneApplicableCollection();
void testGetApplicablePackagesMultipleApplicableCollections();
--
2.31.1

@ -0,0 +1,28 @@
From 4a8a3f410552c58dfafb384bb361c6e40bebff1d Mon Sep 17 00:00:00 2001
From: Jaroslav Rohel <jrohel@redhat.com>
Date: Wed, 21 Jul 2021 11:01:32 +0200
Subject: [PATCH] Fix: dnf_context_module_install: memory leaks
---
libdnf/dnf-context.cpp | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/libdnf/dnf-context.cpp b/libdnf/dnf-context.cpp
index 55af2b2..6cb0011 100644
--- a/libdnf/dnf-context.cpp
+++ b/libdnf/dnf-context.cpp
@@ -3486,7 +3486,10 @@ dnf_context_module_install(DnfContext * context, const char ** module_specs, GEr
}
for (const auto &nevra : modpkg->getArtifacts()) {
int epoch;
- char *name, *version, *release, *arch;
+ g_autofree char *name = nullptr;
+ g_autofree char *version = nullptr;
+ g_autofree char *release = nullptr;
+ g_autofree char *arch = nullptr;
if (hy_split_nevra(nevra.c_str(), &name, &epoch, &version, &release, &arch)) {
// this really should never happen; unless the modular repodata is corrupted
g_autofree char *errmsg = g_strdup_printf (_("Failed to parse module artifact NEVRA '%s'"), nevra.c_str());
--
libgit2 1.0.1

@ -0,0 +1,91 @@
From 07416268889f95e1495fb3d7b856de1c502870ba Mon Sep 17 00:00:00 2001
From: Jaroslav Rohel <jrohel@redhat.com>
Date: Wed, 21 Jul 2021 11:15:50 +0200
Subject: [PATCH] covscan: remove unused vars, mark private func static, return values
The `begin` and `end` variables were not used
in `ModulePackageContainer::updateFailSafeData`. Removed.
The `checksum` in "utils.cpp" is a private (static) function.
Added check of return value of `dnf_copy_recursive` function in unit test.
In the `install` in the "goal-py.cpp" file:
Explicitly ignores the return values of `hy_goal_install` and
`hy_goal_install_optional`. The functions always return zero.
Explicitly ignores the return values of `hy_goal_install_selector` and
`hy_goal_install_selector_optional`. The `error` argument is used instead.
---
libdnf/module/ModulePackageContainer.cpp | 2 --
libdnf/utils/utils.cpp | 2 +-
python/hawkey/goal-py.cpp | 8 ++++----
tests/libdnf/module/ModulePackageContainerTest.cpp | 3 ++-
4 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/libdnf/module/ModulePackageContainer.cpp b/libdnf/module/ModulePackageContainer.cpp
index c0ad126..efab497 100644
--- a/libdnf/module/ModulePackageContainer.cpp
+++ b/libdnf/module/ModulePackageContainer.cpp
@@ -1656,8 +1656,6 @@ void ModulePackageContainer::updateFailSafeData()
if (pImpl->activatedModules) {
std::vector<ModulePackage *> latest = pImpl->getLatestActiveEnabledModules();
- auto begin = fileNames.begin();
- auto end = fileNames.end();
if (g_mkdir_with_parents(pImpl->persistDir.c_str(), 0755) == -1) {
const char * errTxt = strerror(errno);
auto logger(Log::getLogger());
diff --git a/libdnf/utils/utils.cpp b/libdnf/utils/utils.cpp
index 450718d..15f5275 100644
--- a/libdnf/utils/utils.cpp
+++ b/libdnf/utils/utils.cpp
@@ -301,7 +301,7 @@ void decompress(const char * inPath, const char * outPath, mode_t outMode, const
fclose(inFile);
}
-void checksum(const char * type, const char * inPath, const char * checksum_valid, bool * valid_out, gchar ** calculated_out)
+static void checksum(const char * type, const char * inPath, const char * checksum_valid, bool * valid_out, gchar ** calculated_out)
{
GError * errP{nullptr};
gboolean valid;
diff --git a/python/hawkey/goal-py.cpp b/python/hawkey/goal-py.cpp
index 2641a1d..5bbb959 100644
--- a/python/hawkey/goal-py.cpp
+++ b/python/hawkey/goal-py.cpp
@@ -281,15 +281,15 @@ install(_GoalObject *self, PyObject *args, PyObject *kwds) try
if (flags & HY_WEAK_SOLV) {
if (pkg) {
- hy_goal_install_optional(self->goal, pkg);
+ (void)hy_goal_install_optional(self->goal, pkg);
} else {
- hy_goal_install_selector_optional(self->goal, sltr, &error);
+ (void)hy_goal_install_selector_optional(self->goal, sltr, &error);
}
} else {
if (pkg) {
- hy_goal_install(self->goal, pkg);
+ (void)hy_goal_install(self->goal, pkg);
} else {
- hy_goal_install_selector(self->goal, sltr, &error);
+ (void)hy_goal_install_selector(self->goal, sltr, &error);
}
}
return op_error2exc(error);
diff --git a/tests/libdnf/module/ModulePackageContainerTest.cpp b/tests/libdnf/module/ModulePackageContainerTest.cpp
index b2cf170..6360a0c 100644
--- a/tests/libdnf/module/ModulePackageContainerTest.cpp
+++ b/tests/libdnf/module/ModulePackageContainerTest.cpp
@@ -17,7 +17,8 @@ void ModulePackageContainerTest::setUp()
char *retptr = mkdtemp(tmpdir);
CPPUNIT_ASSERT(retptr);
char * etc_target = g_strjoin(NULL, tmpdir, "/etc", NULL);
- dnf_copy_recursive(TESTDATADIR "/modules/etc", etc_target, &error);
+ auto ret = dnf_copy_recursive(TESTDATADIR "/modules/etc", etc_target, &error);
+ g_assert_true(ret);
g_assert_no_error(error);
g_free(etc_target);
--
libgit2 1.0.1

@ -0,0 +1,32 @@
From 263eee36afc0ae5c8f342f4b61038e91ee942b21 Mon Sep 17 00:00:00 2001
From: Marek Blaha <mblaha@redhat.com>
Date: Thu, 22 Apr 2021 15:19:26 +0200
Subject: [PATCH] hawkey: surrogateescape error handler to decode UTF-8 strings (RhBug:1893176)
This ensures that libdnf does not raise UnicodeDecodeError when
accessing package with non UTF-8 file names.
= changelog =
msg: DNF does not fail on non UTF-8 file names in a package
type: bugfix
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1893176
---
python/hawkey/iutil-py.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/python/hawkey/iutil-py.cpp b/python/hawkey/iutil-py.cpp
index 56ccafd..57bef57 100644
--- a/python/hawkey/iutil-py.cpp
+++ b/python/hawkey/iutil-py.cpp
@@ -285,7 +285,7 @@ strlist_to_pylist(const char **slist)
return NULL;
for (const char **iter = slist; *iter; ++iter) {
- UniquePtrPyObject str(PyUnicode_FromString(*iter));
+ UniquePtrPyObject str(PyUnicode_DecodeUTF8(*iter, strlen(*iter), "surrogateescape"));
if (!str)
return NULL;
int rc = PyList_Append(list.get(), str.get());
--
libgit2 1.0.1

@ -0,0 +1,28 @@
From 6eb68174565ce0402cead9e45053b560e819e982 Mon Sep 17 00:00:00 2001
From: Aleš Matěj <amatej@redhat.com>
Date: Tue, 21 Sep 2021 12:10:49 +0200
Subject: [PATCH] Turn off strict validation of modulemd documents (RhBug:2004853,2007166,2007167)
https://bugzilla.redhat.com/show_bug.cgi?id=2004853
https://bugzilla.redhat.com/show_bug.cgi?id=2007166
https://bugzilla.redhat.com/show_bug.cgi?id=2007167
---
libdnf/module/modulemd/ModuleMetadata.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libdnf/module/modulemd/ModuleMetadata.cpp b/libdnf/module/modulemd/ModuleMetadata.cpp
index fbdd8a1..9dcd661 100644
--- a/libdnf/module/modulemd/ModuleMetadata.cpp
+++ b/libdnf/module/modulemd/ModuleMetadata.cpp
@@ -78,7 +78,7 @@ void ModuleMetadata::addMetadataFromString(const std::string & yaml, int priorit
g_autoptr(GPtrArray) failures = NULL;
ModulemdModuleIndex * mi = modulemd_module_index_new();
- gboolean success = modulemd_module_index_update_from_string(mi, yaml.c_str(), TRUE, &failures, &error);
+ gboolean success = modulemd_module_index_update_from_string(mi, yaml.c_str(), FALSE, &failures, &error);
if(!success){
ModuleMetadata::reportFailures(failures);
}
--
libgit2 1.0.1

@ -0,0 +1,58 @@
From 551a83052ff92fa975f1015e2fc25b174f85b0e6 Mon Sep 17 00:00:00 2001
From: Aleš Matěj <amatej@redhat.com>
Date: Tue, 26 Oct 2021 09:33:51 +0200
Subject: [PATCH] Add unittest for setting up repo with empty keyfile (RhBug:1994614)
The test ensures we don't crash when the keyfile is empty/not loaded.
Test for: https://github.com/rpm-software-management/libdnf/commit/be66d0908d939ddaf3022c5489012bd1dbdb0075
RHEL bug:
https://bugzilla.redhat.com/show_bug.cgi?id=1994614
Fedora bug:
https://bugzilla.redhat.com/show_bug.cgi?id=1946024
---
tests/libdnf/dnf-self-test.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/tests/libdnf/dnf-self-test.c b/tests/libdnf/dnf-self-test.c
index 32a21e6..5295837 100644
--- a/tests/libdnf/dnf-self-test.c
+++ b/tests/libdnf/dnf-self-test.c
@@ -199,6 +199,26 @@ ch_test_repo_func(void)
g_object_unref(context);
}
+static void
+dnf_repo_setup_with_empty_keyfile(void)
+{
+ DnfContext *context = dnf_context_new();
+ dnf_context_set_release_ver(context, "33");
+ DnfRepo *repo = dnf_repo_new(context);
+ GKeyFile *empty_key_file = g_key_file_new();
+
+ dnf_repo_set_keyfile(repo, empty_key_file);
+
+ GError *error = NULL;
+ // Empty key file is not an errror, there is just no configuration to be loaded.
+ g_assert(dnf_repo_setup(repo, &error));
+ g_assert_no_error(error);
+
+ g_object_unref(repo);
+ g_object_unref(context);
+ g_key_file_free(empty_key_file);
+}
+
static guint _allow_cancel_updates = 0;
static guint _action_updates = 0;
static guint _package_progress_updates = 0;
@@ -1217,6 +1237,7 @@ main(int argc, char **argv)
g_test_add_func("/libdnf/lock", dnf_lock_func);
g_test_add_func("/libdnf/lock[threads]", dnf_lock_threads_func);
g_test_add_func("/libdnf/repo", ch_test_repo_func);
+ g_test_add_func("/libdnf/repo_empty_keyfile", dnf_repo_setup_with_empty_keyfile);
g_test_add_func("/libdnf/state", dnf_state_func);
g_test_add_func("/libdnf/state[child]", dnf_state_child_func);
g_test_add_func("/libdnf/state[parent-1-step]", dnf_state_parent_one_step_proxy_func);
--
libgit2 1.1.0

@ -0,0 +1,90 @@
From e83ff88f8e4604024e4d5f4fd9f2fa4e5d4f03f9 Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Tue, 23 Nov 2021 14:14:23 +0100
Subject: [PATCH] Add getLatestModules()
It returns latest module packages for each module name, stream, and
architecture.
It is an alternative implementation to code base with
the old modular solver.
Alternative to 73868368120ceea97ada628a1aa42236fb42b89d
---
libdnf/module/ModulePackageContainer.cpp | 39 +++++++++++++++++++++++++++++++++++++++
libdnf/module/ModulePackageContainer.hpp | 9 +++++++++
2 files changed, 48 insertions(+)
diff --git a/libdnf/module/ModulePackageContainer.cpp b/libdnf/module/ModulePackageContainer.cpp
index efab497..f9f861c 100644
--- a/libdnf/module/ModulePackageContainer.cpp
+++ b/libdnf/module/ModulePackageContainer.cpp
@@ -1037,6 +1037,45 @@ ModulePackageContainer::getLatestModulesPerRepo(ModuleState moduleFilter,
return output;
}
+std::vector<ModulePackage *>
+ModulePackageContainer::getLatestModules(const std::vector<ModulePackage *> modulePackages, bool activeOnly)
+{
+ std::vector<ModulePackage *> latestModules;
+ if (activeOnly) {
+ // When no active module return
+ if (!pImpl->activatedModules) {
+ return latestModules;
+ }
+ }
+ std::map<std::string, std::vector<ModulePackage *>> latest;
+
+ for (auto modulePackage : modulePackages) {
+ if (activeOnly && !isModuleActive(modulePackage)) {
+ continue;
+ }
+ auto nameStreamArch = modulePackage->getNameStream();
+ nameStreamArch.append(":");
+ nameStreamArch.append(modulePackage->getArchCStr());
+ auto & entries = latest[nameStreamArch];
+ if (entries.empty()) {
+ entries.push_back(modulePackage);
+ } else {
+ auto version = (*entries.begin())->getVersionNum();
+ if (version < modulePackage->getVersionNum()) {
+ entries.clear();
+ entries.push_back(modulePackage);
+ } else if (version == modulePackage->getVersionNum()) {
+ entries.push_back(modulePackage);
+ }
+ }
+ }
+ for (auto & entries : latest) {
+ for (auto modulePackage : entries.second) {
+ latestModules.push_back(modulePackage);
+ }
+ }
+ return latestModules;
+}
std::pair<std::vector<std::vector<std::string>>, ModulePackageContainer::ModuleErrorType>
ModulePackageContainer::resolveActiveModulePackages(bool debugSolver)
diff --git a/libdnf/module/ModulePackageContainer.hpp b/libdnf/module/ModulePackageContainer.hpp
index 7e5071b..42d5a9e 100644
--- a/libdnf/module/ModulePackageContainer.hpp
+++ b/libdnf/module/ModulePackageContainer.hpp
@@ -132,6 +132,15 @@ public:
std::vector<std::vector<std::vector<ModulePackage *>>> getLatestModulesPerRepo(
ModuleState moduleFilter, std::vector<ModulePackage *> modulePackages);
+ /**
+ * @brief Return all latest ModulePackages for each module Name, stream and architecture. In case of
+ * multiple latest packages, all will be returned. When activeOnly is true, it returns only the latest active
+ * packages.
+ *
+ * @return std::vector<ModulePackage *>
+ */
+ std::vector<ModulePackage *> getLatestModules(const std::vector<ModulePackage *> modulePackages, bool activeOnly);
+
std::vector<ModulePackage *> requiresModuleEnablement(const libdnf::PackageSet & packages);
/**
--
libgit2 1.1.0

@ -0,0 +1,107 @@
From 7d8f9cfcdf7725fef2c99ecb2dedcdff1e9506d7 Mon Sep 17 00:00:00 2001
From: Jaroslav Rohel <jrohel@redhat.com>
Date: Wed, 13 Apr 2022 12:26:10 +0200
Subject: [PATCH 26/34] context: Substitute all repository config options
(RhBug:2076853)
It also solves the problem: Substitution of variables in `baseurl`
does not work in microdnf and PackageKit unless `metalink` or `mirrorlist`
is set at the same time.
---
libdnf/dnf-repo.cpp | 34 +++++++++++++++++++++++++---------
1 file changed, 25 insertions(+), 9 deletions(-)
diff --git a/libdnf/dnf-repo.cpp b/libdnf/dnf-repo.cpp
index 710045fb..9d42e3e3 100644
--- a/libdnf/dnf-repo.cpp
+++ b/libdnf/dnf-repo.cpp
@@ -83,6 +83,7 @@ typedef struct
LrHandle *repo_handle;
LrResult *repo_result;
LrUrlVars *urlvars;
+ bool unit_test_mode; /* ugly hack for unit tests */
} DnfRepoPrivate;
G_DEFINE_TYPE_WITH_PRIVATE(DnfRepo, dnf_repo, G_TYPE_OBJECT)
@@ -847,8 +848,11 @@ dnf_repo_conf_reset(libdnf::ConfigRepo &config)
/* Loads repository configuration from GKeyFile */
static void
-dnf_repo_conf_from_gkeyfile(libdnf::ConfigRepo &config, const char *repoId, GKeyFile *gkeyFile)
+dnf_repo_conf_from_gkeyfile(DnfRepo *repo, const char *repoId, GKeyFile *gkeyFile)
{
+ DnfRepoPrivate *priv = GET_PRIVATE(repo);
+ auto & config = *priv->repo->getConfig();
+
// Reset to the initial state before reloading the configuration.
dnf_repo_conf_reset(config);
@@ -883,20 +887,31 @@ dnf_repo_conf_from_gkeyfile(libdnf::ConfigRepo &config, const char *repoId, GKey
// list can be ['value1', 'value2, value3'] therefore we first join
// to have 'value1, value2, value3'
g_autofree gchar * tmp_strval = g_strjoinv(",", list);
+
+ // Substitute vars.
+ g_autofree gchar *subst_value = dnf_repo_substitute(repo, tmp_strval);
+
+ if (strcmp(key, "baseurl") == 0 && strstr(tmp_strval, "file://$testdatadir") != NULL) {
+ priv->unit_test_mode = true;
+ }
+
try {
- optionItem.newString(libdnf::Option::Priority::REPOCONFIG, tmp_strval);
+ optionItem.newString(libdnf::Option::Priority::REPOCONFIG, subst_value);
} catch (const std::exception & ex) {
- g_debug("Invalid configuration value: %s = %s in %s; %s", key, value.c_str(), repoId, ex.what());
+ g_debug("Invalid configuration value: %s = %s in %s; %s", key, subst_value, repoId, ex.what());
}
}
} else {
-
// process other (non list) options
+
+ // Substitute vars.
+ g_autofree gchar *subst_value = dnf_repo_substitute(repo, value.c_str());
+
try {
- optionItem.newString(libdnf::Option::Priority::REPOCONFIG, value);
+ optionItem.newString(libdnf::Option::Priority::REPOCONFIG, subst_value);
} catch (const std::exception & ex) {
- g_debug("Invalid configuration value: %s = %s in %s; %s", key, value.c_str(), repoId, ex.what());
+ g_debug("Invalid configuration value: %s = %s in %s; %s", key, subst_value, repoId, ex.what());
}
}
@@ -950,7 +965,7 @@ dnf_repo_set_keyfile_data(DnfRepo *repo, gboolean reloadFromGKeyFile, GError **e
// Reload repository configuration from keyfile.
if (reloadFromGKeyFile) {
- dnf_repo_conf_from_gkeyfile(*conf, repoId, priv->keyfile);
+ dnf_repo_conf_from_gkeyfile(repo, repoId, priv->keyfile);
dnf_repo_apply_setopts(*conf, repoId);
}
@@ -996,8 +1011,9 @@ dnf_repo_set_keyfile_data(DnfRepo *repo, gboolean reloadFromGKeyFile, GError **e
g_autofree gchar *url = NULL;
url = lr_prepend_url_protocol(baseurls[0]);
if (url != NULL && strncasecmp(url, "file://", 7) == 0) {
- if (g_strstr_len(url, -1, "$testdatadir") == NULL)
+ if (!priv->unit_test_mode) {
priv->kind = DNF_REPO_KIND_LOCAL;
+ }
g_free(priv->location);
g_free(priv->keyring);
priv->location = dnf_repo_substitute(repo, url + 7);
@@ -1224,7 +1240,7 @@ dnf_repo_setup(DnfRepo *repo, GError **error) try
auto repoId = priv->repo->getId().c_str();
auto conf = priv->repo->getConfig();
- dnf_repo_conf_from_gkeyfile(*conf, repoId, priv->keyfile);
+ dnf_repo_conf_from_gkeyfile(repo, repoId, priv->keyfile);
dnf_repo_apply_setopts(*conf, repoId);
auto sslverify = conf->sslverify().getValue();
--
2.31.1

@ -0,0 +1,50 @@
From 074ca4cf643c79b8ec3db89a7fd5580ba387eb4d Mon Sep 17 00:00:00 2001
From: Jaroslav Rohel <jrohel@redhat.com>
Date: Wed, 20 Apr 2022 08:22:30 +0200
Subject: [PATCH 27/34] Use environment variable in unittest instead of ugly
hack in libdnf
Libdnf contains hacks for unit tests. This removes one hack.
---
libdnf/dnf-repo.cpp | 3 ---
tests/libdnf/dnf-self-test.c | 3 +++
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/libdnf/dnf-repo.cpp b/libdnf/dnf-repo.cpp
index 9d42e3e3..c015d7fd 100644
--- a/libdnf/dnf-repo.cpp
+++ b/libdnf/dnf-repo.cpp
@@ -1191,7 +1191,6 @@ dnf_repo_setup(DnfRepo *repo, GError **error) try
DnfRepoEnabled enabled = DNF_REPO_ENABLED_NONE;
g_autofree gchar *basearch = NULL;
g_autofree gchar *release = NULL;
- g_autofree gchar *testdatadir = NULL;
basearch = g_key_file_get_string(priv->keyfile, "general", "arch", NULL);
if (basearch == NULL)
@@ -1230,8 +1229,6 @@ dnf_repo_setup(DnfRepo *repo, GError **error) try
for (const auto & item : libdnf::dnf_context_get_vars(priv->context))
priv->urlvars = lr_urlvars_set(priv->urlvars, item.first.c_str(), item.second.c_str());
- testdatadir = dnf_realpath(TESTDATADIR);
- priv->urlvars = lr_urlvars_set(priv->urlvars, "testdatadir", testdatadir);
if (!lr_handle_setopt(priv->repo_handle, error, LRO_VARSUB, priv->urlvars))
return FALSE;
if (!lr_handle_setopt(priv->repo_handle, error, LRO_GNUPGHOMEDIR, priv->keyring))
diff --git a/tests/libdnf/dnf-self-test.c b/tests/libdnf/dnf-self-test.c
index 52958371..906f0e21 100644
--- a/tests/libdnf/dnf-self-test.c
+++ b/tests/libdnf/dnf-self-test.c
@@ -1225,6 +1225,9 @@ main(int argc, char **argv)
g_log_set_fatal_mask(NULL, G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL);
g_log_set_always_fatal (G_LOG_FATAL_MASK);
+ /* Sets a variable to replace in repository configurations. */
+ g_setenv("DNF_VAR_testdatadir", TESTDATADIR, TRUE);
+
/* tests go here */
g_test_add_func("/libdnf/repo_loader{gpg-asc}", dnf_repo_loader_gpg_asc_func);
g_test_add_func("/libdnf/repo_loader{gpg-wrong-asc}", dnf_repo_loader_gpg_wrong_asc_func);
--
2.31.1

@ -0,0 +1,169 @@
From 983aeea57d75494fd4ea2ff2903f966136278c15 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Wed, 9 Feb 2022 13:17:00 +0100
Subject: [PATCH 28/34] Add private API for filling, reading and verifying new
dnf solv userdata
---
libdnf/hy-iutil-private.hpp | 24 +++++++++
libdnf/hy-iutil.cpp | 102 ++++++++++++++++++++++++++++++++++++
2 files changed, 126 insertions(+)
diff --git a/libdnf/hy-iutil-private.hpp b/libdnf/hy-iutil-private.hpp
index e07b1b51..d498c032 100644
--- a/libdnf/hy-iutil-private.hpp
+++ b/libdnf/hy-iutil-private.hpp
@@ -24,6 +24,30 @@
#include "hy-iutil.h"
#include "hy-types.h"
#include "sack/packageset.hpp"
+#include <array>
+#include <utility>
+
+// Use 8 bytes for libsolv version (API: solv_toolversion)
+// to be future proof even though it currently is "1.2"
+static constexpr const size_t solv_userdata_solv_toolversion_size{8};
+static constexpr const std::array<char, 4> solv_userdata_magic{'\0', 'd', 'n', 'f'};
+static constexpr const std::array<char, 4> solv_userdata_dnf_version{'\0', '1', '.', '0'};
+
+static constexpr const int solv_userdata_size = solv_userdata_solv_toolversion_size + \
+ solv_userdata_magic.size() + \
+ solv_userdata_dnf_version.size() + \
+ CHKSUM_BYTES;
+
+struct SolvUserdata {
+ char dnf_magic[solv_userdata_magic.size()];
+ char dnf_version[solv_userdata_dnf_version.size()];
+ char libsolv_version[solv_userdata_solv_toolversion_size];
+ unsigned char checksum[CHKSUM_BYTES];
+}__attribute__((packed)); ;
+
+int solv_userdata_fill(SolvUserdata *solv_userdata, const unsigned char *checksum, GError** error);
+std::unique_ptr<SolvUserdata> solv_userdata_read(FILE *fp);
+int solv_userdata_verify(const SolvUserdata *solv_userdata, const unsigned char *checksum);
/* crypto utils */
int checksum_cmp(const unsigned char *cs1, const unsigned char *cs2);
diff --git a/libdnf/hy-iutil.cpp b/libdnf/hy-iutil.cpp
index 2af13197..f81ca52f 100644
--- a/libdnf/hy-iutil.cpp
+++ b/libdnf/hy-iutil.cpp
@@ -43,6 +43,7 @@ extern "C" {
#include <solv/evr.h>
#include <solv/solver.h>
#include <solv/solverdebug.h>
+#include <solv/repo_solv.h>
#include <solv/util.h>
#include <solv/pool_parserpmrichdep.h>
}
@@ -182,6 +183,107 @@ int checksum_write(const unsigned char *cs, FILE *fp)
return 0;
}
+static std::array<char, solv_userdata_solv_toolversion_size>
+get_padded_solv_toolversion()
+{
+ std::array<char, solv_userdata_solv_toolversion_size> padded_solv_toolversion{};
+ std::string solv_ver_str{solv_toolversion};
+ std::copy(solv_ver_str.rbegin(), solv_ver_str.rend(), padded_solv_toolversion.rbegin());
+
+ return padded_solv_toolversion;
+}
+
+int
+solv_userdata_fill(SolvUserdata *solv_userdata, const unsigned char *checksum, GError** error)
+{
+ if (strlen(solv_toolversion) > solv_userdata_solv_toolversion_size) {
+ g_set_error(error, DNF_ERROR, DNF_ERROR_INTERNAL_ERROR,
+ _("Libsolv's solv_toolversion is: %zu long but we expect max of: %zu"),
+ strlen(solv_toolversion), solv_userdata_solv_toolversion_size);
+ return 1;
+ }
+
+ // copy dnf solv file magic
+ memcpy(solv_userdata->dnf_magic, solv_userdata_magic.data(), solv_userdata_magic.size());
+
+ // copy dnf solv file version
+ memcpy(solv_userdata->dnf_version, solv_userdata_dnf_version.data(), solv_userdata_dnf_version.size());
+
+ // copy libsolv solv file version
+ memcpy(solv_userdata->libsolv_version, get_padded_solv_toolversion().data(), solv_userdata_solv_toolversion_size);
+
+ // copy checksum
+ memcpy(solv_userdata->checksum, checksum, CHKSUM_BYTES);
+
+ return 0;
+}
+
+
+std::unique_ptr<SolvUserdata>
+solv_userdata_read(FILE *fp)
+{
+ unsigned char *dnf_solvfile_userdata_read = NULL;
+ int dnf_solvfile_userdata_len_read;
+ if (!fp) {
+ return nullptr;
+ }
+
+ int ret_code = solv_read_userdata(fp, &dnf_solvfile_userdata_read, &dnf_solvfile_userdata_len_read);
+ // The userdata layout has to match our struct exactly so we can just cast the memory
+ // allocated by libsolv
+ std::unique_ptr<SolvUserdata> uniq_userdata(reinterpret_cast<SolvUserdata *>(dnf_solvfile_userdata_read));
+ if(ret_code) {
+ g_warning("Failed to read solv userdata: solv_read_userdata returned: %i", ret_code);
+ return nullptr;
+ }
+
+ if (dnf_solvfile_userdata_len_read != solv_userdata_size) {
+ g_warning("Solv userdata length mismatch, read: %i vs expected: %i",
+ dnf_solvfile_userdata_len_read, solv_userdata_size);
+ return nullptr;
+ }
+
+ return uniq_userdata;
+}
+
+gboolean
+solv_userdata_verify(const SolvUserdata *solv_userdata, const unsigned char *checksum)
+{
+ // check dnf solvfile magic bytes
+ if (memcmp(solv_userdata->dnf_magic, solv_userdata_magic.data(), solv_userdata_magic.size()) != 0) {
+ // This is not dnf header do not read after it
+ g_warning("magic bytes don't match, read: %s vs. dnf solvfile magic: %s",
+ solv_userdata->dnf_magic, solv_userdata_magic.data());
+ return FALSE;
+ }
+
+ // check dnf solvfile version
+ if (memcmp(solv_userdata->dnf_version, solv_userdata_dnf_version.data(), solv_userdata_dnf_version.size()) != 0) {
+ // Mismatching dnf solvfile version -> we need to regenerate
+ g_warning("dnf solvfile version doesn't match, read: %s vs. dnf solvfile version: %s",
+ solv_userdata->dnf_version, solv_userdata_dnf_version.data());
+ return FALSE;
+ }
+
+ // check libsolv solvfile version
+ if (memcmp(solv_userdata->libsolv_version, get_padded_solv_toolversion().data(), solv_userdata_solv_toolversion_size) != 0) {
+ // Mismatching libsolv solvfile version -> we need to regenerate
+ g_warning("libsolv solvfile version doesn't match, read: %s vs. libsolv version: %s",
+ solv_userdata->libsolv_version, solv_toolversion);
+ return FALSE;
+ }
+
+ // check solvfile checksum
+ if (checksum_cmp(solv_userdata->checksum, checksum)) {
+ // Mismatching solvfile checksum -> we need to regenerate
+ g_debug("solvfile checksum doesn't match, read: %s vs. repomd checksum: %s",
+ solv_userdata->checksum, checksum);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
int
checksum_type2length(int type)
{
--
2.31.1

@ -0,0 +1,417 @@
From 465a6a59279bd7fa2680c626ca0f10c059276668 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Wed, 9 Feb 2022 13:18:41 +0100
Subject: [PATCH 29/34] Use dnf solv userdata to check versions and checksum
(RhBug:2027445)
Remove unused functions for checksums
= changelog =
msg: Write and check versions and checksums for solvfile cache by using new dnf solvfile userdata (RhBug:2027445)
It is not possible to use old cache files, therefore cache regeneration is triggered automatically.
type: bugfix
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2027445
---
libdnf/dnf-sack.cpp | 254 ++++++++++++++++++++++--------------
libdnf/hy-iutil-private.hpp | 2 -
libdnf/hy-iutil.cpp | 20 ---
3 files changed, 156 insertions(+), 120 deletions(-)
diff --git a/libdnf/dnf-sack.cpp b/libdnf/dnf-sack.cpp
index b9baeaef..61f4807c 100644
--- a/libdnf/dnf-sack.cpp
+++ b/libdnf/dnf-sack.cpp
@@ -225,17 +225,39 @@ dnf_sack_new(void)
return DNF_SACK(g_object_new(DNF_TYPE_SACK, NULL));
}
-static int
-can_use_repomd_cache(FILE *fp_solv, unsigned char cs_repomd[CHKSUM_BYTES])
-{
- unsigned char cs_cache[CHKSUM_BYTES];
-
- if (fp_solv &&
- !checksum_read(cs_cache, fp_solv) &&
- !checksum_cmp(cs_cache, cs_repomd))
- return 1;
+// Try to load cached solv file into repo otherwise return FALSE
+static gboolean
+try_to_use_cached_solvfile(const char *path, Repo *repo, int flags, const unsigned char *checksum, GError **err){
+ FILE *fp_cache = fopen(path, "r");
+ if (!fp_cache) {
+ // Missing cache files (ENOENT) are not an error and can even be expected in some cases
+ // (such as when repo doesn't have updateinfo/prestodelta metadata).
+ // Use g_debug in order not to pollute the log by default with such entries.
+ if (errno == ENOENT) {
+ g_debug("Failed to open solvfile cache: %s: %s", path, strerror(errno));
+ } else {
+ g_warning("Failed to open solvfile cache: %s: %s", path, strerror(errno));
+ }
+ return FALSE;
+ }
+ std::unique_ptr<SolvUserdata> solv_userdata = solv_userdata_read(fp_cache);
+ gboolean ret = TRUE;
+ if (solv_userdata && solv_userdata_verify(solv_userdata.get(), checksum)) {
+ // after reading the header rewind to the begining
+ fseek(fp_cache, 0, SEEK_SET);
+ if (repo_add_solv(repo, fp_cache, flags)) {
+ g_set_error (err,
+ DNF_ERROR,
+ DNF_ERROR_INTERNAL_ERROR,
+ _("repo_add_solv() has failed."));
+ ret = FALSE;
+ }
+ } else {
+ ret = FALSE;
+ }
- return 0;
+ fclose(fp_cache);
+ return ret;
}
void
@@ -375,33 +397,27 @@ load_ext(DnfSack *sack, HyRepo hrepo, _hy_repo_repodata which_repodata,
gboolean done = FALSE;
char *fn_cache = dnf_sack_give_cache_fn(sack, name, suffix);
- fp = fopen(fn_cache, "r");
assert(libdnf::repoGetImpl(hrepo)->checksum);
- if (can_use_repomd_cache(fp, libdnf::repoGetImpl(hrepo)->checksum)) {
- int flags = 0;
- /* the updateinfo is not a real extension */
- if (which_repodata != _HY_REPODATA_UPDATEINFO)
- flags |= REPO_EXTEND_SOLVABLES;
- /* do not pollute the main pool with directory component ids */
- if (which_repodata == _HY_REPODATA_FILENAMES || which_repodata == _HY_REPODATA_OTHER)
- flags |= REPO_LOCALPOOL;
- done = TRUE;
+
+ int flags = 0;
+ /* the updateinfo is not a real extension */
+ if (which_repodata != _HY_REPODATA_UPDATEINFO)
+ flags |= REPO_EXTEND_SOLVABLES;
+ /* do not pollute the main pool with directory component ids */
+ if (which_repodata == _HY_REPODATA_FILENAMES || which_repodata == _HY_REPODATA_OTHER)
+ flags |= REPO_LOCALPOOL;
+ if (try_to_use_cached_solvfile(fn_cache, repo, flags, libdnf::repoGetImpl(hrepo)->checksum, error)) {
g_debug("%s: using cache file: %s", __func__, fn_cache);
- ret = repo_add_solv(repo, fp, flags);
- if (ret) {
- g_set_error_literal (error,
- DNF_ERROR,
- DNF_ERROR_INTERNAL_ERROR,
- _("failed to add solv"));
- return FALSE;
- } else {
- repo_update_state(hrepo, which_repodata, _HY_LOADED_CACHE);
- repo_set_repodata(hrepo, which_repodata, repo->nrepodata - 1);
- }
+ done = TRUE;
+ repo_update_state(hrepo, which_repodata, _HY_LOADED_CACHE);
+ repo_set_repodata(hrepo, which_repodata, repo->nrepodata - 1);
}
+ if (error && *error) {
+ g_prefix_error(error, _("Loading extension cache %s (%d) failed: "), fn_cache, which_repodata);
+ return FALSE;
+ }
+
g_free(fn_cache);
- if (fp)
- fclose(fp);
if (done)
return TRUE;
@@ -514,35 +530,53 @@ write_main(DnfSack *sack, HyRepo hrepo, int switchtosolv, GError **error)
strerror(errno));
goto done;
}
- rc = repo_write(repo, fp);
- rc |= checksum_write(repoImpl->checksum, fp);
- rc |= fclose(fp);
+
+ SolvUserdata solv_userdata;
+ if (solv_userdata_fill(&solv_userdata, repoImpl->checksum, error)) {
+ ret = FALSE;
+ fclose(fp);
+ goto done;
+ }
+
+ Repowriter *writer = repowriter_create(repo);
+ repowriter_set_userdata(writer, &solv_userdata, solv_userdata_size);
+ rc = repowriter_write(writer, fp);
+ repowriter_free(writer);
if (rc) {
+ ret = FALSE;
+ fclose(fp);
+ g_set_error(error,
+ DNF_ERROR,
+ DNF_ERROR_INTERNAL_ERROR,
+ _("While writing primary cache %s repowriter write failed: %i, error: %s"),
+ tmp_fn_templ, rc, pool_errstr(repo->pool));
+ goto done;
+ }
+
+ if (fclose(fp)) {
ret = FALSE;
g_set_error (error,
DNF_ERROR,
DNF_ERROR_FILE_INVALID,
- _("write_main() failed writing data: %i"), rc);
+ _("Failed closing tmp file %s: %s"),
+ tmp_fn_templ, strerror(errno));
goto done;
}
}
if (switchtosolv && repo_is_one_piece(repo)) {
+ repo_empty(repo, 1);
/* switch over to written solv file activate paging */
- FILE *fp = fopen(tmp_fn_templ, "r");
- if (fp) {
- repo_empty(repo, 1);
- rc = repo_add_solv(repo, fp, 0);
- fclose(fp);
- if (rc) {
- /* this is pretty fatal */
- ret = FALSE;
- g_set_error_literal (error,
- DNF_ERROR,
- DNF_ERROR_FILE_INVALID,
- _("write_main() failed to re-load "
- "written solv file"));
- goto done;
- }
+ gboolean loaded = try_to_use_cached_solvfile(tmp_fn_templ, repo, 0, repoImpl->checksum, error);
+ if (error && *error) {
+ g_prefix_error(error, _("Failed to use newly written primary cache: %s: "), tmp_fn_templ);
+ ret = FALSE;
+ goto done;
+ }
+ if (!loaded) {
+ g_set_error(error, DNF_ERROR, DNF_ERROR_INTERNAL_ERROR,
+ _("Failed to use newly written primary cache: %s"), tmp_fn_templ);
+ ret = FALSE;
+ goto done;
}
}
@@ -569,20 +603,6 @@ write_ext_updateinfo_filter(Repo *repo, Repokey *key, void *kfdata)
return repo_write_stdkeyfilter(repo, key, 0);
}
-static int
-write_ext_updateinfo(HyRepo hrepo, Repodata *data, FILE *fp)
-{
- auto repoImpl = libdnf::repoGetImpl(hrepo);
- Repo *repo = repoImpl->libsolvRepo;
- int oldstart = repo->start;
- repo->start = repoImpl->main_end;
- repo->nsolvables -= repoImpl->main_nsolvables;
- int res = repo_write_filtered(repo, fp, write_ext_updateinfo_filter, data, 0);
- repo->start = oldstart;
- repo->nsolvables += repoImpl->main_nsolvables;
- return res;
-}
-
static gboolean
write_ext(DnfSack *sack, HyRepo hrepo, _hy_repo_repodata which_repodata,
const char *suffix, GError **error)
@@ -611,37 +631,78 @@ write_ext(DnfSack *sack, HyRepo hrepo, _hy_repo_repodata which_repodata,
FILE *fp = fdopen(tmp_fd, "w+");
g_debug("%s: storing %s to: %s", __func__, repo->name, tmp_fn_templ);
- if (which_repodata != _HY_REPODATA_UPDATEINFO)
- ret |= repodata_write(data, fp);
- else
- ret |= write_ext_updateinfo(hrepo, data, fp);
- ret |= checksum_write(repoImpl->checksum, fp);
- ret |= fclose(fp);
+
+ SolvUserdata solv_userdata;
+ if (solv_userdata_fill(&solv_userdata, repoImpl->checksum, error)) {
+ fclose(fp);
+ success = FALSE;
+ goto done;
+ }
+
+ Repowriter *writer = repowriter_create(repo);
+ repowriter_set_userdata(writer, &solv_userdata, solv_userdata_size);
+ if (which_repodata != _HY_REPODATA_UPDATEINFO) {
+ repowriter_set_repodatarange(writer, data->repodataid, data->repodataid + 1);
+ repowriter_set_flags(writer, REPOWRITER_NO_STORAGE_SOLVABLE);
+ ret = repowriter_write(writer, fp);
+ } else {
+ // write only updateinfo repodata
+ int oldstart = repo->start;
+ repo->start = repoImpl->main_end;
+ repo->nsolvables -= repoImpl->main_nsolvables;
+ repowriter_set_flags(writer, REPOWRITER_LEGACY);
+ repowriter_set_keyfilter(writer, write_ext_updateinfo_filter, data);
+ repowriter_set_keyqueue(writer, 0);
+ ret = repowriter_write(writer, fp);
+ repo->start = oldstart;
+ repo->nsolvables += repoImpl->main_nsolvables;
+ }
+ repowriter_free(writer);
if (ret) {
+ success = FALSE;
+ fclose(fp);
+ g_set_error (error,
+ DNF_ERROR,
+ DNF_ERROR_INTERNAL_ERROR,
+ _("While writing extension cache %s (%d): repowriter write failed: %i, error: %s"),
+ tmp_fn_templ, which_repodata, ret, pool_errstr(repo->pool));
+ goto done;
+ }
+
+ if (fclose(fp)) {
success = FALSE;
g_set_error (error,
DNF_ERROR,
- DNF_ERROR_FAILED,
- _("write_ext(%1$d) has failed: %2$d"),
- which_repodata, ret);
+ DNF_ERROR_FILE_INVALID,
+ _("While writing extension cache (%d): cannot close temporary file: %s"),
+ which_repodata, tmp_fn_templ);
goto done;
}
}
if (repo_is_one_piece(repo) && which_repodata != _HY_REPODATA_UPDATEINFO) {
/* switch over to written solv file activate paging */
- FILE *fp = fopen(tmp_fn_templ, "r");
- if (fp) {
- int flags = REPO_USE_LOADING | REPO_EXTEND_SOLVABLES;
- /* do not pollute the main pool with directory component ids */
- if (which_repodata == _HY_REPODATA_FILENAMES || which_repodata == _HY_REPODATA_OTHER)
- flags |= REPO_LOCALPOOL;
- repodata_extend_block(data, repo->start, repo->end - repo->start);
- data->state = REPODATA_LOADING;
- repo_add_solv(repo, fp, flags);
- data->state = REPODATA_AVAILABLE;
- fclose(fp);
+ int flags = REPO_USE_LOADING | REPO_EXTEND_SOLVABLES;
+ /* do not pollute the main pool with directory component ids */
+ if (which_repodata == _HY_REPODATA_FILENAMES || which_repodata == _HY_REPODATA_OTHER)
+ flags |= REPO_LOCALPOOL;
+ repodata_extend_block(data, repo->start, repo->end - repo->start);
+ data->state = REPODATA_LOADING;
+ int loaded = try_to_use_cached_solvfile(tmp_fn_templ, repo, flags, repoImpl->checksum, error);
+ if (error && *error) {
+ g_prefix_error(error, _("Failed to use newly written extension cache: %s (%d): "),
+ tmp_fn_templ, which_repodata);
+ success = FALSE;
+ goto done;
+ }
+ if (!loaded) {
+ g_set_error(error, DNF_ERROR, DNF_ERROR_INTERNAL_ERROR,
+ _("Failed to use newly written extension cache: %s (%d)"), tmp_fn_templ, which_repodata);
+ success = FALSE;
+ goto done;
}
+
+ data->state = REPODATA_AVAILABLE;
}
if (!mv(tmp_fn_templ, fn, error)) {
@@ -672,7 +733,7 @@ load_yum_repo(DnfSack *sack, HyRepo hrepo, GError **error)
FILE *fp_primary = NULL;
FILE *fp_repomd = NULL;
- FILE *fp_cache = fopen(fn_cache, "r");
+
if (!fn_repomd) {
g_set_error (error,
DNF_ERROR,
@@ -693,18 +754,17 @@ load_yum_repo(DnfSack *sack, HyRepo hrepo, GError **error)
}
checksum_fp(repoImpl->checksum, fp_repomd);
- if (can_use_repomd_cache(fp_cache, repoImpl->checksum)) {
+ if (try_to_use_cached_solvfile(fn_cache, repo, 0, repoImpl->checksum, error)) {
const char *chksum = pool_checksum_str(pool, repoImpl->checksum);
g_debug("using cached %s (0x%s)", name, chksum);
- if (repo_add_solv(repo, fp_cache, 0)) {
- g_set_error (error,
- DNF_ERROR,
- DNF_ERROR_INTERNAL_ERROR,
- _("repo_add_solv() has failed."));
- retval = FALSE;
- goto out;
- }
repoImpl->state_main = _HY_LOADED_CACHE;
+ goto out;
+ }
+
+ if (error && *error) {
+ g_prefix_error(error, _("While loading repository failed to use %s: "), fn_cache);
+ retval = FALSE;
+ goto out;
} else {
auto primary = hrepo->getMetadataPath(MD_TYPE_PRIMARY);
if (primary.empty()) {
@@ -733,8 +793,6 @@ load_yum_repo(DnfSack *sack, HyRepo hrepo, GError **error)
repoImpl->state_main = _HY_LOADED_FETCH;
}
out:
- if (fp_cache)
- fclose(fp_cache);
if (fp_repomd)
fclose(fp_repomd);
if (fp_primary)
diff --git a/libdnf/hy-iutil-private.hpp b/libdnf/hy-iutil-private.hpp
index d498c032..efc91c63 100644
--- a/libdnf/hy-iutil-private.hpp
+++ b/libdnf/hy-iutil-private.hpp
@@ -52,9 +52,7 @@ int solv_userdata_verify(const SolvUserdata *solv_userdata, const unsigned char
/* crypto utils */
int checksum_cmp(const unsigned char *cs1, const unsigned char *cs2);
int checksum_fp(unsigned char *out, FILE *fp);
-int checksum_read(unsigned char *csout, FILE *fp);
int checksum_stat(unsigned char *out, FILE *fp);
-int checksum_write(const unsigned char *cs, FILE *fp);
int checksumt_l2h(int type);
const char *pool_checksum_str(Pool *pool, const unsigned char *chksum);
diff --git a/libdnf/hy-iutil.cpp b/libdnf/hy-iutil.cpp
index f81ca52f..c409a10a 100644
--- a/libdnf/hy-iutil.cpp
+++ b/libdnf/hy-iutil.cpp
@@ -142,17 +142,6 @@ checksum_fp(unsigned char *out, FILE *fp)
return 0;
}
-/* calls rewind(fp) before returning */
-int
-checksum_read(unsigned char *csout, FILE *fp)
-{
- if (fseek(fp, -32, SEEK_END) ||
- fread(csout, CHKSUM_BYTES, 1, fp) != 1)
- return 1;
- rewind(fp);
- return 0;
-}
-
/* does not move the fp position */
int
checksum_stat(unsigned char *out, FILE *fp)
@@ -174,15 +163,6 @@ checksum_stat(unsigned char *out, FILE *fp)
return 0;
}
-/* moves fp to the end of file */
-int checksum_write(const unsigned char *cs, FILE *fp)
-{
- if (fseek(fp, 0, SEEK_END) ||
- fwrite(cs, CHKSUM_BYTES, 1, fp) != 1)
- return 1;
- return 0;
-}
-
static std::array<char, solv_userdata_solv_toolversion_size>
get_padded_solv_toolversion()
{
--
2.31.1

@ -0,0 +1,83 @@
From 1e0f8f66f6ff30e177c41be7d72330d5eccf2ff8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Wed, 9 Feb 2022 13:24:06 +0100
Subject: [PATCH 30/34] Update unittest to test the new private dnf solvfile
API
---
tests/hawkey/test_iutil.cpp | 34 ++++++++++++++++++++++------------
1 file changed, 22 insertions(+), 12 deletions(-)
diff --git a/tests/hawkey/test_iutil.cpp b/tests/hawkey/test_iutil.cpp
index 8d00cc94..f3c04782 100644
--- a/tests/hawkey/test_iutil.cpp
+++ b/tests/hawkey/test_iutil.cpp
@@ -24,6 +24,8 @@
#include <solv/pool.h>
+#include <solv/repo.h>
+#include <solv/repo_write.h>
#include "libdnf/hy-util.h"
@@ -97,28 +99,36 @@ START_TEST(test_checksum)
}
END_TEST
-START_TEST(test_checksum_write_read)
+START_TEST(test_dnf_solvfile_userdata)
{
char *new_file = solv_dupjoin(test_globals.tmpdir,
- "/test_checksum_write_read", NULL);
+ "/test_dnf_solvfile_userdata", NULL);
build_test_file(new_file);
unsigned char cs_computed[CHKSUM_BYTES];
- unsigned char cs_read[CHKSUM_BYTES];
- FILE *fp = fopen(new_file, "r");
+ FILE *fp = fopen(new_file, "r+");
checksum_fp(cs_computed, fp);
- // fails, file opened read-only:
- fail_unless(checksum_write(cs_computed, fp) == 1);
- fclose(fp);
- fp = fopen(new_file, "r+");
- fail_if(checksum_write(cs_computed, fp));
+
+ SolvUserdata solv_userdata;
+ fail_if(solv_userdata_fill(&solv_userdata, cs_computed, NULL));
+
+ Pool *pool = pool_create();
+ Repo *repo = repo_create(pool, "test_repo");
+ Repowriter *writer = repowriter_create(repo);
+ repowriter_set_userdata(writer, &solv_userdata, solv_userdata_size);
+ fail_if(repowriter_write(writer, fp));
+ repowriter_free(writer);
fclose(fp);
+
fp = fopen(new_file, "r");
- fail_if(checksum_read(cs_read, fp));
- fail_if(checksum_cmp(cs_computed, cs_read));
+ std::unique_ptr<SolvUserdata> dnf_solvfile = solv_userdata_read(fp);
+ fail_unless(dnf_solvfile);
+ fail_unless(solv_userdata_verify(dnf_solvfile.get(), cs_computed));
fclose(fp);
g_free(new_file);
+ repo_free(repo, 0);
+ pool_free(pool);
}
END_TEST
@@ -181,7 +191,7 @@ iutil_suite(void)
TCase *tc = tcase_create("Main");
tcase_add_test(tc, test_abspath);
tcase_add_test(tc, test_checksum);
- tcase_add_test(tc, test_checksum_write_read);
+ tcase_add_test(tc, test_dnf_solvfile_userdata);
tcase_add_test(tc, test_mkcachedir);
tcase_add_test(tc, test_version_split);
suite_add_tcase(s, tc);
--
2.31.1

@ -0,0 +1,38 @@
From 893eb087e56588d62e81e91e5d283003bd80552a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Tue, 8 Mar 2022 11:43:38 +0100
Subject: [PATCH 31/34] Increase required libsolv version for cache versioning
---
CMakeLists.txt | 2 +-
libdnf.spec | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 60cf1b8c..d895b2bf 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -51,7 +51,7 @@ endif()
# build dependencies
find_package(Gpgme REQUIRED)
-find_package(LibSolv 0.6.30 REQUIRED COMPONENTS ext)
+find_package(LibSolv 0.7.20 REQUIRED COMPONENTS ext)
find_package(OpenSSL REQUIRED)
diff --git a/libdnf.spec b/libdnf.spec
index a849cdea..aa51dd28 100644
--- a/libdnf.spec
+++ b/libdnf.spec
@@ -1,5 +1,5 @@
-%global libsolv_version 0.7.17
-%global libmodulemd_version 2.11.2-2
+%global libsolv_version 0.7.21
+%global libmodulemd_version 2.13.0
%global librepo_version 1.13.1
%global dnf_conflict 4.3.0
%global swig_version 3.0.12
--
2.31.1

@ -0,0 +1,46 @@
From b636af779fcdab326eef7bbb74912254c2fa2b0c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Thu, 17 Mar 2022 10:34:24 +0100
Subject: [PATCH 32/34] Add more specific error handling for loading repomd and
primary
---
libdnf/dnf-sack.cpp | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/libdnf/dnf-sack.cpp b/libdnf/dnf-sack.cpp
index 61f4807c..8e11b8f8 100644
--- a/libdnf/dnf-sack.cpp
+++ b/libdnf/dnf-sack.cpp
@@ -780,13 +780,24 @@ load_yum_repo(DnfSack *sack, HyRepo hrepo, GError **error)
fp_primary = solv_xfopen(primary.c_str(), "r");
assert(fp_primary);
- g_debug("fetching %s", name);
- if (repo_add_repomdxml(repo, fp_repomd, 0) || \
- repo_add_rpmmd(repo, fp_primary, 0, 0)) {
+ g_debug("Loading repomd: %s", fn_repomd);
+ if (repo_add_repomdxml(repo, fp_repomd, 0)) {
g_set_error (error,
DNF_ERROR,
DNF_ERROR_INTERNAL_ERROR,
- _("repo_add_repomdxml/rpmmd() has failed."));
+ _("Loading repomd has failed: %s"),
+ pool_errstr(repo->pool));
+ retval = FALSE;
+ goto out;
+ }
+
+ g_debug("Loading primary: %s", primary.c_str());
+ if (repo_add_rpmmd(repo, fp_primary, 0, 0)) {
+ g_set_error (error,
+ DNF_ERROR,
+ DNF_ERROR_INTERNAL_ERROR,
+ _("Loading primary has failed: %s"),
+ pool_errstr(repo->pool));
retval = FALSE;
goto out;
}
--
2.31.1

@ -0,0 +1,74 @@
From c5919efe898294420ec8e91e4eed5b9081e681c5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hr=C3=A1zk=C3=BD?= <lhrazky@redhat.com>
Date: Thu, 17 Feb 2022 18:18:16 +0100
Subject: [PATCH 33/34] libdnf/transaction/RPMItem: Fix handling transaction id
in resolveTransactionItemReason
The maxTransactionId argument was ignored, the method was always returning the
reason from the last transaction. This is the correct result for
maxTransactionId = -1. In a couple of places the method is called with
maxTransactionId = -2. Fixing this would mean nontrivial changes to the
logic which could potentially break something else, so I'm leaving this
behavior unchanged.
For non-negative values of maxTransactionId (with which it's not being called
anywhere in dnf codebase), the commit adds a condition to SELECT only
transaction ids less than or equal to maxTransactionId.
= changelog =
msg: Fix handling transaction id in resolveTransactionItemReason
type: bugfix
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2053014
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2010259
---
libdnf/transaction/RPMItem.cpp | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/libdnf/transaction/RPMItem.cpp b/libdnf/transaction/RPMItem.cpp
index 5f667ab9..ecce789d 100644
--- a/libdnf/transaction/RPMItem.cpp
+++ b/libdnf/transaction/RPMItem.cpp
@@ -255,7 +255,11 @@ RPMItem::resolveTransactionItemReason(SQLite3Ptr conn,
const std::string &arch,
int64_t maxTransactionId)
{
- const char *sql = R"**(
+ // NOTE: All negative maxTransactionId values are treated the same. The
+ // method is called with maxTransactionId = -2 in a couple of places, the
+ // semantics here have been the same as with -1 for a long time. If it
+ // ain't broke...
+ std::string sql = R"**(
SELECT
ti.action as action,
ti.reason as reason
@@ -271,14 +275,25 @@ RPMItem::resolveTransactionItemReason(SQLite3Ptr conn,
AND ti.action not in (3, 5, 7, 10)
AND i.name = ?
AND i.arch = ?
+ )**";
+
+ if (maxTransactionId >= 0) {
+ sql.append(" AND ti.trans_id <= ?");
+ }
+
+ sql.append(R"**(
ORDER BY
ti.trans_id DESC
LIMIT 1
- )**";
+ )**");
if (arch != "") {
SQLite3::Query query(*conn, sql);
- query.bindv(name, arch);
+ if (maxTransactionId >= 0) {
+ query.bindv(name, arch, maxTransactionId);
+ } else {
+ query.bindv(name, arch);
+ }
if (query.step() == SQLite3::Statement::StepResult::ROW) {
auto action = static_cast< TransactionItemAction >(query.get< int64_t >("action"));
--
2.31.1

@ -0,0 +1,33 @@
From c303b7c3723f3e9fbc43963a62237ea17516fc6b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hr=C3=A1zk=C3=BD?= <lhrazky@redhat.com>
Date: Thu, 17 Feb 2022 18:30:14 +0100
Subject: [PATCH 34/34] libdnf/transaction/TransactionItem: Set short action
for Reason Change
Sets the "short" (one letter) representation of the Reason Change action
to "C".
This was likely not ever used before as the only way to create a
transaction with a reason change and something else is rolling back
multiple transactions, which was broken.
---
libdnf/transaction/TransactionItem.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/libdnf/transaction/TransactionItem.cpp b/libdnf/transaction/TransactionItem.cpp
index 3b43d1f1..4358038e 100644
--- a/libdnf/transaction/TransactionItem.cpp
+++ b/libdnf/transaction/TransactionItem.cpp
@@ -51,8 +51,7 @@ static const std::map< TransactionItemAction, std::string > transactionItemActio
{TransactionItemAction::REMOVE, "E"},
{TransactionItemAction::REINSTALL, "R"},
{TransactionItemAction::REINSTALLED, "R"},
- // TODO: replace "?" with something better
- {TransactionItemAction::REASON_CHANGE, "?"},
+ {TransactionItemAction::REASON_CHANGE, "C"},
};
/*
--
2.31.1

@ -0,0 +1,45 @@
From c4ee580c73375060b6eb5b3414636688e3d601c3 Mon Sep 17 00:00:00 2001
From: Marek Blaha <mblaha@redhat.com>
Date: Fri, 10 Jun 2022 15:29:56 +0200
Subject: [PATCH] Do not print errors on failovermethod repo option
(RhBug:2039906)
= changelog =
msg: Do not print errors if repository config contains failovermethod option
type: bugfix
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2039906
---
libdnf/conf/ConfigRepo.cpp | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/libdnf/conf/ConfigRepo.cpp b/libdnf/conf/ConfigRepo.cpp
index e98ac0af..0cb52f58 100644
--- a/libdnf/conf/ConfigRepo.cpp
+++ b/libdnf/conf/ConfigRepo.cpp
@@ -22,6 +22,8 @@
#include "Const.hpp"
#include "Config-private.hpp"
+#include "bgettext/bgettext-lib.h"
+
namespace libdnf {
class ConfigRepo::Impl {
@@ -174,6 +176,14 @@ ConfigRepo::Impl::Impl(Config & owner, ConfigMain & mainConfig)
owner.optBinds().add("enabled_metadata", enabled_metadata);
owner.optBinds().add("user_agent", user_agent);
owner.optBinds().add("countme", countme);
+ owner.optBinds().add("failovermethod", failovermethod,
+ [&](Option::Priority priority, const std::string & value){
+ if (value != "priority") {
+ throw Option::InvalidValue(_("only the value 'priority' is supported."));
+ }
+ failovermethod.set(priority, value);
+ }, nullptr, false
+ );
owner.optBinds().add("sslverifystatus", sslverifystatus);
}
--
2.36.1

@ -0,0 +1,24 @@
From 9dbd5f8f0ac3d6d3fab9147a3208623cba698682 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 Jun 2022 17:26:44 +0200
Subject: [PATCH] sack/query.hpp: Add a missing include
---
libdnf/sack/query.hpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/libdnf/sack/query.hpp b/libdnf/sack/query.hpp
index 9e49761c..306b24e3 100644
--- a/libdnf/sack/query.hpp
+++ b/libdnf/sack/query.hpp
@@ -26,6 +26,7 @@
#include "../hy-types.h"
#include "../hy-query.h"
#include "../hy-subject.h"
+#include "../nevra.hpp"
#include "../repo/solvable/Dependency.hpp"
#include "../repo/solvable/DependencyContainer.hpp"
#include "../transaction/Swdb.hpp"
--
2.36.1

@ -0,0 +1,128 @@
From 876393d5d0cd5f806415dcdc90168e58e66da916 Mon Sep 17 00:00:00 2001
From: Jaroslav Rohel <jrohel@redhat.com>
Date: Mon, 28 Mar 2022 07:29:48 +0200
Subject: [PATCH] context: dnf_context_remove accepts `<package-spec>` as dnf,
unify code
Prior to change, the `dnf_context_remove` function only accepted
the package name (without globs). It was not possible to enter more detailed
specifications and thus, for example, select a specific version of the package
to uninstall - for example, which kernel we want to uninstall.
This patch adds full `<package-spec>` support as in dnf, including support
for globs (wildcards) and searching against 'provides' and 'file provides'.
Better error handling for `hy_goal_upgrade_selector` in` dnf_context_update`.
Unification of the function code `dnf_context_install`, `dnf_context_remove`,
`dnf_context_update`.
= changelog =
msg: context: Support <package-spec> (NEVRA forms, provides, file provides) including globs in the dnf_context_remove func
type: enhancement
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2084602
---
libdnf/dnf-context.cpp | 46 ++++++++++++++++++++++++------------------
1 file changed, 26 insertions(+), 20 deletions(-)
diff --git a/libdnf/dnf-context.cpp b/libdnf/dnf-context.cpp
index 6cb0011b..4b055f03 100644
--- a/libdnf/dnf-context.cpp
+++ b/libdnf/dnf-context.cpp
@@ -2391,10 +2391,9 @@ dnf_context_run(DnfContext *context, GCancellable *cancellable, GError **error)
* Since: 0.1.0
**/
gboolean
-dnf_context_install (DnfContext *context, const gchar *name, GError **error) try
+dnf_context_install(DnfContext *context, const gchar *name, GError **error) try
{
DnfContextPrivate *priv = GET_PRIVATE (context);
- g_autoptr(GPtrArray) selector_matches = NULL;
/* create sack and add sources */
if (priv->sack == NULL) {
@@ -2405,7 +2404,7 @@ dnf_context_install (DnfContext *context, const gchar *name, GError **error) try
g_auto(HySubject) subject = hy_subject_create(name);
g_auto(HySelector) selector = hy_subject_get_best_selector(subject, priv->sack, NULL, FALSE, NULL);
- selector_matches = hy_selector_matches(selector);
+ g_autoptr(GPtrArray) selector_matches = hy_selector_matches(selector);
if (selector_matches->len == 0) {
g_set_error(error,
DNF_ERROR,
@@ -2438,31 +2437,33 @@ gboolean
dnf_context_remove(DnfContext *context, const gchar *name, GError **error) try
{
DnfContextPrivate *priv = GET_PRIVATE(context);
- GPtrArray *pkglist;
- hy_autoquery HyQuery query = NULL;
- gboolean ret = TRUE;
- guint i;
/* create sack and add repos */
if (priv->sack == NULL) {
dnf_state_reset(priv->state);
- ret = dnf_context_setup_sack(context, priv->state, error);
- if (!ret)
+ if (!dnf_context_setup_sack(context, priv->state, error))
return FALSE;
}
- /* find installed packages to remove */
- query = hy_query_create(priv->sack);
- query->installed();
- hy_query_filter(query, HY_PKG_NAME, HY_EQ, name);
- pkglist = hy_query_run(query);
+ libdnf::Query query(priv->sack, libdnf::Query::ExcludeFlags::APPLY_EXCLUDES);
+ query.installed();
+ auto ret = query.filterSubject(name, nullptr, false, true, true, true);
+ if (!ret.first) {
+ g_set_error(error,
+ DNF_ERROR,
+ DNF_ERROR_PACKAGE_NOT_FOUND,
+ "No installed package matches '%s'", name);
+ return FALSE;
+ }
+
+ g_autoptr(GPtrArray) packages = query.run();
/* add each package */
- for (i = 0; i < pkglist->len; i++) {
- auto pkg = static_cast<DnfPackage *>(g_ptr_array_index(pkglist, i));
+ for (guint i = 0; i < packages->len; i++) {
+ auto pkg = static_cast<DnfPackage *>(g_ptr_array_index(packages, i));
hy_goal_erase(priv->goal, pkg);
}
- g_ptr_array_unref(pkglist);
+
return TRUE;
} CATCH_TO_GERROR(FALSE)
@@ -2493,8 +2494,7 @@ dnf_context_update(DnfContext *context, const gchar *name, GError **error) try
}
g_auto(HySubject) subject = hy_subject_create(name);
- g_auto(HySelector) selector = hy_subject_get_best_selector(subject, priv->sack, NULL, FALSE,
- NULL);
+ g_auto(HySelector) selector = hy_subject_get_best_selector(subject, priv->sack, NULL, FALSE, NULL);
g_autoptr(GPtrArray) selector_matches = hy_selector_matches(selector);
if (selector_matches->len == 0) {
g_set_error(error,
@@ -2504,8 +2504,14 @@ dnf_context_update(DnfContext *context, const gchar *name, GError **error) try
return FALSE;
}
- if (hy_goal_upgrade_selector(priv->goal, selector))
+ int ret = hy_goal_upgrade_selector(priv->goal, selector);
+ if (ret != 0) {
+ g_set_error(error,
+ DNF_ERROR,
+ ret,
+ "Ill-formed Selector '%s'", name);
return FALSE;
+ }
return TRUE;
} CATCH_TO_GERROR(FALSE)
--
2.36.1

@ -0,0 +1,62 @@
From 44d75a36d7c8a933119e5b63f180a8c23715ec51 Mon Sep 17 00:00:00 2001
From: Jaroslav Rohel <jrohel@redhat.com>
Date: Mon, 28 Mar 2022 07:51:45 +0200
Subject: [PATCH] context: Fix doc dnf_context_install/remove/update/distrosync
Functions do not support groups - only packages are supported.
The `dnf_context_remove` function marks all matching packages for removal
- not just the oldest one.
---
libdnf/dnf-context.cpp | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/libdnf/dnf-context.cpp b/libdnf/dnf-context.cpp
index 4b055f03..fe005430 100644
--- a/libdnf/dnf-context.cpp
+++ b/libdnf/dnf-context.cpp
@@ -2379,7 +2379,7 @@ dnf_context_run(DnfContext *context, GCancellable *cancellable, GError **error)
/**
* dnf_context_install:
* @context: a #DnfContext instance.
- * @name: A package or group name, e.g. "firefox" or "@gnome-desktop"
+ * @name: A package specification (NEVRA forms, provide, file provide, globs supported) e.g. "firefox"
* @error: A #GError or %NULL
*
* Finds a remote package and marks it to be installed.
@@ -2422,12 +2422,12 @@ dnf_context_install(DnfContext *context, const gchar *name, GError **error) try
/**
* dnf_context_remove:
* @context: a #DnfContext instance.
- * @name: A package or group name, e.g. "firefox" or "@gnome-desktop"
+ * @name: A package specification (NEVRA forms, provide, file provide, globs supported) e.g. "firefox"
* @error: A #GError or %NULL
*
* Finds an installed package and marks it to be removed.
*
- * If multiple packages are available then only the oldest package is removed.
+ * If multiple packages are available, all of them will be removed.
*
* Returns: %TRUE for success, %FALSE otherwise
*
@@ -2470,7 +2470,7 @@ dnf_context_remove(DnfContext *context, const gchar *name, GError **error) try
/**
* dnf_context_update:
* @context: a #DnfContext instance.
- * @name: A package or group name, e.g. "firefox" or "@gnome-desktop"
+ * @name: A package specification (NEVRA forms, provide, file provide, globs supported) e.g. "firefox"
* @error: A #GError or %NULL
*
* Finds an installed and remote package and marks it to be updated.
@@ -2548,7 +2548,7 @@ dnf_context_update_all (DnfContext *context,
/**
* dnf_context_distrosync:
* @context: a #DnfContext instance.
- * @name: A package or group name, e.g. "firefox" or "@gnome-desktop"
+ * @name: A package specification (NEVRA forms, provide, file provide, globs supported) e.g. "firefox"
* @error: A #GError or %NULL
*
* Finds an installed and remote package and marks it to be synchronized with remote version.
--
2.36.1

@ -0,0 +1,100 @@
From cf4893a0128c567ed1fdd1b02c9cf2b43bfb02f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Mon, 30 May 2022 08:59:41 +0200
Subject: [PATCH] advisory upgrade: filter out advPkgs with different arch
This prevents a situation in security upgrades where libsolv cannot
upgrade dependent pkgs because we ask for an upgrade of different arch:
We can get the following testcase if libdnf has filtered out
json-c-2-2.el8.x86_64@rhel-8-for-x86_64-baseos-rpms
(because there is an advisory for already installed json-c-1-1.el8.x86_64) but
json-c-2-2.el8.i686@rhel-8-for-x86_64-baseos-rpms is not filtered out because
it has different architecture. The resulting transaction doesn't work.
```
repo @System -99.-1000 testtags <inline>
#>=Pkg: bind-libs-lite 1 1.el8 x86_64
#>=Pkg: json-c 1 1.el8 x86_64
repo rhel-8-for-x86_64-baseos-rpms -99.-1000 testtags <inline>
#>=Pkg: json-c 2 2.el8 x86_64
#>=Prv: libjson-c.so.4()(64bit)
#>
#>=Pkg: json-c 2 2.el8 i686
#>=Prv: libjson-c.so.4()
#>
#>=Pkg: bind-libs-lite 2 2.el8 x86_64
#>=Req: libjson-c.so.4()(64bit)
system x86_64 rpm @System
job update oneof json-c-1-1.el8.x86_64@@System json-c-2-2.el8.i686@rhel-8-for-x86_64-baseos-rpms bind-libs-lite-2-2.el8.x86_64@rhel-8-for-x86_64-baseos-rpms [forcebest,targeted,setevr,setarch]
result transaction,problems <inline>
#>problem f06d81a4 info package bind-libs-lite-2-2.el8.x86_64 requires libjson-c.so.4()(64bit), but none of the providers can be installed
#>problem f06d81a4 solution 96f9031b allow bind-libs-lite-1-1.el8.x86_64@@System
#>problem f06d81a4 solution c8daf94f allow json-c-2-2.el8.x86_64@rhel-8-for-x86_64-baseos-rpms
#>upgrade bind-libs-lite-1-1.el8.x86_64@@System bind-libs-lite-2-2.el8.x86_64@rhel-8-for-x86_64-baseos-rpms
#>upgrade json-c-1-1.el8.x86_64@@System json-c-2-2.el8.x86_64@rhel-8-for-x86_64-baseos-rpms```
```
= changelog =
msg: Filter out advisory pkgs with different arch during advisory upgrade, fixes possible problems in dependency resulution.
type: bugfix
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2088149
---
libdnf/sack/query.cpp | 25 +++++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)
diff --git a/libdnf/sack/query.cpp b/libdnf/sack/query.cpp
index ac2736b5..03d39659 100644
--- a/libdnf/sack/query.cpp
+++ b/libdnf/sack/query.cpp
@@ -1877,12 +1877,6 @@ Query::Impl::filterAdvisory(const Filter & f, Map *m, int keyname)
std::vector<Solvable *> candidates;
std::vector<Solvable *> installed_solvables;
- Id id = -1;
- while ((id = resultPset->next(id)) != -1) {
- candidates.push_back(pool_id2solvable(pool, id));
- }
- NameArchEVRComparator cmp_key(pool);
-
if (cmp_type & HY_UPGRADE) {
Query installed(sack, ExcludeFlags::IGNORE_EXCLUDES);
installed.installed();
@@ -1893,6 +1887,18 @@ Query::Impl::filterAdvisory(const Filter & f, Map *m, int keyname)
installed_solvables.push_back(pool_id2solvable(pool, installed_id));
}
std::sort(installed_solvables.begin(), installed_solvables.end(), NameArchSolvableComparator);
+ Id id = -1;
+ while ((id = resultPset->next(id)) != -1) {
+ Solvable * s = pool_id2solvable(pool, id);
+ // 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).
+ // Otherwise a pkg with different Arch than installed can end up in upgrade set which is wrong.
+ // It can result in dependency issues, reported as: RhBug:2088149.
+ 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);
+ }
+ }
// Apply security filters only to packages with lower priority - to unify behaviour upgrade
// and upgrade-minimal
@@ -1915,7 +1921,14 @@ Query::Impl::filterAdvisory(const Filter & f, Map *m, int keyname)
}
}
std::swap(candidates, priority_candidates);
+ } else {
+ Id id = -1;
+ while ((id = resultPset->next(id)) != -1) {
+ candidates.push_back(pool_id2solvable(pool, id));
+ }
}
+
+ NameArchEVRComparator cmp_key(pool);
std::sort(candidates.begin(), candidates.end(), cmp_key);
for (auto & advisoryPkg : pkgs) {
if (cmp_type & HY_UPGRADE) {
--
2.36.1

@ -0,0 +1,71 @@
From 652977360c4253faff9e95d35c603b2f585671fe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ale=C5=A1=20Mat=C4=9Bj?= <amatej@redhat.com>
Date: Tue, 5 Jul 2022 09:02:22 +0200
Subject: [PATCH] Add obsoletes to filtering for advisory candidates
Patch https://github.com/rpm-software-management/libdnf/pull/1526
introduced a regression where we no longer do a security upgrade if a
package A is installed and package B obsoletes A and B is available in two
versions while there is an advisory for the second version.
Test: https://github.com/rpm-software-management/ci-dnf-stack/pull/1130
---
libdnf/sack/query.cpp | 32 ++++++++++++++++++++++++++++----
1 file changed, 28 insertions(+), 4 deletions(-)
diff --git a/libdnf/sack/query.cpp b/libdnf/sack/query.cpp
index 03d39659..5355f9f7 100644
--- a/libdnf/sack/query.cpp
+++ b/libdnf/sack/query.cpp
@@ -1878,6 +1878,13 @@ 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.
+ // It can result in dependency issues, reported as: RhBug:2088149.
+
Query installed(sack, ExcludeFlags::IGNORE_EXCLUDES);
installed.installed();
installed.addFilter(HY_PKG_LATEST_PER_ARCH, HY_EQ, 1);
@@ -1887,13 +1894,30 @@ Query::Impl::filterAdvisory(const Filter & f, Map *m, int keyname)
installed_solvables.push_back(pool_id2solvable(pool, installed_id));
}
std::sort(installed_solvables.begin(), installed_solvables.end(), NameArchSolvableComparator);
+
+ Query obsoletes(sack, ExcludeFlags::IGNORE_EXCLUDES);
+ obsoletes.addFilter(HY_PKG, HY_EQ, resultPset);
+ obsoletes.available();
+
+ Query possibly_obsoleted(sack, ExcludeFlags::IGNORE_EXCLUDES);
+ possibly_obsoleted.addFilter(HY_PKG, HY_EQ, resultPset);
+ possibly_obsoleted.addFilter(HY_PKG_UPGRADES, HY_EQ, 1);
+ possibly_obsoleted.queryUnion(installed);
+ possibly_obsoleted.apply();
+
+ obsoletes.addFilter(HY_PKG_OBSOLETES, HY_EQ, possibly_obsoleted.runSet());
+ obsoletes.apply();
+ Id obsoleted_id = -1;
+ // Add to candidates resultPset pkgs that obsolete some installed (or to be installed in this transaction) pkg
+ while ((obsoleted_id = obsoletes.pImpl->result->next(obsoleted_id)) != -1) {
+ Solvable * s = pool_id2solvable(pool, obsoleted_id);
+ candidates.push_back(s);
+ }
+
Id id = -1;
+ // Add to candidates resultPset pkgs that match name and arch with some already installed pkg
while ((id = resultPset->next(id)) != -1) {
Solvable * s = pool_id2solvable(pool, id);
- // 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).
- // Otherwise a pkg with different Arch than installed can end up in upgrade set which is wrong.
- // It can result in dependency issues, reported as: RhBug:2088149.
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);
--
2.36.1

@ -0,0 +1,35 @@
From 3a3929a27734aa77c980610a43039cb6b2b6d658 Mon Sep 17 00:00:00 2001
From: Jan Kolarik <jkolarik@redhat.com>
Date: Wed, 10 Aug 2022 05:21:38 +0000
Subject: [PATCH] Fix listing a repository without cpeid (RhBug:2066334)
= changelog =
type: bugfix
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2066334
---
libdnf/repo/Repo.cpp | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/libdnf/repo/Repo.cpp b/libdnf/repo/Repo.cpp
index e3a574fb..d61a24a5 100644
--- a/libdnf/repo/Repo.cpp
+++ b/libdnf/repo/Repo.cpp
@@ -1021,8 +1021,13 @@ bool Repo::Impl::loadCache(bool throwExcept, bool ignoreMissing)
for (auto elem = yum_repomd->distro_tags; elem; elem = g_slist_next(elem)) {
if (elem->data) {
auto distroTag = static_cast<LrYumDistroTag *>(elem->data);
- if (distroTag->tag)
- distro_tags.emplace_back(distroTag->cpeid, distroTag->tag);
+ if (distroTag->tag) {
+ std::string cpeid_str;
+ if (distroTag->cpeid) {
+ cpeid_str = distroTag->cpeid;
+ }
+ distro_tags.emplace_back(std::move(cpeid_str), distroTag->tag);
+ }
}
}
--
2.37.1

@ -0,0 +1,89 @@
From af5493156ecb1af3aedd5559a9a60b5df54a17ac 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 5355f9f7..b7b1560e 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

File diff suppressed because it is too large Load Diff

@ -0,0 +1,317 @@
From 0e13ac4820e72682b427cfe3cabcfa32561cf631 Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Fri, 24 Mar 2023 13:22:41 +0100
Subject: [PATCH] Backport: 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 f9f861c1..546d5837 100644
--- a/libdnf/module/ModulePackageContainer.cpp
+++ b/libdnf/module/ModulePackageContainer.cpp
@@ -235,13 +235,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);
@@ -324,23 +317,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);
- std::vector<ModulePackage *> packages = md.getAllModulePackages(pImpl->moduleSack, r, repoID);
- 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);
+ 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 dc8a7262f4955160172a32e54eb1db4a644471fa Mon Sep 17 00:00:00 2001
From: Jaroslav Mracek <jmracek@redhat.com>
Date: Tue, 21 Mar 2023 11:28:43 +0100
Subject: [PATCH] Backport: 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 6b2f91a2..b7710303 100644
--- a/libdnf/goal/Goal.cpp
+++ b/libdnf/goal/Goal.cpp
@@ -83,8 +83,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")},
@@ -94,24 +94,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")},
@@ -121,19 +121,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
@@ -147,9 +147,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:
@@ -172,44 +174,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 546d5837..0dbece4d 100644
--- a/libdnf/module/ModulePackageContainer.cpp
+++ b/libdnf/module/ModulePackageContainer.cpp
@@ -341,7 +341,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);
+ auto packages = md.getAllModulePackages(pImpl->moduleSack, repo, repoID);
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,47 @@
From a5fe0e0eb6457ca51fabe8123d7407951cb8fcba Mon Sep 17 00:00:00 2001
From: Jaroslav Rohel <jrohel@redhat.com>
Date: Wed, 24 May 2023 12:35:29 +0200
Subject: [PATCH] conf: Support "proxy=_none_" in main config (RhBug:2155713)
It has the same meaning as "proxy=". Introduced for compatibility with yum.
Yum does not support a proxy option with an empty value. Instead, it has
the special value "_none_". The value "_none_" is case insensitive.
Support for "proxy=_none_" in the repository configuration was added some
time ago - in commit ea749e6238cdb54fe3b5add67875ab5912d2e766
= changelog =
msg: Support "proxy=_none_" in main config
type: enhancement
resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2155713
---
libdnf/conf/ConfigMain.cpp | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/libdnf/conf/ConfigMain.cpp b/libdnf/conf/ConfigMain.cpp
index a6645d70..a775cf8c 100644
--- a/libdnf/conf/ConfigMain.cpp
+++ b/libdnf/conf/ConfigMain.cpp
@@ -476,7 +476,18 @@ ConfigMain::Impl::Impl(Config & owner)
}, nullptr, true
);
- owner.optBinds().add("proxy", proxy);
+ owner.optBinds().add("proxy", proxy,
+ [&](Option::Priority priority, const std::string & value){
+ auto tmpValue(value);
+ for (auto & ch : tmpValue)
+ ch = std::tolower(ch);
+ if (tmpValue == "_none_")
+ proxy.set(priority, "");
+ else
+ proxy.set(priority, value);
+ }, nullptr, false
+ );
+
owner.optBinds().add("proxy_username", proxy_username);
owner.optBinds().add("proxy_password", proxy_password);
owner.optBinds().add("proxy_auth_method", proxy_auth_method);
--
2.40.1

File diff suppressed because it is too large Load Diff

@ -0,0 +1,37 @@
From d138dbf60588b73a8ee9499540c82a8950ba9432 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,99 @@
From c32ce1071807176eb31d884d4185b20d944a28b9 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 b771030..6939d8a 100644
--- a/libdnf/goal/Goal.cpp
+++ b/libdnf/goal/Goal.cpp
@@ -639,6 +639,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)
@@ -1324,10 +1330,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;
}
@@ -1345,17 +1365,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

@ -0,0 +1,335 @@
From 8752006f5f9c11bca3f04c99b463fd167caf0ddd 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 | 121 +++++++++++++++++++++++++++++++++++++-----
4 files changed, 129 insertions(+), 14 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d895b2bf..e5829e6a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -34,6 +34,7 @@ option(WITH_MAN "Enables hawkey man page generation" ON)
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(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 aa51dd28..df482f54 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
@@ -84,6 +86,9 @@ BuildRequires: pkgconfig(sqlite3)
BuildRequires: pkgconfig(json-c)
BuildRequires: pkgconfig(cppunit)
BuildRequires: pkgconfig(libcrypto)
+%if %{with selinux}
+BuildRequires: pkgconfig(libselinux)
+%endif
BuildRequires: pkgconfig(modulemd-2.0) >= %{libmodulemd_version}
BuildRequires: pkgconfig(smartcols)
BuildRequires: gettext
@@ -205,7 +210,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
@@ -219,7 +225,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 998a6f94..10b15230 100644
--- a/libdnf/CMakeLists.txt
+++ b/libdnf/CMakeLists.txt
@@ -89,6 +89,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 d61a24a5..68b82ccc 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>
@@ -649,6 +654,78 @@ 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 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)) {
+ 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
+
+ return retval;
+}
+
static void gpgImportKey(gpgme_ctx_t context, int keyFd)
{
auto logger(Log::getLogger());
@@ -703,8 +780,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";
- mkdtemp(tmpdir);
+ char tmpdir[] = "/tmp/libdnf.XXXXXX";
+ create_temporary_directory(tmpdir);
Finalizer tmpDirRemover([&tmpdir](){
dnf_remove_recursive(tmpdir, NULL);
});
@@ -853,6 +930,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.
@@ -861,14 +945,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;
}
}
@@ -1151,8 +1248,8 @@ void Repo::Impl::addCountmeFlag(LrHandle *handle) {
bool Repo::Impl::isMetalinkInSync()
{
auto logger(Log::getLogger());
- char tmpdir[] = "/tmp/tmpdir.XXXXXX";
- mkdtemp(tmpdir);
+ char tmpdir[] = "/tmp/libdnf.XXXXXX";
+ create_temporary_directory(tmpdir);
Finalizer tmpDirRemover([&tmpdir](){
dnf_remove_recursive(tmpdir, NULL);
});
@@ -1221,8 +1318,8 @@ bool Repo::Impl::isRepomdInSync()
{
auto logger(Log::getLogger());
LrYumRepo *yum_repo;
- char tmpdir[] = "/tmp/tmpdir.XXXXXX";
- mkdtemp(tmpdir);
+ char tmpdir[] = "/tmp/libdnf.XXXXXX";
+ create_temporary_directory(tmpdir);
Finalizer tmpDirRemover([&tmpdir](){
dnf_remove_recursive(tmpdir, NULL);
});
@@ -1260,8 +1357,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

@ -0,0 +1,912 @@
%global libsolv_version 0.7.20-3
%global libmodulemd_version 2.11.2-2
%global librepo_version 1.13.1
%global dnf_conflict 4.3.0
%global swig_version 3.0.12
%global libdnf_major_version 0
%global libdnf_minor_version 63
%global libdnf_micro_version 0
%define __cmake_in_source_build 1
# set sphinx package name according to distro
%global requires_python2_sphinx python2-sphinx
%global requires_python3_sphinx python3-sphinx
%if 0%{?rhel} == 7
%global requires_python2_sphinx python-sphinx
%endif
%if 0%{?suse_version}
%global requires_python2_sphinx python2-Sphinx
%global requires_python3_sphinx python3-Sphinx
%endif
%bcond_with valgrind
# Do not build bindings for python3 for RHEL <= 7
%if 0%{?rhel} && 0%{?rhel} <= 7
%bcond_with python3
%else
%bcond_without python3
%endif
%if 0%{?rhel} > 7 || 0%{?fedora} > 29
# Disable python2 build by default
%bcond_with python2
%else
%bcond_without python2
%endif
%if 0%{?rhel} && ! 0%{?centos}
%bcond_without rhsm
%else
%bcond_with rhsm
%endif
%bcond_without selinux
%if 0%{?rhel}
%bcond_with zchunk
%else
%bcond_without zchunk
%endif
%bcond_with sanitizers
%global _cmake_opts \\\
-DENABLE_RHSM_SUPPORT=%{?with_rhsm:ON}%{!?with_rhsm:OFF} \\\
%{nil}
Name: libdnf
Version: %{libdnf_major_version}.%{libdnf_minor_version}.%{libdnf_micro_version}
Release: 19%{?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-Revert-Improve-performance-for-module-query.patch
Patch2: 0002-Revert-Enhance-description-of-modular-solvables.patch
Patch3: 0003-Revert-Fix-typo-lates-latest.patch
Patch4: 0004-Revert-Remove-unused-code-bump-version.patch
Patch5: 0005-Revert-Report-a-new-type-of-the-module-resolve-error.patch
Patch6: 0006-Revert-Add-additional-fallback-for-module-resolve.patch
Patch7: 0007-Revert-Decide-how-to-handle-context-according-to-sta.patch
Patch8: 0008-Revert-Fix-load-update-FailSafe.patch
Patch9: 0009-Revert-Change-mechanism-of-module-conflicts.patch
Patch10: 0010-Revert-Call-addVersion2Modules-as-late-as-possible.patch
Patch11: 0011-Revert-Fix-modular-queries-with-the-new-solver.patch
Patch12: 0012-Revert-Add-compatible-layer-for-MdDocuments-v2.patch
Patch13: 0013-Revert-Add-an-alternative-constructor-for-ModulePack.patch
Patch14: 0014-Revert-Adjust-modular-solver-to-new-context-type.patch
Patch15: 0015-Revert-Change-usage-of-context-and-version-in-modula.patch
Patch16: 0016-Fix-failing-unittest-caused-by-the-revert-of-new-mod.patch
Patch17: 0017-Modify-unit-test-after-change-of-handling-advisories.patch
Patch18: 0018-Adjust-module-error-formatting-function-for-original.patch
Patch19: 0019-Remove-redundant-test.patch
Patch20: 0020-Fix-dnf_context_module_install-memory-leaks.patch
Patch21: 0021-covscan-remove-unused-vars-mark-private-func-static-return-values.patch
Patch22: 0022-hawkey-surrogateescape-error-handler-to-decode-UTF-8-strings-RhBug1893176.patch
Patch23: 0023-Turn-off-strict-validation-of-modulemd-documents-RhBug200485320071662007167.patch
Patch24: 0024-Add-unittest-for-setting-up-repo-with-empty-keyfile-RhBug1994614.patch
Patch25: 0025-Add-getLatestModules.patch
Patch26: 0026-context-Substitute-all-repository-config-options-RhB.patch
Patch27: 0027-Use-environment-variable-in-unittest-instead-of-ugly.patch
Patch28: 0028-Add-private-API-for-filling-reading-and-verifying-ne.patch
Patch29: 0029-Use-dnf-solv-userdata-to-check-versions-and-checksum.patch
Patch30: 0030-Update-unittest-to-test-the-new-private-dnf-solvfile.patch
Patch31: 0031-Increase-required-libsolv-version-for-cache-versioni.patch
Patch32: 0032-Add-more-specific-error-handling-for-loading-repomd-.patch
Patch33: 0033-libdnf-transaction-RPMItem-Fix-handling-transaction-.patch
Patch34: 0034-libdnf-transaction-TransactionItem-Set-short-action-.patch
Patch35: 0035-Do-not-print-errors-on-failovermethod-repo-option-Rh.patch
Patch36: 0036-sack-query.hpp-Add-a-missing-include.patch
Patch37: 0037-context-dnf_context_remove-accepts-package-spec-as-d.patch
Patch38: 0038-context-Fix-doc-dnf_context_install-remove-update-di.patch
Patch39: 0039-advisory-upgrade-filter-out-advPkgs-with-different-a.patch
Patch40: 0040-Add-obsoletes-to-filtering-for-advisory-candidates.patch
Patch41: 0041-Fix-listing-a-repository-without-cpeid-RhBug-2066334.patch
Patch42: 0042-Allow-change-of-arch-during-security-updates-with-no.patch
Patch43: 0043-Update-translations.patch
Patch44: 0044-Add_repoid_to_solver_error_messagase.patch
Patch45: 0045-conf-Support-proxy-_none_-in-main-config-RhBug-21557.patch
Patch46: 0046-Update-translations-RHEL-8.9.patch
Patch47: 0047-filterAdvisory-installed_solvables-sort-RhBug2212838.patch
Patch48: 0048-Avoid-reinstal-installonly-packages-marked-for-ERASE.patch
Patch49: 0049-PGP-Set-a-default-creation-SELinux-labels-on-GnuPG-d.patch
BuildRequires: cmake
BuildRequires: gcc
BuildRequires: gcc-c++
BuildRequires: libsolv-devel >= %{libsolv_version}
BuildRequires: pkgconfig(librepo) >= %{librepo_version}
BuildRequires: pkgconfig(check)
%if %{with valgrind}
BuildRequires: valgrind
%endif
BuildRequires: pkgconfig(gio-unix-2.0) >= 2.46.0
BuildRequires: pkgconfig(gtk-doc)
BuildRequires: rpm-devel >= 4.11.0
%if %{with rhsm}
BuildRequires: pkgconfig(librhsm) >= 0.0.3
%endif
%if %{with zchunk}
BuildRequires: pkgconfig(zck) >= 0.9.11
%endif
BuildRequires: pkgconfig(sqlite3)
BuildRequires: pkgconfig(json-c)
BuildRequires: pkgconfig(cppunit)
BuildRequires: pkgconfig(libcrypto)
%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
BuildRequires: liblsan
BuildRequires: libubsan
%endif
Requires: libmodulemd%{?_isa} >= %{libmodulemd_version}
Requires: libsolv%{?_isa} >= %{libsolv_version}
Requires: librepo%{?_isa} >= %{librepo_version}
%if %{without python2}
# Obsoleted from here so we can track the fast growing version easily.
# We intentionally only obsolete and not provide, this is a broken upgrade
# prevention, not providing the removed functionality.
Obsoletes: python2-%{name} < %{version}-%{release}
Obsoletes: python2-hawkey < %{version}-%{release}
Obsoletes: python2-hawkey-debuginfo < %{version}-%{release}
Obsoletes: python2-libdnf-debuginfo < %{version}-%{release}
%endif
%description
A Library providing simplified C and Python API to libsolv.
%package devel
Summary: Development files for %{name}
Requires: %{name}%{?_isa} = %{version}-%{release}
Requires: libsolv-devel%{?_isa} >= %{libsolv_version}
%description devel
Development files for %{name}.
%if %{with python2}
%package -n python2-%{name}
%{?python_provide:%python_provide python2-%{name}}
Summary: Python 2 bindings for the libdnf library.
Requires: %{name}%{?_isa} = %{version}-%{release}
BuildRequires: python2-devel
%if !0%{?mageia}
BuildRequires: %{requires_python2_sphinx}
%endif
%if 0%{?rhel} == 7
BuildRequires: swig3 >= %{swig_version}
%else
BuildRequires: swig >= %{swig_version}
%endif
%description -n python2-%{name}
Python 2 bindings for the libdnf library.
%endif
# endif with python2
%if %{with python3}
%package -n python3-%{name}
%{?python_provide:%python_provide python3-%{name}}
Summary: Python 3 bindings for the libdnf library.
Requires: %{name}%{?_isa} = %{version}-%{release}
BuildRequires: python3-devel
BuildRequires: %{requires_python3_sphinx}
BuildRequires: swig >= %{swig_version}
%description -n python3-%{name}
Python 3 bindings for the libdnf library.
%endif
%if %{with python2}
%package -n python2-hawkey
Summary: Python 2 bindings for the hawkey library
%{?python_provide:%python_provide python2-hawkey}
BuildRequires: python2-devel
Requires: %{name}%{?_isa} = %{version}-%{release}
Requires: python2-%{name} = %{version}-%{release}
# Fix problem with hawkey - dnf version incompatibility
# Can be deleted for distros where only python2-dnf >= 2.0.0
Conflicts: python2-dnf < %{dnf_conflict}
Conflicts: python-dnf < %{dnf_conflict}
%description -n python2-hawkey
Python 2 bindings for the hawkey library.
%endif
# endif with python2
%if %{with python3}
%package -n python3-hawkey
Summary: Python 3 bindings for the hawkey library
%{?python_provide:%python_provide python3-hawkey}
BuildRequires: python3-devel
Requires: %{name}%{?_isa} = %{version}-%{release}
Requires: python3-%{name} = %{version}-%{release}
# Fix problem with hawkey - dnf version incompatibility
# Can be deleted for distros where only python3-dnf >= 2.0.0
Conflicts: python3-dnf < %{dnf_conflict}
# Obsoletes F27 packages
Obsoletes: platform-python-hawkey < %{version}-%{release}
%description -n python3-hawkey
Python 3 bindings for the hawkey library.
%endif
%prep
%autosetup -S git -p1
%if %{with python2}
mkdir build-py2
%endif
%if %{with python3}
mkdir build-py3
%endif
%build
%if %{with python2}
pushd build-py2
%if 0%{?mageia} || 0%{?suse_version}
cd ..
%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} -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}
%make_build
popd
%endif
# endif with python2
%if %{with python3}
pushd build-py3
%if 0%{?mageia} || 0%{?suse_version}
cd ..
%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} -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}
%make_build
popd
%endif
%check
%if %{with python2}
pushd build-py2
make ARGS="-V" test
popd
%endif
%if %{with python3}
# If we didn't run the general tests yet, do it now.
%if %{without python2}
pushd build-py3
make ARGS="-V" test
popd
%else
# Otherwise, run just the Python tests, not all of
# them, since we have coverage of the core from the
# first build
pushd build-py3/python/hawkey/tests
make ARGS="-V" test
popd
%endif
%endif
%install
%if %{with python2}
pushd build-py2
%make_install
popd
%endif
%if %{with python3}
pushd build-py3
%make_install
popd
%endif
%find_lang %{name}
%if (0%{?rhel} && 0%{?rhel} <= 7) || 0%{?suse_version}
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%else
%ldconfig_scriptlets
%endif
%files -f %{name}.lang
%license COPYING
%doc README.md AUTHORS
%{_libdir}/%{name}.so.*
%dir %{_libdir}/libdnf/
%dir %{_libdir}/libdnf/plugins/
%{_libdir}/libdnf/plugins/README
%if %{with sanitizers}
%{_sysconfdir}/profile.d/dnf-sanitizers.sh
%endif
%files devel
%doc %{_datadir}/gtk-doc/html/%{name}/
%{_libdir}/%{name}.so
%{_libdir}/pkgconfig/%{name}.pc
%{_includedir}/%{name}/
%if %{with python2}
%files -n python2-%{name}
%{python2_sitearch}/%{name}/
%endif
%if %{with python3}
%files -n python3-%{name}
%{python3_sitearch}/%{name}/
%endif
%if %{with python2}
%files -n python2-hawkey
%{python2_sitearch}/hawkey/
%endif
%if %{with python3}
%files -n python3-hawkey
%{python3_sitearch}/hawkey/
%endif
%changelog
* Fri Mar 29 2024 MSVSphere Packaging Team <packager@msvsphere-os.ru> - 0.63.0-19
- Rebuilt for MSVSphere 8.10 beta
* Wed Oct 18 2023 Petr Pisar <ppisar@redhat.com> - 0.63.0-19
- Set default SELinux labels on GnuPG directories (RHEL-6421)
* Fri Oct 13 2023 Jaroslav Rohel <jrohel@redhat.com> - 0.63.0-18
- filterAdvisory: match installed_solvables sort with lower_bound (RhBug:2212838, RHEL-1244)
- Avoid reinstalling installonly packages marked for ERASE (RhBug:2163474, RHEL-1253)
* Fri Sep 08 2023 Marek Blaha <mblaha@redhat.com> - 0.63.0-17
- Update translations
* Wed May 31 2023 Nicola Sella <nsella@redhat.com> - 0.63-0-16
- Support "proxy=_none_" in main config (RhBug:2155713)
* Wed May 17 2023 Jaroslav Rohel <jrohel@redhat.com> - 0.63.0-15
- Add repoid to solver error messages (RhBug:2179409,2179413)
* Wed Mar 08 2023 Marek Blaha <mblaha@redhat.com> - 0.63.0-14
- Update translations
* Wed Oct 26 2022 Nicola Sella <nsella@redhat.com> - 0.63.0-13
- Allow change of arch during security updates with noarch (RhBug:2124483)
* Tue Sep 13 2022 Lukas Hrazky <lhrazky@redhat.com> - 0.63.0-12
- Fix listing a repository without cpeid (RhBug:2066334)
* Thu Jul 21 2022 Lukas Hrazky <lhrazky@redhat.com> - 0.63.0-11
- Add obsoletes to filtering for advisory candidates
* Tue Jun 14 2022 Lukas Hrazky <lhrazky@redhat.com> - 0.63.0-10
- Do not print errors on failovermethod repo option
- the dnf_context_remove() function accepts `<package-spec>`, doc updates
- advisory upgrade: filter out advPkgs with different arch
* Wed May 04 2022 Lukas Hrazky <lhrazky@redhat.com> - 0.63.0-8
- Substitute all repository config options (fixes substitution of baseurl)
- Use solvfile userdata to store and check checksums and solv versions
- Fix handling transaction id in resolveTransactionItemReason
- Set short action for Reason Change
* Fri Jan 14 2022 Pavla Kratochvilova <pkratoch@redhat.com> - 0.63.0-7
- Rebuild with new release number
* Tue Jan 11 2022 Pavla Kratochvilova <pkratoch@redhat.com> - 0.63.0-6
- Add getLatestModules()
* Mon Nov 29 2021 Pavla Kratochvilova <pkratoch@redhat.com> - 0.63.0-5
- Add unittest for setting up repo with empty keyfile (RhBug:1994614)
* Tue Nov 09 2021 Pavla Kratochvilova <pkratoch@redhat.com> - 0.63.0-4
- Bump release number because of conflicting version of 8.5 build
* Tue Nov 09 2021 Pavla Kratochvilova <pkratoch@redhat.com> - 0.63.0-3
- Turn off strict validation of modulemd documents (RhBug:2004853,2007166,2007167)
* Tue Jul 27 2021 Pavla Kratochvilova <pkratoch@redhat.com> - 0.63.0-2
- Fix: dnf_context_module_install: memory leaks
- covscan: remove unused vars, mark private func static, return values
- DNF does not fail on non UTF-8 file names in a package
* Wed May 19 2021 Pavla Kratochvilova <pkratoch@redhat.com> - 0.63.0-1
- Update to 0.62.0
- Hardening: add signature check with rpmcliVerifySignatures (RhBug:1932079)
- Support allow_vendor_change setting in dnf context API
- Add a new option module_obsoletes
- Add new API applyObsoletes() function to apply modular obsoletes
- 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)
- Swdb: Add a method to get the current transaction
- [context,API] Functions for accessing main/global configuration options
- [context,API] Function for adding setopt
- Add getter for modular obsoletes from ModuleMetadata
- Add ModulePackage.getStaticContext() and getRequires()
- Fix modular queries with the new solver
- Fix: Fully set ssl in newHandle function
- [conf] Add options for working with certificates used with proxy
- Modify module NSVCA parsing - context definition (RhBug:1926771)
- [context] Fix: dnf_package_is_installonly (RhBug:1928056)
- Add getApplicablePackages to advisory and isApplicable to advisorymodule
- Keep isAdvisoryApplicable to preserve API
- [context] Support config file option "proxy_auth_method", defaults "any"
- Support main config file options "installonlypkgs" and "protected_packages". Changes behaviour of microdnf and PackageKit.
- Properly handle multiple collections in updateinfo.xml (RhBug:1804234)
- Fix a crash when [media] section in .treeinfo is missing for bootable media (RhBug:1946024)
- Add new dnf_context_module_install() C API
* Fri Feb 12 2021 Nicola Sella <nsella@redhat.com> - 0.55.0-6
- Fix removal step during modular enable in context part
* Thu Feb 11 2021 Nicola Sella <nsella@redhat.com> - 0.55.0-5
- Add new option module_stream_switch
* Mon Feb 08 2021 Nicola Sella <nsella@redhat.com> - 0.55.0-4
- [context] improve retrieving repository configuration
- Allow loading incomplete cache and loading ext solv files without its repodata
* Fri Jan 29 2021 Nicola Sella <nsella@redhat.com> - 0.55.0-3
- Avoid multilib file conflict in config.h (RhBug:1918818)
- [modules] Add special handling for src artifacts (RhBug:1809314)
* Fri Jan 15 2021 Nicola Sella <nsella@redhat.com> - 0.55.0-2
- Better msgs if "basecachedir" or "proxy_password" isn't set (RhBug:1888946)
* Mon Nov 09 2020 Nicola Sella <nsella@redhat.com> - 0.55.0-1
- Add vendor to dnf API (RhBug:1876561)
- Add formatting function for solver error
- Add error types in ModulePackageContainer
- Implement module enable for context part
- Improve string formatting for translation
- Remove redundant printf and change logging info to notice (RhBug:1827424)
- Add allow_vendor_change option (RhBug:1788371) (RhBug:1788371)
* 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)
* Fri Jan 31 2020 Marek Blaha <mblaha@redhat.com> - 0.39.1-4
- [translations] Update translations from zanata (RhBug:1754965)
* Mon Jan 13 2020 Ales Matej <amatej@redhat.com> - 0.39.1-3
- Add two new query filters: obsoletes_by_priority, upgrades_by_priority (RhBug:1769466)
- [context] Add wildcard support in dnf_context_repo_set_data (RhBug:1781420)
- Remove killGpgAgent function (RhBug:1781601)
* Thu Dec 12 2019 Pavla Kratochvilova <pkratoch@redhat.com> - 0.39.1-2
- [user-agent] Stop checking os-release(5) data against a hard-coded whitelist (RhBug:1777255)
* Mon Nov 25 2019 Ales Matej <amatej@redhat.com> - 0.39.1-1
- Update to 0.39.1
- Report reason how package was excluded (RhBug:1649754)
- Additional Arm detection improvements (RhBug:1691430)
- Set skip_if_unavailable for media repos to skip their update (RhBug:1716067)
- Add support of xml:base for remote and local url in context (RhBug:1734350,1717865)
* Wed Nov 13 2019 Ales Matej <amatej@redhat.com> - 0.38.1-1
- Update to 0.38.1
- Change the best option default to false
- Use more descriptive message when failed to retrieve GPG key (RhBug:1605117)
- Add removeMetadataTypeFromDownload function to the API
- Context part of libdnf can now read vars (urlvars) from dirs and environment
- Throw exception immediately if file cannot be opened
- Add test when there is no primary metadata in compatible format (RhBug:1744960)
- Various improvements to countme features
- Don't abort on rpmdb checksum calculation failure
- Enable module dependency trees when using set_modules_enabled_by_pkgset() (RhBug:1762314)
- Resolve problem with --best and search in provides (RhBug:1737469)
- New method "Query::filterSubject()", replaces Solution::getBestSolution()
- The Solution class was removed
- Add query argument into get_best_query and get_best_solution
- Add module reset function into dnf_context
- Add method to get all repository metadata locations
- Catch NoModuleException in case of not existent value was used in persistor (RhBug:1761773)
* Tue Oct 22 2019 Ales Matej <amatej@redhat.com> - 0.35.5-1
- Update to 0.35.5
- Make libdnf own its plugin directory (RhBug:1714265)
- Set priority of dnf.conf.d drop-ins
- Fix toString() to not insert [] (RhBug:1584442)
- Fix handling large number of filenames on input (RhBug:1690915)
- Detect armv7 with crypto extension only on arm version >= 8
- A new standardized User-Agent field consisting of the libdnf and OS version
(including the variant) (RhBug:1156007)
- Add basic countme support (RhBug:1647454)
- Fix crash in PackageKit (RhBug:1636803)
- Do not create @System.solv files (RhBug:1707995)
- Set LRO_CACHEDIR so zchunk works again (RhBug:1739867)
- Improve detection of extras packages by comparing (name, arch) pair instead
of full NEVRA (RhBuh:1684517)
- Improve handling multilib packages in the history command (RhBug:1728637)
- Repo download: use full error description into the exception text (RhBug:1741442)
- Properly close hawkey.log (RhBug:1594016)
- Fix dnf updateinfo --update to not list advisories for packages updatable
only from non-enabled modules
- Apply modular filtering by package name (RhBug:1702729)
* Wed Oct 16 2019 Pavla Kratochvilova <pkratoch@redhat.com> - 0.35.1-9
- Prevent reinstalling modified packages with same NEVRA (RhBug:1728252,1644241,1760825)
* Fri Sep 06 2019 Marek Blaha <mblaha@redhat.com> - 0.35.1-8
- Enhanced fix of moving directories in minimal container (RhBug:1700341)
* Thu Sep 05 2019 Jaroslav Mracek <jmracek@redhat.com> - 0.35.1-7
- Remove patch to not fail when installing modular RPMs without modular metadata
* Thu Sep 05 2019 Marek Blaha <mblaha@redhat.com> - 0.35.1-6
- Fix moving directories in minimal container (RhBug:1700341)
* Tue Aug 06 2019 Pavla Kratochvilova <pkratoch@redhat.com> - 0.35.1-5
- Add suport for query sequence conversions
* Thu Aug 01 2019 Pavla Kratochvilova <pkratoch@redhat.com> - 0.35.1-4
- Fix typo in error message (RhBug:1726661)
- Update localizations from zanata (RhBug:1689991)
- Don't disable nonexistent but required repositories (RhBug:1689331)
- Ignore trailing blank lines of multiline value (RhBug:1722493)
- Re-size includes map before re-computation (RhBug:1725213)
* Tue Jul 16 2019 Marek Blaha <mblaha@redhat.com> - 0.35.1-3
- Fix attaching and detaching of libsolvRepo and repo_internalize_trigger()
(RhBug:1730224)
* Thu Jul 04 2019 Pavla Kratochvilova <pkratoch@redhat.com> - 0.35.1-2
- Add patch to not fail when installing modular RPMs without modular metadata
* Tue Jun 11 2019 Pavla Kratochvilova <pkratoch@redhat.com> - 0.35.1-1
- Update to 0.35.1
- Skip invalid key files in "/etc/pki/rpm-gpg" with warning (RhBug:1644040)
- Enable timestamp preserving for downloaded data (RhBug:1688537)
- Fix 'database is locked' error (RhBug:1631533)
- Replace the 'Failed to synchronize cache' message (RhBug:1712055)
- Fix 'no such table: main.trans_cmdline' error (RhBug:1596540)
- Fix: skip_if_unavailable=true for local repositories (RhBug:1716313)
- Add support of modular FailSafe (RhBug:1623128)
- Add support of DNF main config file in context; used by PackageKit and
microdnf (RhBug:1689331)
- Exit gpg-agent after repokey import (RhBug:1650266)
* Mon May 13 2019 Pavla Kratochvilova <pkratoch@redhat.com> - 0.33.0-1
- Update to 0.33.0
- Enhance sorting for module list (RhBug:1590358)
- [DnfRepo] Add methods for alternative repository metadata type and download (RhBug:1656314)
- Remove installed profile on module enable or disable (RhBug:1653623)
- Enhance modular solver to handle enabled and default module streams differently (RhBug:1648839)
- Add support of wild cards for modules (RhBug:1644588)
- Exclude module pkgs that have conflict
- Enhance config parser to preserve order of data, and keep comments and format
- Improve ARM detection
- Add support for SHA-384
- Return empty query if incorrect reldep (RhBug:1687135)
- ConfigParser: Improve compatibility with Python ConfigParser and dnf-plugin-spacewalk (RhBug:1692044)
- ConfigParser: Unify default set of string represenation of boolean values
- Fix segfault when interrupting dnf process (RhBug:1610456)
- Installroot now requires absolute path
- Support "_none_" value for repo option "proxy" (RhBug:1680272)
- Add support for Module advisories
- Add support for xml:base attribute from primary.xml (RhBug:1691315)
- Improve detection of Platform ID (RhBug:1688462)
* Fri Apr 26 2019 Pavla Kratochvilova <pkratoch@redhat.com> - 0.22.5-6
- Rebuild for libsolv soname bump (in libsolve update to 0.7.4)
* Wed Apr 03 2019 Jaroslav Mracek <jmracek@redhat.com> - 0.22.5-5
- Backport patches to set default to skip_if_unavailable to false (RhBug:1692452)
* Tue Feb 12 2019 Jaroslav Mracek <jmracek@redhat.com> - 0.22.5-4
- Backport patch to exclude module pkgs that have conflict (RhBug:1670496)
* Fri Feb 08 2019 Jaroslav Mracek <jmracek@redhat.com> - 0.22.5-3
- Backport patches to add support for modular updateinfoxml applicability
* Wed Feb 06 2019 Pavla Kratochvilova <pkratoch@redhat.com> - 0.22.5-2
- Add patch: Add best as default behavior (RhBug1670776)
* Mon Dec 17 2018 Daniel Mach <dmach@redhat.com> - 0.22.4-1
- Enhance LIBDNF plugins support
- [repo] Check whether metadata cache is expired (RhBug:1539620,1648274)
- [sack] Implement dnf_sack_get_rpmdb_version()
* Fri Nov 23 2018 Jaroslav Mracek <jmracek@redhat.com> - 0.22.3-1
- Permanently disable Python2 build for Fedora 30+
- Update to 0.22.3
- Modify solver_describe_decision to report cleaned (RhBug:1486749)
- [swdb] create persistent WAL files (RhBug:1640235)
- Relocate ModuleContainer save hook (RhBug:1632518)
- [transaction] Fix transaction item lookup for obsoleted packages (RhBug: 1642796)
- Fix memory leaks and memory allocations
- [repo] Possibility to extend downloaded repository metadata
* Wed Oct 24 2018 Jaroslav Mracek <jmracek@redhat.com> - 0.22.0-2
- Add patch Modify-solver_describe_decision-to-report-cleaned-RhBug1486749
- Add patch swdb-create-persistent-WAL-files-RhBug1640235
- Add patch Relocate-ModuleContainer-save-hook-RhBug1632518
- Add patch Test-if-sack-is-present-and-run-save-module-persistor-RhBug1632518
* Mon Oct 15 2018 Jaroslav Mracek <jmracek@redhat.com> - 0.22.0-1
- Fix segfault in repo_internalize_trigger (RhBug:1375895)
- Change sorting of installonly packages (RhBug:1627685)
- [swdb] Fixed pattern searching in history db (RhBug:1635542)
- Check correctly gpg for repomd when refresh is used (RhBug:1636743)
- [conf] Provide additional VectorString methods for compatibility with Python list.
- [plugins] add plugin loading and hooks into libdnf
* Tue Sep 25 2018 Jaroslav Mracek <jmracek@redhat.com> - 0.20.0-1
- [module] Report module solver errors
- [module] Enhance module commands and errors
- [transaction] Fixed several problems with SWDB
- Remove unneeded regex URL tests (RhBug:1598336)
- Allow quoted values in ini files (RhBug:1624056)
- Filter out not unique set of solver problems (RhBug:1564369)
- Resolves: rhbz#1614531 - dnf 3.2 does not depsolve correctly
- Resolves: rhbz#1614346 - dnf rollback doesn't work after install/downgrade/upgrade
- bug 1605274 - DNF crashes on * in installation repository URL
- Resolves: rhbz#1623383 - dnf.exceptions.ConfigError: Error parsing ...
* Mon Sep 10 2018 Jaroslav Mracek <jmracek@redhat.com> - 0.19.1-1
- Fix compilation errors on gcc-4.8.5
- [module] Allow module queries on disabled modules (RhBug:1627081)
* Fri Sep 07 2018 Jaroslav Mracek <jmracek@redhat.com> - 0.19.0-1
- [query] Reldeps can contain a space char (RhBug:1612462)
- [transaction] Avoid adding duplicates via Transaction::addItem()
- Fix compilation errors on gcc-4.8.5
- [module] Make available ModuleProfile using SWIG
- [module] Redesign module disable and reset
* Fri Aug 31 2018 Daniel Mach <dmach@redhat.com> - 0.18.0-1
- [repo] Implement GPG key import
- [repo] Introduce Repo class replacing dnf.repo.Repo
- [context] Fix memory corruption in dnf_context
- [rhsm] Fix: RHSM don't write .repo file with same content (RhBug:1600452)
- [module] Create /etc/dnf/modules.d if it doesn't exist.
- [module] Forward C++ exceptions to bindings.
* Thu Aug 16 2018 Daniel Mach <dmach@redhat.com> - 0.17.2-2
- [module] Create /etc/dnf/modules.d if it doesn't exist.
- [module] Forward C++ exceptions to bindings.
* Mon Aug 13 2018 Daniel Mach <dmach@redhat.com> - 0.17.2-1
- [sqlite3] Change db locking mode to DEFAULT.
- [doc] Add libsmartcols-devel to devel deps.
* Mon Aug 13 2018 Daniel Mach <dmach@redhat.com> - 0.17.1-1
- [module] Solve a problem in python constructor of NSVCAP if no version.
- [translations] Update translations from zanata.
- [transaction] Fix crash after using dnf.comps.CompsQuery and forking the process in Anaconda.
- [module] Support for resetting module state.
- [output] Introduce wrapper for smartcols.
* Tue Aug 07 2018 Daniel Mach <dmach@redhat.com> - 0.17.0-1
- [conf] Add module_platform_id option.
- [module] Add ModulePackageContainer class.
- [module] Add ModulePersistor class.
- [sack] Module filtering made available in python API
- [sack] Module auto-enabling according to installed packages
* Fri Jul 27 2018 Daniel Mach <dmach@redhat.com> - 0.16.1-1
- [module] Implement 'module_hotfixes' conf option to skip filtering RPMs from hotfix repos.
- [goal] Fix distupgrade filter, allow downgrades.
- [context] Allow to set module platform in context.
- [module] Introduce proper modular dependency solving.
- [module] Platform pseudo-module based on /etc/os-release.
- [goal] Add Goal::listSuggested().
- [l10n] Support for translations, add gettext build dependency.
* Sun Jul 22 2018 Daniel Mach <dmach@redhat.com> - 0.16.0-1
- Fix RHSM plugin
- Add support for logging
- Bump minimal libmodulemd version to 1.6.1
* Mon Jul 09 2018 Igor Gnatenko <ignatenko@redhat.com> - 0.15.2-2
- Fix librhsm support logic
* Fri Jun 29 2018 Jaroslav Mracek <jmracek@redhat.com> - 0.15.2-1
- Update to 0.15.1
- Resolves: rhbz#1595487
* Fri Jun 29 2018 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 0.15.1-2
- Restore proper ldconfig_scriptlets
* Tue Jun 26 2018 Jaroslav Mracek <jmracek@redhat.com> - 0.15.1-1
- Update to 0.15.1
* Fri Jun 15 2018 Miro Hrončok <mhroncok@redhat.com> - 0.11.1-6
- Rebuilt for Python 3.7
* Wed Feb 07 2018 Fedora Release Engineering <releng@fedoraproject.org> - 0.11.1-5
- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
* Tue Jan 30 2018 Igor Gnatenko <ignatenko@redhat.com> - 0.11.1-4
- Switch to %%ldconfig_scriptlets
* Tue Nov 07 2017 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 0.11.1-3
- Use better Obsoletes for platform-python
* Fri Nov 03 2017 Igor Gnatenko <ignatenko@redhat.com> - 0.11.1-2
- Remove platform-python subpackage
* Mon Oct 16 2017 Jaroslav Mracek <jmracek@redhat.com> - 0.11.1-1
- Rerelease of 0.11.1-1
- Improvement query performance
- Run file query in hy_subject_get_best_solution only for files (arguments that start with ``/`` or
``*/``)
- Resolves: rhbz#1498207 - DNF crash during upgrade installation F26 -> F27
* Tue Oct 10 2017 Igor Gnatenko <ignatenko@redhat.com> - 0.11.0-1
- Update to 0.11.0
* Mon Oct 02 2017 Jaroslav Mracek <jmracek@redhat.com> - 0.10.1-2
- Rerelease of 0.10.1-1
* Wed Sep 27 2017 Jaroslav Mracek <jmracek@redhat.com> - 0.10.1-1
- Update to 0.10.1
- It improves query performance with name and arch filters. Also nevra filter will now
handle string with or without epoch.
- Additionally for python bindings it renames NEVRA._has_just_name() to NEVRA.has_just_name() due
to movement of code into c part of library.
- Resolves: rhbz#1260242 - --exclude does not affect dnf remove's removal of requirements
- Resolves: rhbz#1485881 - DNF claims it cannot install package, which have been already installed
- Resolves: rhbz#1361187 - [abrt] python-ipython-console: filter_updown(): python3.5 killed by SIGABRT
* Fri Sep 15 2017 Igor Gnatenko <ignatenko@redhat.com> - 0.9.3-8
- Disable platform python on old releases
* Tue Aug 15 2017 Lumír Balhar <lbalhar@redhat.com> - 0.9.3-7
- Add platform-python subpackage
* Fri Aug 11 2017 Igor Gnatenko <ignatenko@redhat.com> - 0.9.3-6
- Rebuilt after RPM update (№ 3)
* Thu Aug 10 2017 Igor Gnatenko <ignatenko@redhat.com> - 0.9.3-5
- Rebuilt for RPM soname bump
* Thu Aug 10 2017 Igor Gnatenko <ignatenko@redhat.com> - 0.9.3-4
- Rebuilt for RPM soname bump
* Thu Aug 03 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.3-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild
* Wed Jul 26 2017 Fedora Release Engineering <releng@fedoraproject.org> - 0.9.3-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
* Mon Jul 24 2017 Jaroslav Mracek <jmracek@redhat.com> - 0.9.3-1
- Update to 0.9.3
* Sat Jul 01 2017 Igor Gnatenko <ignatenko@redhat.com> - 0.9.2-1
- Update to 0.9.2
* Mon Jun 12 2017 Jaroslav Mracek <jmracek@redhat.com> - 0.9.1-1
- Update to 0.9.1
* Mon May 22 2017 Jaroslav Mracek <jmracek@redhat.com> - 0.9.0-1
- Update to 0.9.0
* Tue May 02 2017 Jaroslav Mracek <jmracek@redhat.com> - 0.8.2-1
- Update to 0.8.2
* Fri Mar 24 2017 Igor Gnatenko <ignatenko@redhat.com> - 0.8.1-1
- Update to 0.8.1
* Tue Mar 21 2017 Jaroslav Mracek <jmracek@redhat.com> - 0.8.0-1
- Update to 0.8.0
* Mon Feb 20 2017 Igor Gnatenko <ignatenko@redhat.com> - 0.7.4-1
- Update to 0.7.4
* Fri Feb 10 2017 Igor Gnatenko <ignatenko@redhat.com> - 0.7.3-1
- Update to 0.7.3
* Wed Feb 08 2017 Igor Gnatenko <ignatenko@redhat.com> - 0.7.2-1
- 0.7.2
* Fri Jan 06 2017 Igor Gnatenko <ignatenko@redhat.com> - 0.7.1-1
- 0.7.1
* Wed Dec 21 2016 Peter Robinson <pbrobinson@fedoraproject.org> 0.7.0-0.7gitf9b798c
- Rebuild for Python 3.6
* Mon Dec 19 2016 Igor Gnatenko <i.gnatenko.brain@gmail.com> - 0.7.0-0.6gitf9b798c
- Use new upstream URL
* Tue Dec 13 2016 Stratakis Charalampos <cstratak@redhat.com> - 0.7.0-0.5gitf9b798c
- Rebuild for Python 3.6
* Tue Dec 06 2016 Martin Hatina <mhatina@redhat.com> - 0.7.0-0.4gitf9b798c
- Increase conflict version of dnf
* Thu Dec 01 2016 Igor Gnatenko <i.gnatenko.brain@gmail.com> - 0.7.0-0.3gitf9b798c
- Update to latest snapshot
* Fri Nov 04 2016 Igor Gnatenko <ignatenko@redhat.com> - 0.7.0-0.2git8bd77f8
- Update to latest snapshot
* Thu Sep 29 2016 Igor Gnatenko <ignatenko@redhat.com> - 0.7.0-0.1git179c0a6
- Initial package
Loading…
Cancel
Save