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