Blob Blame History Raw
From ed90521f38374017874a86ce146eef8782fade47 Mon Sep 17 00:00:00 2001
From: Jan Silhan <jsilhan@redhat.com>
Date: Tue, 14 Jun 2016 11:25:48 +0200
Subject: [PATCH 1/2] selector: prefer obsoletes (Related:RhBug:1096506)

when searching by provides the packages that contain the same name as provide or contain obsoletes with the same name as their provide will be picked first

Closes: #189
Approved by: j-mracek
---
 src/goal.c              | 33 +++++++++++++++++++++++++++++++--
 tests/repos/greedy.repo |  2 ++
 tests/test_goal.c       | 23 +++++++++++++++++++++++
 3 files changed, 56 insertions(+), 2 deletions(-)

diff --git a/src/goal.c b/src/goal.c
index 442bc4a..480e738 100644
--- a/src/goal.c
+++ b/src/goal.c
@@ -39,6 +39,7 @@
 #include "goal_internal.h"
 #include "iutil.h"
 #include "package_internal.h"
+#include "packageset.h"
 #include "query_internal.h"
 #include "reldep_internal.h"
 #include "repo_internal.h"
@@ -353,6 +354,34 @@ job_has(Queue *job, Id what, Id id)
     return 0;
 }
 
+/**
+ * add_preferred_provide:
+ * when searching by provides the packages that contain the same
+ * name as provide or contain obsoletes with the same name as their
+ * provide will be picked first
+ */
+static void
+add_preferred_provide(HySack sack, Queue *job, Id id)
+{
+    Pool *pool = sack_pool(sack);
+    const char *name = pool_dep2str(pool, id);
+    HyQuery q = hy_query_create(sack);
+    hy_query_filter(q, HY_PKG_NAME, HY_NEQ, name);
+    HyPackageSet pset = hy_query_run_set(q);
+    hy_query_filter(q, HY_PKG_PROVIDES, HY_EQ, name);
+    hy_query_filter_package_in(q, HY_PKG_OBSOLETES, HY_NEQ, pset);
+    HyPackageList plist = hy_query_run(q);
+    for (int i = 0; i < hy_packagelist_count(plist); i++) {
+        HyPackage pkg = hy_packagelist_get(plist, i);
+        queue_push2(job, SOLVER_DISFAVOR|SOLVER_SOLVABLE,
+                    package_id(pkg));
+    }
+    queue_push2(job, SOLVER_SOLVABLE_PROVIDES, id);
+    hy_query_free(q);
+    hy_packageset_free(pset);
+    hy_packagelist_free(plist);
+}
+
 static int
 filter_arch2job(HySack sack, const struct _Filter *f, Queue *job)
 {
@@ -472,7 +501,7 @@ filter_provides2job(HySack sack, const struct _Filter *f, Queue *job)
     switch (f->cmp_type) {
     case HY_EQ:
 	id = reldep_id(f->matches[0].reldep);
-	queue_push2(job, SOLVER_SOLVABLE_PROVIDES, id);
+	add_preferred_provide(sack, job, id);
 	break;
     case HY_GLOB:
 	dataiterator_init(&di, pool, 0, 0, SOLVABLE_PROVIDES, name, SEARCH_GLOB);
@@ -483,7 +512,7 @@ filter_provides2job(HySack sack, const struct _Filter *f, Queue *job)
 	assert(di.idp);
 	id = *di.idp;
 	if (!job_has(job, SOLVABLE_PROVIDES, id))
-	    queue_push2(job, SOLVER_SOLVABLE_PROVIDES, id);
+	    add_preferred_provide(sack, job, id);
 	dataiterator_free(&di);
 	break;
     default:
diff --git a/tests/repos/greedy.repo b/tests/repos/greedy.repo
index 64bb85a..d450885 100644
--- a/tests/repos/greedy.repo
+++ b/tests/repos/greedy.repo
@@ -5,5 +5,7 @@
 =Pkg: B 1 0 noarch
 =Rec: C
 =Prv: somereq
+=Obs: somereq
 =Pkg: C 1 0 noarch
 =Prv: somereq
+=Pkg: somereq 1 0 noarch
diff --git a/tests/test_goal.c b/tests/test_goal.c
index dc7dcec..6dba956 100644
--- a/tests/test_goal.c
+++ b/tests/test_goal.c
@@ -224,6 +224,28 @@ START_TEST(test_goal_install_selector)
 }
 END_TEST
 
+START_TEST(test_goal_install_selector_obsoletes_first)
+{
+    HySelector sltr;
+    HyGoal goal = hy_goal_create(test_globals.sack);
+
+    sltr = hy_selector_create(test_globals.sack);
+    hy_selector_set(sltr, HY_PKG_PROVIDES, HY_EQ, "somereq");
+    fail_if(hy_goal_install_selector(goal, sltr));
+    hy_selector_free(sltr);
+
+    fail_if(hy_goal_run(goal));
+    assert_iueo(goal, 1, 0, 0, 0);
+
+    HyPackageList plist = hy_goal_list_installs(goal);
+    char *nvra = hy_package_get_nevra(hy_packagelist_get(plist, 0));
+    ck_assert_str_eq(nvra, "B-1-0.noarch");
+    hy_free(nvra);
+    hy_packagelist_free(plist);
+    hy_goal_free(goal);
+}
+END_TEST
+
 START_TEST(test_goal_install_selector_err)
 {
     // Test that using the hy_goal_*_selector() methods returns an error for
@@ -1309,6 +1331,7 @@ goal_suite(void)
     tc = tcase_create("Greedy");
     tcase_add_unchecked_fixture(tc, fixture_greedy_only, teardown);
     tcase_add_test(tc, test_goal_run_all);
+    tcase_add_test(tc, test_goal_install_selector_obsoletes_first);
     tcase_add_test(tc, test_goal_install_weak_deps);
     suite_add_tcase(s, tc);
 
-- 
2.11.0