[pacman-dev] [PATCH 1/2] Add -S --recursive operation

Dan McGee dan at archlinux.org
Thu Aug 11 02:06:26 EDT 2011


This closely matches what we had before for -R --recursive. Basically,
when specifying a target (e.g., pacman), we can now recursively pull all
dependencies, regardless of version specifiers and whether they are
already satisfied in the local database. This could be used to update
pacman on a system with an old glibc, for example, as both pacman and
glibc would get pulled into the transaction.

This is most useful with --needed to prevent needless reinstalls as
described in the man page changes.

The end goal of this change is to wire it into SyncFirst and have it be
the default mode of operation there, but that belongs in a separate
changeset.

Signed-off-by: Dan McGee <dan at archlinux.org>
---
 doc/pacman.8.txt    |    7 +++++++
 lib/libalpm/deps.c  |   29 +++++++++++++++++++++++++++++
 src/pacman/conf.h   |    3 ++-
 src/pacman/pacman.c |    8 +++++++-
 4 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt
index 3240022..a362d2c 100644
--- a/doc/pacman.8.txt
+++ b/doc/pacman.8.txt
@@ -400,6 +400,13 @@ system upgrade and install/upgrade the foo package in the same operation.
 *\--needed*::
 	Don't reinstall the targets that are already up to date.
 
+*\--recursive*::
+	Recursively reinstall all dependencies of the targets. This forces upgrades
+	or reinstalls of all dependencies without requiring explicit version
+	requirements. This is most useful in combination with the '\--needed' flag,
+	which will induce a deep dependency upgrade without any unnecessary
+	reinstalls.
+
 
 Handling Config Files[[HCF]]
 ----------------------------
diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c
index 51ae0fb..992ebe2 100644
--- a/lib/libalpm/deps.c
+++ b/lib/libalpm/deps.c
@@ -701,6 +701,12 @@ int _alpm_resolvedeps(alpm_handle_t *handle, alpm_list_t *localpkgs,
 		return 0;
 	}
 
+	if(handle->trans->flags & ALPM_TRANS_FLAG_RECURSE) {
+		/* removing local packages from the equation causes the entire dep chain to
+		 * get pulled for each target- e.g., pactree -u output */
+		localpkgs = NULL;
+	}
+
 	/* Create a copy of the packages list, so that it can be restored
 	   on error */
 	packages_copy = alpm_list_copy(*packages);
@@ -753,6 +759,29 @@ int _alpm_resolvedeps(alpm_handle_t *handle, alpm_list_t *localpkgs,
 		alpm_list_free(deps);
 	}
 
+	if(handle->trans->flags & ALPM_TRANS_FLAG_NEEDED) {
+		/* remove any deps that were pulled that match installed version */
+		/* odd loop syntax so we can modify the list as we iterate */
+		i = *packages;
+		while(i) {
+			alpm_pkg_t *tpkg = i->data;
+			alpm_pkg_t *local = _alpm_db_get_pkgfromcache(
+					handle->db_local, tpkg->name);
+			if(local && _alpm_pkg_compare_versions(tpkg, local) == 0) {
+				/* with the NEEDED flag, packages up to date are not reinstalled */
+				_alpm_log(handle, ALPM_LOG_DEBUG,
+						"not adding dep %s-%s as it is not needed, same version\n",
+						local->name, local->version);
+				j = i;
+				i = i->next;
+				*packages = alpm_list_remove_item(*packages, j);
+				free(j);
+			} else {
+				i = i->next;
+			}
+		}
+	}
+
 	if(ret != 0) {
 		alpm_list_free(*packages);
 		*packages = packages_copy;
diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index bce42ab..33a8798 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -123,7 +123,8 @@ enum {
 	OP_ASEXPLICIT,
 	OP_ARCH,
 	OP_PRINTFORMAT,
-	OP_GPGDIR
+	OP_GPGDIR,
+	OP_RECURSIVE
 };
 
 /* clean method */
diff --git a/src/pacman/pacman.c b/src/pacman/pacman.c
index 21ccc96..585c8e0 100644
--- a/src/pacman/pacman.c
+++ b/src/pacman/pacman.c
@@ -165,6 +165,7 @@ static void usage(int op, const char * const myname)
 			addlist(_("  -w, --downloadonly   download packages but do not install/upgrade anything\n"));
 			addlist(_("  -y, --refresh        download fresh package databases from the server\n"));
 			addlist(_("      --needed         don't reinstall up to date packages\n"));
+			addlist(_("      --recursive      reinstall all dependencies of target packages\n"));
 		} else if(op == PM_OP_DATABASE) {
 			printf("%s:  %s {-D --database} <%s> <%s>\n", str_usg, myname, str_opt, str_pkg);
 			printf("%s:\n", str_opt);
@@ -506,6 +507,9 @@ static int parsearg_remove(int opt)
 		case 'c': config->flags |= ALPM_TRANS_FLAG_CASCADE; break;
 		case 'n': config->flags |= ALPM_TRANS_FLAG_NOSAVE; break;
 		case 's':
+		case OP_RECURSIVE:
+			/* 's' is the legacy flag here, but since recursive is used in -S without
+			 * a shortopt, we need to do funky tricks */
 			if(config->flags & ALPM_TRANS_FLAG_RECURSE) {
 				config->flags |= ALPM_TRANS_FLAG_RECURSEALL;
 			} else {
@@ -544,6 +548,7 @@ static int parsearg_sync(int opt)
 		return 0;
 	switch(opt) {
 		case OP_NEEDED: config->flags |= ALPM_TRANS_FLAG_NEEDED; break;
+		case OP_RECURSIVE: config->flags |= ALPM_TRANS_FLAG_RECURSE; break;
 		case 'c': (config->op_s_clean)++; break;
 		case 'g': (config->group)++; break;
 		case 'i': (config->op_s_info)++; break;
@@ -603,7 +608,6 @@ static int parseargs(int argc, char *argv[])
 		{"print",      no_argument,       0, 'p'},
 		{"quiet",      no_argument,       0, 'q'},
 		{"root",       required_argument, 0, 'r'},
-		{"recursive",  no_argument,       0, 's'},
 		{"search",     no_argument,       0, 's'},
 		{"unrequired", no_argument,       0, 't'},
 		{"upgrades",   no_argument,       0, 'u'},
@@ -612,6 +616,7 @@ static int parseargs(int argc, char *argv[])
 		{"verbose",    no_argument,       0, 'v'},
 		{"downloadonly", no_argument,     0, 'w'},
 		{"refresh",    no_argument,       0, 'y'},
+
 		{"noconfirm",  no_argument,       0, OP_NOCONFIRM},
 		{"config",     required_argument, 0, OP_CONFIG},
 		{"ignore",     required_argument, 0, OP_IGNORE},
@@ -628,6 +633,7 @@ static int parseargs(int argc, char *argv[])
 		{"arch",       required_argument, 0, OP_ARCH},
 		{"print-format", required_argument, 0, OP_PRINTFORMAT},
 		{"gpgdir",     required_argument, 0, OP_GPGDIR},
+		{"recursive",  no_argument,       0, OP_RECURSIVE},
 		{0, 0, 0, 0}
 	};
 
-- 
1.7.6



More information about the pacman-dev mailing list