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

Reply via email to