From 3c33e4fc7b2dee1b5113ca07f4c2b2cae420a00e Mon Sep 17 00:00:00 2001
From: Nagy Gabor <ngaba@bibl.u-szeged.hu>
Date: Tue, 20 Nov 2007 09:57:38 +0100
Subject: [PATCH] _alpm_checkconflicts split

_alpm_innerconflicts: check for target<->target conflicts
_alpm_outerconflicts: check for target<->localpkg conflicts
This will be useful in sync.c clean-up and in testdb.c

As an application the patch also fixes a misleading message (and a memleak) in add.c

Signed-off-by: Nagy Gabor <ngaba@bibl.u-szeged.hu>
---
 lib/libalpm/add.c      |   25 ++++++++++++++++++-------
 lib/libalpm/conflict.c |   29 ++++++++++++++++++++++++-----
 lib/libalpm/conflict.h |    2 ++
 3 files changed, 44 insertions(+), 12 deletions(-)

diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index e6efe2d..8466876 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -135,7 +135,7 @@ error:
 
 int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)
 {
-	alpm_list_t *lp = NULL, *i = NULL;
+	alpm_list_t *lp = NULL;
 
 	ALPM_LOG_FUNC;
 
@@ -161,16 +161,19 @@ int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)
 
 		/* no unsatisfied deps, so look for conflicts */
 		_alpm_log(PM_LOG_DEBUG, "looking for conflicts\n");
-		lp = _alpm_checkconflicts(db, trans->packages);
+		alpm_list_t *inner = _alpm_innerconflicts(trans->packages);
+		alpm_list_t *outer = _alpm_outerconflicts(db, trans->packages);
+		lp = alpm_list_join(inner, outer);
+		
+		/* attempt to resolve conflicts */
+		/*
 		for(i = lp; i; i = i->next) {
 			pmconflict_t *conflict = i->data;
 
-			_alpm_log(PM_LOG_ERROR, _("replacing packages with -A and -U is not supported yet\n"));
-			_alpm_log(PM_LOG_ERROR, _("please remove '%s' first, using -Rd\n"), conflict->package2);
+			_alpm_log(PM_LOG_ERROR, _("conflict resolving with -A and -U is not supported yet\n"));
+			_alpm_log(PM_LOG_ERROR, _("you cannot install '%s' and '%s' at the same time\n"), conflict->package1, conflict->package2);
 			RET_ERR(PM_ERR_CONFLICTING_DEPS, -1);
 
-			/* Attempt to resolve conflicts */
-			/*
 			int skip_this = 0;
 			QUESTION(trans, PM_TRANS_CONV_CONFLICT_PKG, miss->target, miss->depend.name, NULL, &skip_this);
 			if(skip_this) {
@@ -191,8 +194,8 @@ int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)
 					break;
 				}
 			}
-			*/
 		}
+		*/
 		/* Removal code should go here, as described above. Instead of simply
 		 * removing items, perhaps throw them in another list to be removed, then
 		 * proceed as sync.c would? I'm not sure because I'm not familiar enough
@@ -203,6 +206,14 @@ int _alpm_add_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)
 			} else {
 				FREELIST(lp);
 			}
+			if(inner) {
+				_alpm_log(PM_LOG_ERROR, _("conflicting packages were found in the target list\n"));
+				_alpm_log(PM_LOG_ERROR, _("you cannot install two conflicting packages at the same time\n"));
+			}	
+			if(outer) {
+				_alpm_log(PM_LOG_ERROR, _("replacing packages with -A and -U is not supported yet\n"));
+				_alpm_log(PM_LOG_ERROR, _("you can replace packages manually using -Rd and -U\n"));
+			}	
 			RET_ERR(PM_ERR_CONFLICTING_DEPS, -1);
 		}
 
diff --git a/lib/libalpm/conflict.c b/lib/libalpm/conflict.c
index 7268275..7b21c38 100644
--- a/lib/libalpm/conflict.c
+++ b/lib/libalpm/conflict.c
@@ -162,8 +162,24 @@ static void check_conflict(alpm_list_t *list1, alpm_list_t *list2,
 	}
 }
 
-/* Returns a alpm_list_t* of pmconflict_t pointers. */
-alpm_list_t *_alpm_checkconflicts(pmdb_t *db, alpm_list_t *packages)
+/* Check for inter-conflicts */
+alpm_list_t *_alpm_innerconflicts(alpm_list_t *packages)
+{
+	alpm_list_t *baddeps = NULL;
+
+	ALPM_LOG_FUNC;
+
+	_alpm_log(PM_LOG_DEBUG, "check targets vs targets\n");
+	check_conflict(packages, packages, &baddeps, 0);
+
+	return(baddeps);
+}
+
+/* Check for target vs (db - target) conflicts
+ * In case of conflict the package1 field of pmdepconflict_t contains
+ * the target package, package2 field contains the local package
+ */
+alpm_list_t *_alpm_outerconflicts(pmdb_t *db, alpm_list_t *packages)
 {
 	alpm_list_t *baddeps = NULL;
 
@@ -176,18 +192,21 @@ alpm_list_t *_alpm_checkconflicts(pmdb_t *db, alpm_list_t *packages)
 	alpm_list_t *dblist = alpm_list_diff(_alpm_db_get_pkgcache(db), packages,
 			_alpm_pkg_cmp);
 
-	/* three checks to be done here for conflicts */
+	/* two checks to be done here for conflicts */
 	_alpm_log(PM_LOG_DEBUG, "check targets vs db\n");
 	check_conflict(packages, dblist, &baddeps, 1);
 	_alpm_log(PM_LOG_DEBUG, "check db vs targets\n");
 	check_conflict(dblist, packages, &baddeps, -1);
-	_alpm_log(PM_LOG_DEBUG, "check targets vs targets\n");
-	check_conflict(packages, packages, &baddeps, 0);
 
 	alpm_list_free(dblist);
 	return(baddeps);
 }
 
+/* Check for transaction conflicts */
+alpm_list_t *_alpm_checkconflicts(pmdb_t *db, alpm_list_t *packages) {
+	return(alpm_list_join(_alpm_innerconflicts(packages), _alpm_outerconflicts(db, packages)));
+}
+
 /* Returns a alpm_list_t* of file conflicts.
  *  Hooray for set-intersects!
  *  Pre-condition: both lists are sorted!
diff --git a/lib/libalpm/conflict.h b/lib/libalpm/conflict.h
index 8969535..00a593e 100644
--- a/lib/libalpm/conflict.h
+++ b/lib/libalpm/conflict.h
@@ -41,6 +41,8 @@ struct __pmfileconflict_t {
 
 pmconflict_t *_alpm_conflict_new(const char *package1, const char *package2);
 int _alpm_conflict_isin(pmconflict_t *needle, alpm_list_t *haystack);
+alpm_list_t *_alpm_innerconflicts(alpm_list_t *packages);
+alpm_list_t *_alpm_outerconflicts(pmdb_t *db, alpm_list_t *packages);
 alpm_list_t *_alpm_checkconflicts(pmdb_t *db, alpm_list_t *packages);
 alpm_list_t *_alpm_db_find_fileconflicts(pmdb_t *db, pmtrans_t *trans, char *root);
 
-- 
1.5.2.5

