When a package (with specified version) is contained in multiple
repositories, we register in packagemeta the last one we see. But if
libsolv decides that the package needs to be installed, its solution may
arbitrarily specify one from a different repo. This caused me some
confusion when debugging an unrelated issue, and I created the attached
patch to "fix" it.
In retrospect, I'm not sure this patch is right, but I'm sending it
anyway for the sake of discussion. My hesitation comes from the fact
that libsolv might have a good reason for preferring the one it chose,
e.g., if we've assigned priorities to the repos. On the other hand, if
we've gone to the trouble of assigning priorities, shouldn't packagemeta
reflect our choice?
I'm of two minds here.
Ken
From 2c0c1edbecad7cdce69a02cef0506b93fe5d7981 Mon Sep 17 00:00:00 2001
From: Ken Brown <kbr...@cornell.edu>
Date: Wed, 18 Oct 2017 09:24:48 -0400
Subject: [PATCH] Prefer the packageversion registered in packagemeta
When a packageversion that is contained in multiple repositories is
being installed, the solver has no way to know which one we prefer.
Change the solution, if necessary, to use the one we registered in
packagemeta when we parsed the setup.ini files.
---
libsolv.cc | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/libsolv.cc b/libsolv.cc
index 3a244d4..3750867 100644
--- a/libsolv.cc
+++ b/libsolv.cc
@@ -21,6 +21,8 @@
#include "LogSingleton.h"
#include <iomanip>
+#include <set>
+#include <assert.h>
// ---------------------------------------------------------------------------
// Utility functions for mapping between Operators and Relation Ids
@@ -762,10 +764,21 @@ SolverSolution::update(SolverTasks &tasks, updateMode
update, bool use_test_pack
for (int i = 0; i < t->steps.count; i++)
{
- Id id = t->steps.elements[i];
SolverTransaction::transType tt = type(t, i);
+ SolvableVersion sv = SolvableVersion(t->steps.elements[i], pool.pool);
+ // If we are installing a package that is contained in multiple
+ // repositories, we want to use the one registered in
+ // packagemeta.
+ if (tt == SolverTransaction::transInstall)
+ {
+ packagedb db;
+ packagemeta *pkg = db.findBinary(PackageSpecification(sv.Name()));
+ std::set <packageversion>::iterator j = pkg->versions.find(sv);
+ assert (j != pkg->versions.end());
+ sv = *j;
+ }
if (tt != SolverTransaction::transIgnore)
- trans.push_back(SolverTransaction(SolvableVersion(id, pool.pool), tt));
+ trans.push_back(SolverTransaction(sv, tt));
}
// add install and remove tasks for anything marked as reinstall
--
2.14.2