From f0ea21cffca62c566c5e4d2c540c70fb891b9f4c Mon Sep 17 00:00:00 2001
From: Dan McGee <dan@archlinux.org>
Date: Sat, 14 Jul 2007 09:34:39 -0400
Subject: Ensure requiredby entries are removed during an upgrade

This fixes the failure of the requiredby004 pactest in a not so pretty way,
but it gets the job done. I purposely used the extremely long name of
PM_TRANS_TYPE_REMOVEUPGRADE to be both clear and in the hope that someone
else will figure out a better solution.

Original idea from Nagy Gabor, patch updated and cleaned for current code.

Signed-off-by: Dan McGee <dan@archlinux.org>
---
 lib/libalpm/add.c    | 32 +++++++++++++++++++++++---------
 lib/libalpm/alpm.h   |  1 +
 lib/libalpm/remove.c | 16 +++++++++-------
 lib/libalpm/trans.c  | 21 ++++++++++++++-------
 4 files changed, 47 insertions(+), 23 deletions(-)

(limited to 'lib/libalpm')

diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index e95e7a44..8a50be4c 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -355,7 +355,8 @@ int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db)
 		if(oldpkg) {
 			/* this is kinda odd.  If the old package exists, at this point we make a
 			 * NEW transaction, unrelated to handle->trans, and instantiate a "remove"
-			 * with the type PM_TRANS_TYPE_UPGRADE. TODO: kill this weird behavior. */
+			 * with the type PM_TRANS_TYPE_REMOVEUPGRADE. TODO: kill this weird
+			 * behavior. */
 			pmtrans_t *tr = _alpm_trans_new();
 			_alpm_log(PM_LOG_DEBUG, "removing old package first (%s-%s)",
 					oldpkg->name, oldpkg->version);
@@ -364,7 +365,8 @@ int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db)
 				RET_ERR(PM_ERR_TRANS_ABORT, -1);
 			}
 
-			if(_alpm_trans_init(tr, PM_TRANS_TYPE_UPGRADE, trans->flags, NULL, NULL, NULL) == -1) {
+			if(_alpm_trans_init(tr, PM_TRANS_TYPE_REMOVEUPGRADE, trans->flags,
+						NULL, NULL, NULL) == -1) {
 				_alpm_trans_free(tr);
 				tr = NULL;
 				RET_ERR(PM_ERR_TRANS_ABORT, -1);
@@ -846,23 +848,35 @@ int _alpm_add_commit(pmtrans_t *trans, pmdb_t *db)
 		/* update dependency packages' REQUIREDBY fields */
 		_alpm_trans_update_depends(trans, newpkg);
 
-		PROGRESS(trans, (is_upgrade ? PM_TRANS_PROGRESS_UPGRADE_START : PM_TRANS_PROGRESS_ADD_START),
-						 alpm_pkg_get_name(newpkg), 100, pkg_count, (pkg_count - targ_count +1));
+		if(is_upgrade) {
+			PROGRESS(trans, PM_TRANS_PROGRESS_UPGRADE_START,
+					alpm_pkg_get_name(newpkg),100, pkg_count,
+					(pkg_count - targ_count + 1));
+		} else {
+			PROGRESS(trans, PM_TRANS_PROGRESS_ADD_START,
+					alpm_pkg_get_name(newpkg),100, pkg_count,
+					(pkg_count - targ_count + 1));
+		}
 		EVENT(trans, PM_TRANS_EVT_EXTRACT_DONE, NULL, NULL);
 
 		/* run the post-install script if it exists  */
-		if(alpm_pkg_has_scriptlet(newpkg) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) {
+		if(alpm_pkg_has_scriptlet(newpkg)
+				&& !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) {
 			if(is_upgrade) {
 				_alpm_runscriptlet(handle->root, scriptlet, "post_upgrade",
-													alpm_pkg_get_version(newpkg), oldpkg ? alpm_pkg_get_version(oldpkg) : NULL,
-													trans);
+						alpm_pkg_get_version(newpkg),
+						oldpkg ? alpm_pkg_get_version(oldpkg) : NULL, trans);
 			} else {
 				_alpm_runscriptlet(handle->root, scriptlet, "post_install",
-													 alpm_pkg_get_version(newpkg), NULL, trans);
+						alpm_pkg_get_version(newpkg), NULL, trans);
 			}
 		}
 
-		EVENT(trans, (is_upgrade) ? PM_TRANS_EVT_UPGRADE_DONE : PM_TRANS_EVT_ADD_DONE, newpkg, oldpkg);
+		if(is_upgrade) {
+			EVENT(trans, PM_TRANS_EVT_UPGRADE_DONE, newpkg, oldpkg);
+		} else {
+			EVENT(trans, PM_TRANS_EVT_ADD_DONE, newpkg, oldpkg);
+		}
 
 		_alpm_pkg_free(oldpkg);
 	}
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index 268437ba..8181f2e6 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -247,6 +247,7 @@ void *alpm_sync_get_data(const pmsyncpkg_t *sync);
 typedef enum _pmtranstype_t {
 	PM_TRANS_TYPE_ADD = 1,
 	PM_TRANS_TYPE_REMOVE,
+	PM_TRANS_TYPE_REMOVEUPGRADE,
 	PM_TRANS_TYPE_UPGRADE,
 	PM_TRANS_TYPE_SYNC
 } pmtranstype_t;
