diff --git a/doc/pacman.8.txt b/doc/pacman.8.txt index 3240022d..a362d2cf 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 51ae0fb9..992ebe23 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 bce42ab5..33a87983 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 21ccc966..585c8e08 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} };