From 0074e9e312d07ffed9677f2a474c6fe3aa7684fa Mon Sep 17 00:00:00 2001
From: Aurelien Foret <aurelien@archlinux.org>
Date: Wed, 6 Apr 2005 21:01:40 +0000
Subject: more work to backport the sync features from pacman 2.9.5

---
 lib/libalpm/sync.c | 200 ++++++++++++++++++++++++++++++++++++-----------------
 lib/libalpm/sync.h |   2 +
 2 files changed, 138 insertions(+), 64 deletions(-)

diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index 03ccb915..da3e292d 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -42,21 +42,52 @@
 
 extern pmhandle_t *handle;
 
-pmsync_t *sync_new(int type, pmpkg_t *lpkg, pmpkg_t *spkg)
+pmsyncpkg_t *sync_new(int type, pmpkg_t *lpkg, pmpkg_t *spkg)
 {
-	pmsync_t *sync;
+	pmsyncpkg_t *sync;
 
-	if((sync = (pmsync_t *)malloc(sizeof(pmsync_t))) == NULL) {
+	if((sync = (pmsyncpkg_t *)malloc(sizeof(pmsyncpkg_t))) == NULL) {
 		return(NULL);
 	}
 
 	sync->type = type;
 	sync->lpkg = lpkg;
 	sync->spkg = spkg;
+	sync->replaces = NULL;
 	
 	return(sync);
 }
 
+void sync_free(pmsyncpkg_t *sync)
+{
+	if(sync) {
+		FREELISTPTR(sync->replaces);
+		free(sync);
+	}
+}
+
+/* Test for existance of a package in a PMList* of pmsyncpkg_t*
+ * If found, return a pointer to the respective pmsyncpkg_t*
+ */
+static pmsyncpkg_t* find_pkginsync(char *needle, PMList *haystack)
+{
+	PMList *i;
+	pmsyncpkg_t *sync = NULL;
+	int found = 0;
+
+	for(i = haystack; i && !found; i = i->next) {
+		sync = i->data;
+		if(sync && !strcmp(sync->spkg->name, needle)) {
+			found = 1;
+		}
+	}
+	if(!found) {
+		sync = NULL;
+	}
+
+	return(sync);
+}
+
 /* It returns a PMList of packages extracted from the given archive
  * (the archive must have been generated by gensync)
  */
@@ -119,7 +150,7 @@ int sync_sysupgrade(PMList **data)
 							_alpm_log(PM_LOG_WARNING, "%s-%s: ignoring package upgrade (to be replaced by %s-%s)",
 								lpkg->name, lpkg->version, spkg->name, spkg->version);
 						} else {
-							pmsync_t *sync = sync_new(PM_SYSUPG_REPLACE, lpkg, spkg);
+							pmsyncpkg_t *sync = sync_new(PM_SYNC_TYPE_REPLACE, lpkg, spkg);
 							if(sync == NULL) {
 								pm_errno = PM_ERR_MEMORY;
 								goto error;
@@ -139,7 +170,7 @@ int sync_sysupgrade(PMList **data)
 		int cmp;
 		pmpkg_t *local = i->data;
 		pmpkg_t *spkg = NULL;
-		pmsync_t *sync;
+		pmsyncpkg_t *sync;
 
 		for(j = handle->dbs_sync; !spkg && j; j = j->next) {
 
@@ -168,7 +199,7 @@ int sync_sysupgrade(PMList **data)
 			_alpm_log(PM_LOG_FLOW1, "%s-%s: ignoring package upgrade (%s)",
 				local->name, local->version, spkg->version);
 		} else {
-			sync = sync_new(PM_SYSUPG_UPGRADE, local, spkg);
+			sync = sync_new(PM_SYNC_TYPE_UPGRADE, local, spkg);
 			if(sync == NULL) {
 				pm_errno = PM_ERR_MEMORY;
 				goto error;
@@ -191,76 +222,90 @@ error:
 int sync_addtarget(pmdb_t *db, PMList *dbs_sync, pmtrans_t *trans, char *name)
 {
 	char targline[(PKG_NAME_LEN-1)+1+(DB_TREENAME_LEN-1)+1];
-	char *targ, *treename;
+	char *targ;
 	PMList *j;
 	pmpkg_t *local;
-	pmpkg_t *sync = NULL;
+	pmpkg_t *spkg = NULL;
+	pmsyncpkg_t *sync;
 	int cmp;
 
 	ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
 	ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
 	ASSERT(name != NULL, RET_ERR(PM_ERR_WRONG_ARGS, -1));
 
+	if(trans->flags & PM_TRANS_FLAG_SYSUPG) {
+	}
+
 	strncpy(targline, name, (PKG_NAME_LEN-1)+1+(DB_TREENAME_LEN-1)+1);
 	targ = strchr(targline, '/');
 	if(targ) {
 		*targ = '\0';
 		targ++;
-		treename = targline;
-		for(j = dbs_sync; j && !sync; j = j->next) {
+		for(j = dbs_sync; j && !spkg; j = j->next) {
 			pmdb_t *dbs = j->data;
 			if(strcmp(dbs->treename, targline) == 0) {
-				sync = db_scan(dbs, targ, INFRQ_DESC|INFRQ_DEPENDS);
+				spkg = db_get_pkgfromcache(dbs, targ);
+				if(spkg == NULL) {
+					RET_ERR(PM_ERR_PKG_NOT_FOUND, -1);
+				}
 			}
 		}
 	} else {
 		targ = targline;
-		for(j = dbs_sync; j && !sync; j = j->next) {
+		for(j = dbs_sync; j && !spkg; j = j->next) {
 			pmdb_t *dbs = j->data;
-			sync = db_scan(dbs, targ, INFRQ_DESC|INFRQ_DEPENDS);
+			spkg = db_get_pkgfromcache(dbs, targ);
+			if(spkg == NULL) {
+				continue;
+			}
 		}
 	}
-	if(sync == NULL) {
+	if(spkg == NULL) {
 		RET_ERR(PM_ERR_PKG_NOT_FOUND, -1);
 	}
 
-	/* if not a sysupgrade, compare versions and determine if it is necessary */
-	if(!trans->flags & PM_TRANS_FLAG_SYSUPG) {
-		local = db_get_pkgfromcache(db, name);
-		if(local) {
-			cmp = alpm_pkg_vercmp(local->version, sync->version);
-			if(cmp > 0) {
-				/* local version is newer - get confirmation first */
-				/* ORE
-				if(!yesno(":: %s-%s: local version is newer.  Upgrade anyway? [Y/n] ", lpkgname, lpkgver)) {
-				}*/
-				_alpm_log(PM_LOG_WARNING, "%s-%s: local version is newer -- skipping");
-				FREE(sync);
-				return(0);
-			} else if(cmp == 0) {
-				/* versions are identical */
-				/* ORE
-				if(!yesno(":: %s-%s: is up to date.  Upgrade anyway? [Y/n] ", lpkgname, lpkgver)) {
-				}*/
-				_alpm_log(PM_LOG_WARNING, "%s-%s: is up to date -- skipping");
-				FREE(sync);
-				return(0);
-			}
+	local = db_get_pkgfromcache(db, name);
+	if(local) {
+		cmp = alpm_pkg_vercmp(local->version, spkg->version);
+		if(cmp > 0) {
+			/* local version is newer - get confirmation first */
+			/* ORE
+			if(!yesno(":: %s-%s: local version is newer.  Upgrade anyway? [Y/n] ", lpkgname, lpkgver)) {
+			}*/
+			_alpm_log(PM_LOG_WARNING, "%s-%s: local version is newer -- skipping");
+			return(0);
+		} else if(cmp == 0) {
+			/* versions are identical */
+			/* ORE
+			if(!yesno(":: %s-%s: is up to date.  Upgrade anyway? [Y/n] ", lpkgname, lpkgver)) {
+			}*/
+			_alpm_log(PM_LOG_WARNING, "%s-%s: is up to date -- skipping");
+			return(0);
 		}
 	}
 
+	sync = sync_new(PM_SYNC_TYPE_UPGRADE, local, spkg);
+	if(sync == NULL) {
+		RET_ERR(PM_ERR_MEMORY, -1);
+	}
 	/* add the package to the transaction */
-	trans->packages = pm_list_add(trans->packages, sync);
+	if(!find_pkginsync(sync->spkg->name, trans->packages)) {
+		trans->packages = pm_list_add(trans->packages, sync);
+	}
 
 	return(0);
 }
 
 int sync_prepare(pmdb_t *db, pmtrans_t *trans, PMList **data)
 {
+	PMList *deps = NULL;
 	PMList *list = NULL;
 	PMList *trail = NULL;
 	PMList *i;
 
+	ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
+	ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
+
 	if(trans->packages == NULL) {
 		return(0);
 	}
@@ -269,46 +314,62 @@ int sync_prepare(pmdb_t *db, pmtrans_t *trans, PMList **data)
 	if(!(trans->flags & PM_TRANS_FLAG_NODEPS)) {
 		TRANS_CB(trans, PM_TRANS_EVT_RESOLVEDEPS_START, NULL, NULL);
 
-		list = pm_list_new();
-		trail = pm_list_new();
-
 		for(i = trans->packages; i; i = i->next) {
-			pmpkg_t *sync = i->data;
-			_alpm_log(PM_LOG_FLOW1, "resolving dependencies for package %s", sync->name);
-			if(resolvedeps(handle->db_local, handle->dbs_sync, sync, list, trail) == -1) {
+			pmsyncpkg_t *sync = i->data;
+			list = pm_list_add(list, sync->spkg);
+		}
+		trail = pm_list_new();
+		for(i = list; i; i = i->next) {
+			pmpkg_t *spkg = i->data;
+			_alpm_log(PM_LOG_FLOW1, "resolving dependencies for package %s", spkg->name);
+			if(resolvedeps(handle->db_local, handle->dbs_sync, spkg, trans->packages, trail) == -1) {
 				/* pm_errno is set by resolvedeps */
 				goto error;
 			}
 			/* ORE
 			if called from makepkg, reason should be set to REASON_DEPEND */
-			sync->reason = PM_PKG_REASON_EXPLICIT;
-		}
-		FREELISTPTR(trail);
-
-		for(i = list; i; i = i->next) {
-			pmpkg_t *sync = i->data;
-			if(sync == NULL) {
-				continue;
-			}
-			if(!pkg_isin(sync, trans->packages)) {
-				pmpkg_t *pkg = db_scan(sync->data, sync->name, INFRQ_DESC|INFRQ_DEPENDS);
-				if(pkg == NULL) {
-					_alpm_log(PM_LOG_ERROR, "could not find package \"%s\" in repository %s",
-					          sync->name, ((pmdb_t *)sync->data)->treename);
-					pm_errno = PM_ERR_PKG_NOT_FOUND;
-					goto error;
-				}
-				pkg->reason = PM_PKG_REASON_DEPEND;
-				trans->packages = pm_list_add(trans->packages, pkg);
-			}
+			spkg->reason = PM_PKG_REASON_EXPLICIT;
 		}
 		FREELISTPTR(list);
+		FREELISTPTR(trail);
 
 		TRANS_CB(trans, PM_TRANS_EVT_RESOLVEDEPS_DONE, NULL, NULL);
 	}
 
 	/* ORE
 	check for inter-conflicts and whatnot */
+	for(i = trans->packages; i; i = i->next) {
+		pmsyncpkg_t *sync = i->data;
+		if(sync) {
+			list = pm_list_add(list, sync->spkg);
+		}
+	}
+	deps = checkdeps(db, PM_TRANS_TYPE_UPGRADE, list);
+	if(deps) {
+		int errorout = 0;
+		for(i = deps; i; i = i->next) {
+			pmdepmissing_t *miss = i->data;
+			if(miss->type == PM_DEP_TYPE_DEPEND || miss->type == PM_DEP_TYPE_REQUIRED) {
+				/*if(!errorout) {
+					fprintf(stderr, "error: unresolvable dependencies:\n");
+					errorout = 1;
+				}
+				fprintf(stderr, "  %s: requires %s", miss->target, miss->depend.name);
+				switch(miss->depend.mod) {
+					case PM_DEP_MOD_EQ:  fprintf(stderr, "=%s",  miss->depend.version); break;
+					case PM_DEP_MOD_GE:  fprintf(stderr, ">=%s", miss->depend.version); break;
+					case PM_DEP_MOD_LE:  fprintf(stderr, "<=%s", miss->depend.version); break;
+				}
+				if(miss->type == PM_DEP_TYPE_DEPEND) {
+					fprintf(stderr, " but it is not in the sync db\n");
+				} else {
+					fprintf(stderr, "\n");
+				}*/
+			}
+		}
+		/* ORE
+		then look for conflicts */
+	}
 
 	/* ORE
 	any packages in rmtargs need to be removed from final.
@@ -326,21 +387,32 @@ int sync_prepare(pmdb_t *db, pmtrans_t *trans, PMList **data)
 error:
 	FREELISTPTR(list);
 	FREELISTPTR(trail);
+	FREELIST(deps);
 	return(-1);
 }
 
 int sync_commit(pmdb_t *db, pmtrans_t *trans)
 {
-	PMList *i, *files = NULL;
+	PMList *i, *j, *files = NULL;
 	PMList *final = NULL;
+	PMList *rmtargs = NULL;
 	PMList *data;
 	pmtrans_t *tr;
 
 	/* remove any conflicting packages (WITHOUT dep checks) */
+	/* ORE - alpm does not handle removal of conflicting pkgs for now */
 
 	/* remove to-be-replaced packages */
+	for(i = final; i; i = i->next) {
+		pmsyncpkg_t *sync = i->data;
+		for(j = sync->replaces; j; j = j->next) {
+			pmpkg_t *pkg = j->data;
+			rmtargs = pm_list_add(rmtargs, strdup(pkg->name));
+		}
+	}
 
 	/* install targets */
+	/* ORE - need for a flag specifying that deps have already been checked */
 	tr = trans_new(PM_TRANS_TYPE_UPGRADE, 0);
 	for(i = files; i; i = i->next) {
 		trans_addtarget(tr, i->data);
diff --git a/lib/libalpm/sync.h b/lib/libalpm/sync.h
index 94a70189..7c839736 100644
--- a/lib/libalpm/sync.h
+++ b/lib/libalpm/sync.h
@@ -38,6 +38,8 @@ void sync_free(pmsyncpkg_t *sync);
 
 PMList *sync_load_archive(char *archive);
 
+int sync_sysupgrade(pmlist_t **data);
+
 int sync_addtarget(pmdb_t *db, PMList *dbs_sync, pmtrans_t *trans, char *name);
 int sync_prepare(pmdb_t *db, pmtrans_t *trans, PMList **data);
 int sync_commit(pmdb_t *db, pmtrans_t *trans);
-- 
cgit v1.2.3-70-g09d2