diff --git a/lib/libalpm/remove.c b/lib/libalpm/remove.c
index 775bd563..33c122d7 100644
--- a/lib/libalpm/remove.c
+++ b/lib/libalpm/remove.c
@@ -96,7 +96,8 @@ int _alpm_remove_prepare(pmtrans_t *trans, pmdb_t *db, alpm_list_t **data)
 	ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
 	ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
 
-	if(trans->type == PM_TRANS_TYPE_UPGRADE) {
+	/* skip all checks if we are doing this removal as part of an upgrade */
+	if(trans->type == PM_TRANS_TYPE_REMOVEUPGRADE) {
 		return(0);
 	}
 
@@ -205,7 +206,7 @@ static void unlink_file(pmpkg_t *info, alpm_list_t *lp, alpm_list_t *targ,
 	
 	snprintf(file, PATH_MAX, "%s%s", handle->root, (char *)lp->data);
 
-	if(trans->type == PM_TRANS_TYPE_UPGRADE) {
+	if(trans->type == PM_TRANS_TYPE_REMOVEUPGRADE) {
 		/* check noupgrade */
 		if(alpm_list_find_str(handle->noupgrade, lp->data)) {
 			_alpm_log(PM_LOG_DEBUG, "Skipping removal of '%s' due to NoUpgrade", file);
@@ -234,7 +235,7 @@ static void unlink_file(pmpkg_t *info, alpm_list_t *lp, alpm_list_t *targ,
 			return;
 		} else if(needbackup) {
 			/* if the file is flagged, back it up to .pacsave */
-			if(!(trans->type == PM_TRANS_TYPE_UPGRADE)) {
+			if(!(trans->type == PM_TRANS_TYPE_REMOVEUPGRADE)) {
 				/* if it was an upgrade, the file would be left alone because
 				 * pacman_add() would handle it */
 				if(!(trans->flags & PM_TRANS_FLAG_NOSAVE)) {
@@ -286,7 +287,7 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db)
 		snprintf(scriptlet, PATH_MAX, "%s%s-%s/install", db->path,
 						 pkgname, alpm_pkg_get_version(info));
 
-		if(trans->type != PM_TRANS_TYPE_UPGRADE) {
+		if(trans->type != PM_TRANS_TYPE_REMOVEUPGRADE) {
 			EVENT(trans, PM_TRANS_EVT_REMOVE_START, info, NULL);
 			_alpm_log(PM_LOG_DEBUG, "removing package %s-%s",
 								pkgname, alpm_pkg_get_version(info));
@@ -323,7 +324,7 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db)
 		         alpm_list_count(trans->packages),
 		         (alpm_list_count(trans->packages) - alpm_list_count(targ) +1));
 
-		if(trans->type != PM_TRANS_TYPE_UPGRADE) {
+		if(trans->type != PM_TRANS_TYPE_REMOVEUPGRADE) {
 			/* run the post-remove script if it exists  */
 			if(alpm_pkg_has_scriptlet(info) && !(trans->flags & PM_TRANS_FLAG_NOSCRIPTLET)) {
 				_alpm_runscriptlet(handle->root, scriptlet, "post_remove",
@@ -352,13 +353,14 @@ int _alpm_remove_commit(pmtrans_t *trans, pmdb_t *db)
 		_alpm_pkg_free(infodup);
 
 		/* call a done event if this isn't an upgrade */
-		if(trans->type != PM_TRANS_TYPE_UPGRADE) {
+		if(trans->type != PM_TRANS_TYPE_REMOVEUPGRADE) {
 			EVENT(trans, PM_TRANS_EVT_REMOVE_DONE, info, NULL);
 		}
 	}
 
 	/* run ldconfig if it exists */
-	if((trans->type != PM_TRANS_TYPE_UPGRADE) && (handle->trans->state != STATE_INTERRUPTED)) {
+	if((trans->type != PM_TRANS_TYPE_REMOVEUPGRADE)
+			&& (handle->trans->state != STATE_INTERRUPTED)) {
 		_alpm_log(PM_LOG_DEBUG, "running \"ldconfig -r %s\"", handle->root);
 		_alpm_ldconfig(handle->root);
 	}
diff --git a/lib/libalpm/trans.c b/lib/libalpm/trans.c
index d940438e..7d7e2021 100644
--- a/lib/libalpm/trans.c
+++ b/lib/libalpm/trans.c
@@ -322,14 +322,15 @@ int _alpm_trans_addtarget(pmtrans_t *trans, char *target)
 			}
 		break;
 		case PM_TRANS_TYPE_REMOVE:
+		case PM_TRANS_TYPE_REMOVEUPGRADE:
 			if(_alpm_remove_loadtarget(trans, handle->db_local, target) == -1) {
-				/* pm_errno is set by remove_loadtarget() */
+				/* pm_errno is set by _alpm_remove_loadtarget() */
 				return(-1);
 			}
 		break;
 		case PM_TRANS_TYPE_SYNC:
 			if(_alpm_sync_addtarget(trans, handle->db_local, handle->dbs_sync, target) == -1) {
-				/* pm_errno is set by sync_loadtarget() */
+				/* pm_errno is set by _alpm_sync_loadtarget() */
 				return(-1);
 			}
 		break;
@@ -363,6 +364,7 @@ int _alpm_trans_prepare(pmtrans_t *trans, alpm_list_t **data)
 			}
 		break;
 		case PM_TRANS_TYPE_REMOVE:
+		case PM_TRANS_TYPE_REMOVEUPGRADE:
 			if(_alpm_remove_prepare(trans, handle->db_local, data) == -1) {
 				/* pm_errno is set by _alpm_remove_prepare() */
 				return(-1);
@@ -402,13 +404,14 @@ int _alpm_trans_commit(pmtrans_t *trans, alpm_list_t **data)
 		case PM_TRANS_TYPE_ADD:
 		case PM_TRANS_TYPE_UPGRADE:
 			if(_alpm_add_commit(trans, handle->db_local) == -1) {
-				/* pm_errno is set by _alpm_add_prepare() */
+				/* pm_errno is set by _alpm_add_commit() */
 				return(-1);
 			}
 		break;
 		case PM_TRANS_TYPE_REMOVE:
+		case PM_TRANS_TYPE_REMOVEUPGRADE:
 			if(_alpm_remove_commit(trans, handle->db_local) == -1) {
-				/* pm_errno is set by _alpm_remove_prepare() */
+				/* pm_errno is set by _alpm_remove_commit() */
 				return(-1);
 			}
 		break;
@@ -484,12 +487,14 @@ int _alpm_trans_update_depends(pmtrans_t *trans, pmpkg_t *pkg)
 
 				_alpm_log(PM_LOG_DEBUG, "updating 'requiredby' field for package '%s'",
 				          alpm_pkg_get_name(deppkg));
-				if(trans->type == PM_TRANS_TYPE_REMOVE) {
+				if(trans->type == PM_TRANS_TYPE_REMOVE
+						|| trans->type == PM_TRANS_TYPE_REMOVEUPGRADE) {
 					void *data = NULL;
 					rqdby = alpm_list_remove(rqdby,	pkgname, _alpm_str_cmp, &data);
 					FREE(data);
 					deppkg->requiredby = rqdby;
 				} else {
+					/* sanity check to make sure package was not already in list */
 					if(!alpm_list_find_str(rqdby, pkgname)) {
 						rqdby = alpm_list_add(rqdby, strdup(pkgname));
 						deppkg->requiredby = rqdby;
@@ -514,12 +519,14 @@ int _alpm_trans_update_depends(pmtrans_t *trans, pmpkg_t *pkg)
 
 		_alpm_log(PM_LOG_DEBUG, "updating 'requiredby' field for package '%s'",
 		          alpm_pkg_get_name(deppkg));
-		if(trans->type == PM_TRANS_TYPE_REMOVE) {
+		if(trans->type == PM_TRANS_TYPE_REMOVE
+						|| trans->type == PM_TRANS_TYPE_REMOVEUPGRADE) {
 			void *data = NULL;
 			rqdby = alpm_list_remove(rqdby, pkgname, _alpm_str_cmp, &data);
 			FREE(data);
 			deppkg->requiredby = rqdby;
 		} else {
+			/* sanity check to make sure package was not already in list */
 			if(!alpm_list_find_str(rqdby, pkgname)) {
 				rqdby = alpm_list_add(rqdby, strdup(pkgname));
 				deppkg->requiredby = rqdby;
@@ -528,7 +535,7 @@ int _alpm_trans_update_depends(pmtrans_t *trans, pmpkg_t *pkg)
 
 		if(_alpm_db_write(localdb, deppkg, INFRQ_DEPENDS)) {
 			_alpm_log(PM_LOG_ERROR, _("could not update 'requiredby' database entry %s-%s"),
-								alpm_pkg_get_name(deppkg), alpm_pkg_get_version(deppkg));
+					alpm_pkg_get_name(deppkg), alpm_pkg_get_version(deppkg));
 		}
 		free(dep);
 	}
-- 
cgit v1.2.3-70-g09d2