[pacman-dev] [PATCH] libalpm/sync.c : conflicts resolving cleanup.

Nagy Gabor shiningxc at gmail.com
Mon Nov 26 11:04:09 EST 2007


The original patch from Nagy tried to resolve target vs target conflicts,
and so broke the following pactests :
sync040, sync041 and sync990

Nagy's proposal to solve this situation was to choose the interactive way,
ask the user how to deal with it:
either remove pkg1 or remove pkg2 or stop here.
So he left this as a TODO.

But instead of trying to resolve these conflicts or asking the user, I
simply made pacman fail in this case.  It's simpler, and still acceptable in
my opinion.  However, this broke the following pactests :
sync893, sync897, sync898, sync992, sync999
But some of them are rather strange..
Reference:
http://www.archlinux.org/pipermail/pacman-dev/2007-October/009745.html

Signed-off-by: Chantry Xavier <shiningxc at gmail.com>
---
 lib/libalpm/sync.c |  222 +++++++++++++++-------------------------------------
 1 files changed, 62 insertions(+), 160 deletions(-)

diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index f6fa318..a2bc39c 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -385,20 +385,6 @@ int _alpm_sync_addtarget(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sy
 	return(0);
 }
 
-/* Helper functions for alpm_list_remove
- */
-static int syncpkg_cmp(const void *s1, const void *s2)
-{
-	const pmsyncpkg_t *sp1 = s1;
-	const pmsyncpkg_t *sp2 = s2;
-	pmpkg_t *p1, *p2;
-
-  p1 = alpm_sync_get_pkg(sp1);
-  p2 = alpm_sync_get_pkg(sp2);
-
-	return(strcmp(alpm_pkg_get_name(p1), alpm_pkg_get_name(p2)));
-}
-
 int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, alpm_list_t **data)
 {
 	alpm_list_t *deps = NULL;
@@ -490,170 +476,86 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
 		EVENT(trans, PM_TRANS_EVT_INTERCONFLICTS_START, NULL, NULL);
 
 		_alpm_log(PM_LOG_DEBUG, "looking for conflicts\n");
-		deps = _alpm_checkconflicts(db_local, list);
+
+		/* 1. check for conflicts in the target list */
+		_alpm_log(PM_LOG_DEBUG, "check targets vs targets\n");
+		deps = _alpm_innerconflicts(list);
+
+		/* TODO : should we try to resolve targets vs targets conflicts? */
 		if(deps) {
-			int errorout = 0;
-			alpm_list_t *asked = NULL;
-			pmconflict_t *conflict = NULL;
-
-			for(i = deps; i && !errorout; i = i->next) {
-				pmsyncpkg_t *sync;
-				pmpkg_t *found = NULL;
-
-				conflict = i->data;
-				_alpm_log(PM_LOG_DEBUG, "package '%s' conflicts with '%s'\n",
-						conflict->package1, conflict->package2);
-				/* check if the conflicting package is about to be removed/replaced.
-				 * if so, then just ignore it. */
-				for(j = trans->packages; j && !found; j = j->next) {
-					sync = j->data;
-					if(sync->type == PM_SYNC_TYPE_REPLACE) {
-						found = _alpm_pkg_find(conflict->package2, sync->data);
-					}
-				}
-				if(found) {
-					_alpm_log(PM_LOG_DEBUG, "'%s' is already elected for removal -- skipping\n",
-							alpm_pkg_get_name(found));
-					continue;
-				}
+				pm_errno = PM_ERR_CONFLICTING_DEPS;
+				ret = -1;
+				*data = deps;
+				goto cleanup;
+		}
 
-				sync = _alpm_sync_find(trans->packages, conflict->package1);
-				if(sync == NULL) {
-					_alpm_log(PM_LOG_DEBUG, "'%s' not found in transaction set -- skipping\n",
-					          conflict->package1);
-					continue;
-				}
-				pmpkg_t *local = _alpm_db_get_pkgfromcache(db_local, conflict->package2);
-				/* check if this package provides the package it's conflicting with */
-				if(alpm_list_find(alpm_pkg_get_provides(sync->pkg),
-							conflict->package2, _alpm_prov_cmp)) {
-					/* treat like a replaces item so requiredby fields are
-					 * inherited properly. */
-					_alpm_log(PM_LOG_DEBUG, "package '%s' provides its own conflict\n",
-							conflict->package1);
-					if(!local) {
-						char *rmpkg = NULL;
-						int target, depend;
-						/* hmmm, package2 isn't installed, so it must be conflicting
-						 * with another package in our final list.  For example:
-						 *
-						 *     pacman -S blackbox xfree86
-						 *
-						 * If no x-servers are installed and blackbox pulls in xorg, then
-						 * xorg and xfree86 will conflict with each other.  In this case,
-						 * we should follow the user's preference and rip xorg out of final,
-						 * opting for xfree86 instead.
-						 */
-
-						/* figure out which one was requested in targets. If they both
-						 * were, then it's still an unresolvable conflict. */
-						target = alpm_list_find_str(trans->targets, conflict->package1);
-						depend = alpm_list_find_str(trans->targets, conflict->package2);
-						if(depend && !target) {
-							_alpm_log(PM_LOG_DEBUG, "'%s' is in the target list -- keeping it\n",
-								conflict->package2);
-							/* remove conflict->package1 */
-							rmpkg = conflict->package1;
-						} else if(target && !depend) {
-							_alpm_log(PM_LOG_DEBUG, "'%s' is in the target list -- keeping it\n",
-								conflict->package1);
-							/* remove conflict->package2 */
-							rmpkg = conflict->package2;
-						} else {
-							/* miss->target2 is not needed, miss->target already provides
-							 * it, let's resolve the conflict */
-							rmpkg = conflict->package2;
-						}
-						if(rmpkg) {
-							pmsyncpkg_t *rsync = _alpm_sync_find(trans->packages, rmpkg);
-							void *vpkg;
-							_alpm_log(PM_LOG_DEBUG, "removing '%s' from target list\n",
-									rsync->pkg->name);
-							trans->packages = alpm_list_remove(trans->packages, rsync,
-									syncpkg_cmp, &vpkg);
-							_alpm_sync_free(vpkg);
-							continue;
-						}
+		/* 2. we check for target vs db conflicts (and resolve)*/
+		_alpm_log(PM_LOG_DEBUG, "check targets vs db and db vs targets\n");
+		deps = _alpm_outerconflicts(db_local, list);
+
+		for(i = deps; i; i = i->next) {
+			pmconflict_t *conflict = i->data;
+
+			/* if conflict->package2 (the local package) is not elected for removal,
+			   we ask the user */
+			int found = 0;
+			for(j = trans->packages; j && !found; j = j->next) {
+				pmsyncpkg_t *sync = j->data;
+				if(sync->type == PM_SYNC_TYPE_REPLACE) {
+					if(_alpm_pkg_find(conflict->package2, sync->data)) {
+						found = 1;
 					}
 				}
-				/* It's a conflict -- see if they want to remove it */
-				_alpm_log(PM_LOG_DEBUG, "resolving package '%s' conflict\n",
-						conflict->package1);
-				if(local) {
-					int doremove = 0;
-					if(!alpm_list_find_str(asked, conflict->package2)) {
-						QUESTION(trans, PM_TRANS_CONV_CONFLICT_PKG, conflict->package1,
+			}
+			if(found) {
+				continue;
+			}
+
+			_alpm_log(PM_LOG_DEBUG, "package '%s' conflicts with '%s'\n",
+					conflict->package1, conflict->package2);
+
+			pmsyncpkg_t *sync = _alpm_sync_find(trans->packages, conflict->package1);
+			pmpkg_t *local = _alpm_db_get_pkgfromcache(db_local, conflict->package2);
+			int doremove = 0;
+			QUESTION(trans, PM_TRANS_CONV_CONFLICT_PKG, conflict->package1,
 								conflict->package2, NULL, &doremove);
-						asked = alpm_list_add(asked, strdup(conflict->package2));
-						if(doremove) {
-							pmpkg_t *q = _alpm_pkg_dup(local);
-							if(sync->type != PM_SYNC_TYPE_REPLACE) {
-								/* switch this sync type to REPLACE */
-								sync->type = PM_SYNC_TYPE_REPLACE;
-								_alpm_pkg_free(sync->data);
-								sync->data = NULL;
-							}
-							/* append to the replaces list */
-							_alpm_log(PM_LOG_DEBUG, "electing '%s' for removal\n",
-									conflict->package2);
-							sync->data = alpm_list_add(sync->data, q);
-							/* see if the package is in the current target list */
-							pmsyncpkg_t *rsync = _alpm_sync_find(trans->packages,
-									conflict->package2);
-							if(rsync) {
-								/* remove it from the target list */
-								void *vpkg;
-								_alpm_log(PM_LOG_DEBUG, "removing '%s' from target list\n",
-										conflict->package2);
-								trans->packages = alpm_list_remove(trans->packages, rsync,
-										syncpkg_cmp, &vpkg);
-								_alpm_sync_free(vpkg);
-							}
-						} else {
-							/* abort */
-							_alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n"));
-							errorout = 1;
-						}
-					}
-				} else {
-					_alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n"));
-					errorout = 1;
+			if(doremove) {
+				pmpkg_t *q = _alpm_pkg_dup(local);
+				if(sync->type != PM_SYNC_TYPE_REPLACE) {
+					/* switch this sync type to REPLACE */
+					sync->type = PM_SYNC_TYPE_REPLACE;
+					_alpm_pkg_free(sync->data);
+					sync->data = NULL;
 				}
-			}
-			if(errorout) {
-				/* The last conflict was unresolvable, so we duplicate it and add it to *data */
-				pm_errno = PM_ERR_CONFLICTING_DEPS;
+				/* append to the replaces list */
+				_alpm_log(PM_LOG_DEBUG, "electing '%s' for removal\n", conflict->package2);
+				sync->data = alpm_list_add(sync->data, q);
+			} else { /* abort */
+				_alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n"));
 				if(data) {
-					pmconflict_t *lastconflict = conflict;
-					if((conflict = malloc(sizeof(pmconflict_t))) == NULL) {
-						_alpm_log(PM_LOG_ERROR, _("malloc failure: could not allocate %zd bytes\n"),
-								sizeof(pmconflict_t));
+					pmconflict_t *retconflict;
+					if((retconflict = malloc(sizeof(pmconflict_t))) == NULL) {
+						_alpm_log(PM_LOG_ERROR, _("malloc failure: could not allocate %zd bytes\n"), sizeof(pmconflict_t));
 						FREELIST(*data);
 						pm_errno = PM_ERR_MEMORY;
-					} else {
-						*conflict = *lastconflict;
-						*data = alpm_list_add(*data, conflict);
+						ret = -1;
+						goto cleanup;
 					}
+					*retconflict = *conflict;
+					*data = alpm_list_add(*data, retconflict);
 				}
-				FREELIST(asked);
-				FREELIST(deps);
+				pm_errno = PM_ERR_CONFLICTING_DEPS;
 				ret = -1;
+				FREELIST(deps);
 				goto cleanup;
 			}
-			FREELIST(asked);
-			FREELIST(deps);
 		}
 		EVENT(trans, PM_TRANS_EVT_INTERCONFLICTS_DONE, NULL, NULL);
+		FREELIST(deps);
 	}
 
 	if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) {
-		/* rebuild remove and list */
-		alpm_list_free(list);
-		list = NULL;
-		for(i = trans->packages; i; i = i->next) {
-			pmsyncpkg_t *sync = i->data;
-			list = alpm_list_add(list, sync->pkg);
-		}
+		/* rebuild remove list */
 		alpm_list_free(remove);
 		remove = NULL;
 		for(i = trans->packages; i; i = i->next) {
@@ -670,7 +572,7 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync
 		if(deps) {
 			pm_errno = PM_ERR_UNSATISFIED_DEPS;
 			ret = -1;
-			FREELIST(deps);
+			*data = deps;
 			goto cleanup;
 		}
 	}
-- 
1.5.3.6





More information about the pacman-dev mailing list