[pacman-dev] [PATCH] Allow sync_prepare to work in certain cases without sync databases

Dan McGee dan at archlinux.org
Tue Nov 15 10:16:19 EST 2011


When doing a bare -U operation on a local package that doesn't pull in
any dependencies from the sync databases, we can get away with missing
database files. This makes the check conditional on no sync targets
found in the target list. This is not the prettiest code here so we have
a bit of hackish behavior required to straighten both the behavior and
the nonsensical error message out.

Addresses FS#26899.

Signed-off-by: Dan McGee <dan at archlinux.org>
---

For maint. Some example behavior:

$ sudo ./src/pacman/pacman -U /home/makepkg/packages/pacman-git-20111115-1-x86_64.pkg.tar.xz
warning: database file for 'testing' does not exist
loading packages...
resolving dependencies...
looking for inter-conflicts...

Targets (1):

Name        Old Version  New Version  Net Change

pacman-git  20111014-1   20111115-1     0.03 MiB

Total Installed Size:   5.46 MiB
Net Upgrade Size:       0.03 MiB

Proceed with installation? [Y/n] y
(1/1) checking package integrity                   [----------------------] 100%
(1/1) loading package files                        [----------------------] 100%
(1/1) checking for file conflicts                  [----------------------] 100%
(1/1) checking available disk space                [----------------------] 100%
(1/1) upgrading pacman-git                         [----------------------] 100%


$ sudo ./src/pacman/pacman -U /tmp/couchdb-1.1.1-1-x86_64.pkg.tar.xz
warning: database file for 'testing' does not exist
warning: database file for 'extra' does not exist
loading packages...
resolving dependencies...
warning: cannot resolve "erlang", a dependency of "couchdb"
warning: cannot resolve "js", a dependency of "couchdb"
:: The following package cannot be upgraded due to unresolvable dependencies:
      couchdb

Do you want to skip the above package for this upgrade? [y/N] n
error: failed to prepare transaction (could not satisfy dependencies)
:: couchdb: requires erlang
:: couchdb: requires js


$ sudo ./src/pacman/pacman -S couchdb
warning: database file for 'testing' does not exist
warning: database file for 'extra' does not exist
error: failed to prepare transaction (could not find database)


 lib/libalpm/deps.c |    2 +-
 lib/libalpm/sync.c |   27 ++++++++++++++++++---------
 2 files changed, 19 insertions(+), 10 deletions(-)

diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c
index 6040158..89f6d69 100644
--- a/lib/libalpm/deps.c
+++ b/lib/libalpm/deps.c
@@ -631,7 +631,7 @@ static alpm_pkg_t *resolvedep(alpm_handle_t *handle, alpm_depend_t *dep,
 	/* first check if one provider is already installed locally */
 	for(i = providers; i; i = i->next) {
 		alpm_pkg_t *pkg = i->data;
-		if(_alpm_pkghash_find(_alpm_db_get_pkgcache_hash(handle->db_local), pkg->name)) {
+		if(_alpm_db_get_pkgfromcache(handle->db_local, pkg->name)) {
 			alpm_list_free(providers);
 			return pkg;
 		}
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index 54b9794..cf20971 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -357,7 +357,7 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data)
 	alpm_list_t *i, *j;
 	alpm_list_t *deps = NULL;
 	alpm_list_t *unresolvable = NULL;
-	alpm_list_t *remove = NULL;
+	size_t from_sync = 0;
 	int ret = 0;
 	alpm_trans_t *trans = handle->trans;
 
@@ -365,19 +365,27 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data)
 		*data = NULL;
 	}
 
-	/* ensure all sync database are valid since we will be using them */
+	for(i = trans->add; i; i = i->next) {
+		alpm_pkg_t *spkg = i->data;
+		from_sync += (spkg->origin == PKG_FROM_SYNCDB);
+	}
+
+	/* ensure all sync database are valid if we will be using them */
 	for(i = handle->dbs_sync; i; i = i->next) {
 		const alpm_db_t *db = i->data;
 		if(db->status & DB_STATUS_INVALID) {
 			RET_ERR(handle, ALPM_ERR_DB_INVALID, -1);
 		}
-		if(db->status & DB_STATUS_MISSING) {
+		/* missing databases are not allowed if we have sync targets */
+		if(from_sync && db->status & DB_STATUS_MISSING) {
 			RET_ERR(handle, ALPM_ERR_DB_NOT_FOUND, -1);
 		}
 	}
 
 	if(!(trans->flags & ALPM_TRANS_FLAG_NODEPS)) {
-		alpm_list_t *resolved = NULL; /* target list after resolvedeps */
+		alpm_list_t *resolved = NULL;
+		alpm_list_t *remove = NULL;
+		alpm_list_t *localpkgs;
 
 		/* Build up list by repeatedly resolving each transaction package */
 		/* Resolve targets dependencies */
@@ -394,7 +402,7 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data)
 
 		/* Compute the fake local database for resolvedeps (partial fix for the
 		 * phonon/qt issue) */
-		alpm_list_t *localpkgs = alpm_list_diff(_alpm_db_get_pkgcache(handle->db_local),
+		localpkgs = alpm_list_diff(_alpm_db_get_pkgcache(handle->db_local),
 				trans->add, _alpm_pkg_cmp);
 
 		/* Resolve packages in the transaction one at a time, in addition
@@ -409,11 +417,13 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data)
 			   dependencies not already on the list */
 		}
 		alpm_list_free(localpkgs);
+		alpm_list_free(remove);
 
 		/* If there were unresolvable top-level packages, prompt the user to
 		   see if they'd like to ignore them rather than failing the sync */
 		if(unresolvable != NULL) {
 			int remove_unresolvable = 0;
+			enum _alpm_errno_t saved_err = handle->pm_errno;
 			QUESTION(handle, ALPM_QUESTION_REMOVE_PKGS, unresolvable,
 					NULL, NULL, &remove_unresolvable);
 			if(remove_unresolvable) {
@@ -421,14 +431,15 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data)
 				   transaction. The packages will be removed from the actual
 				   transaction when the transaction packages are replaced with a
 				   dependency-reordered list below */
-				handle->pm_errno = 0; /* pm_errno was set by resolvedeps */
+				handle->pm_errno = 0;
 				if(data) {
 					alpm_list_free_inner(*data, (alpm_list_fn_free)_alpm_depmiss_free);
 					alpm_list_free(*data);
 					*data = NULL;
 				}
 			} else {
-				/* pm_errno is set by resolvedeps */
+				/* pm_errno was set by resolvedeps, callback may have overwrote it */
+				handle->pm_errno = saved_err;
 				alpm_list_free(resolved);
 				ret = -1;
 				goto cleanup;
@@ -617,8 +628,6 @@ int _alpm_sync_prepare(alpm_handle_t *handle, alpm_list_t **data)
 	}
 
 cleanup:
-	alpm_list_free(remove);
-
 	return ret;
 }
 
-- 
1.7.7.3



More information about the pacman-dev mailing list