From 7561a501b4336648cbed647d608320dad50b3dbc Mon Sep 17 00:00:00 2001
From: Timo Teräs <timo.teras@iki.fi>
Date: Thu, 14 Jun 2018 20:40:05 +0300
Subject: fetch: ignore conflicts when solving --recursive fetches

---
 src/apk_solver.h |  1 +
 src/fetch.c      |  2 +-
 src/solver.c     | 31 +++++++++++++++++++++++--------
 3 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/src/apk_solver.h b/src/apk_solver.h
index b6067e2..b8b072d 100644
--- a/src/apk_solver.h
+++ b/src/apk_solver.h
@@ -34,6 +34,7 @@ struct apk_changeset {
 #define APK_SOLVERF_AVAILABLE		0x0002
 #define APK_SOLVERF_REINSTALL		0x0004
 #define APK_SOLVERF_LATEST		0x0008
+#define APK_SOLVERF_IGNORE_CONFLICT	0x0010
 
 void apk_solver_set_name_flags(struct apk_name *name,
 			       unsigned short solver_flags,
diff --git a/src/fetch.c b/src/fetch.c
index 9707752..e745d84 100644
--- a/src/fetch.c
+++ b/src/fetch.c
@@ -240,7 +240,7 @@ static void mark_names_recursive(struct apk_database *db, struct apk_string_arra
 	struct apk_change *change;
 	int r;
 
-	r = apk_solver_solve(db, 0, ctx->world, &changeset);
+	r = apk_solver_solve(db, APK_SOLVERF_IGNORE_CONFLICT, ctx->world, &changeset);
 	if (r == 0) {
 		foreach_array_item(change, changeset.changes)
 			mark_package(ctx, change->new_pkg);
diff --git a/src/solver.c b/src/solver.c
index d27a7a3..7abc80c 100644
--- a/src/solver.c
+++ b/src/solver.c
@@ -39,6 +39,7 @@ struct apk_solver_state {
 	unsigned int solver_flags_inherit;
 	unsigned int pinning_inherit;
 	unsigned int default_repos;
+	unsigned ignore_conflict : 1;
 };
 
 static struct apk_provider provider_none = {
@@ -156,6 +157,9 @@ static int dependency_satisfiable(struct apk_solver_state *ss, struct apk_depend
 	struct apk_name *name = dep->name;
 	struct apk_provider *p;
 
+	if (dep->conflict && ss->ignore_conflict)
+		return TRUE;
+
 	if (name->ss.locked)
 		return apk_dep_is_provided(dep, &name->ss.chosen);
 
@@ -284,6 +288,9 @@ static void apply_constraint(struct apk_solver_state *ss, struct apk_package *pp
 		apk_version_op_string(dep->result_mask),
 		BLOB_PRINTF(*dep->version));
 
+	if (dep->conflict && ss->ignore_conflict)
+		return;
+
 	name->ss.requirers += !dep->conflict;
 	if (name->ss.requirers == 1 && !dep->conflict)
 		name_requirers_changed(ss, name);
@@ -309,7 +316,7 @@ static void exclude_non_providers(struct apk_solver_state *ss, struct apk_name *
 	struct apk_provider *p;
 	struct apk_dependency *d;
 
-	if (name == must_provide)
+	if (name == must_provide || ss->ignore_conflict)
 		return;
 
 	dbg_printf("%s must provide %s (skip_virtuals=%d)\n", name->name, must_provide->name, skip_virtuals);
@@ -624,6 +631,8 @@ static void assign_name(struct apk_solver_state *ss, struct apk_name *name, stru
 		if (p.version == &apk_null_blob &&
 		    name->ss.chosen.version == &apk_null_blob)
 			return;
+		if (ss->ignore_conflict)
+			return;
 		/* Conflict: providing same name */
 		mark_error(ss, p.pkg, "conflict: same name provided");
 		mark_error(ss, name->ss.chosen.pkg, "conflict: same name provided");
@@ -641,13 +650,15 @@ static void assign_name(struct apk_solver_state *ss, struct apk_name *name, stru
 		list_del(&name->ss.dirty_list);
 
 	/* disqualify all conflicting packages */
-	foreach_array_item(p0, name->providers) {
-		if (p0->pkg == p.pkg)
-			continue;
-		if (p.version == &apk_null_blob &&
-		    p0->version == &apk_null_blob)
-			continue;
-		disqualify_package(ss, p0->pkg, "conflicting provides");
+	if (!ss->ignore_conflict) {
+		foreach_array_item(p0, name->providers) {
+			if (p0->pkg == p.pkg)
+				continue;
+			if (p.version == &apk_null_blob &&
+			    p0->version == &apk_null_blob)
+				continue;
+			disqualify_package(ss, p0->pkg, "conflicting provides");
+		}
 	}
 	reevaluate_reverse_deps(ss, name);
 	reevaluate_reverse_installif(ss, name);
@@ -880,6 +891,9 @@ static void cset_gen_dep(struct apk_solver_state *ss, struct apk_package *ppkg,
 	struct apk_name *name = dep->name;
 	struct apk_package *pkg = name->ss.chosen.pkg;
 
+	if (dep->conflict && ss->ignore_conflict)
+		return;
+
 	if (!apk_dep_is_provided(dep, &name->ss.chosen))
 		mark_error(ss, ppkg, "unfulfilled dependency");
 
@@ -974,6 +988,7 @@ restart:
 	ss->db = db;
 	ss->changeset = changeset;
 	ss->default_repos = apk_db_get_pinning_mask_repos(db, APK_DEFAULT_PINNING_MASK);
+	ss->ignore_conflict = !!(solver_flags & APK_SOLVERF_IGNORE_CONFLICT);
 	list_init(&ss->dirty_head);
 	list_init(&ss->unresolved_head);
 
-- 
cgit v1.2.3-70-g09d2