[pacman-dev] [PATCH 14/15] Add option to ask which optdeps to install

Benedikt Morbach benedikt.morbach at googlemail.com
Sun Sep 11 15:29:47 EDT 2011


Signed-off-by: Benedikt Morbach <benedikt.morbach at googlemail.com>
---
 doc/pacman.conf.5.txt |    5 +++-
 etc/pacman.conf.in    |    2 +-
 src/pacman/conf.c     |    2 +
 src/pacman/conf.h     |    3 +-
 src/pacman/sync.c     |   70 ++++++++++++++++++++++++++++++++++++++++++++++++-
 src/pacman/util.c     |   59 ++++++++++++++++++++++++++++------------
 src/pacman/util.h     |    1 +
 7 files changed, 120 insertions(+), 22 deletions(-)

diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt
index 5354358..2bfe757 100644
--- a/doc/pacman.conf.5.txt
+++ b/doc/pacman.conf.5.txt
@@ -156,9 +156,12 @@ Options
 	packages are only cleaned if not installed locally and not present in any
 	known sync database.
 
-*HandleOptdeps =* Install::
+*HandleOptdeps =* Install &| Ask::
 	If set to `Install`, the optional dependencies of all targets are
 	automatically installed.
+	If set to `Ask`, display a prompt for each target, where the user can select
+	which of the optional dependencies of that target will be installed.
+	Also, the optional dependencies of the targets won't be shown during installation.
 
 *SigLevel =* ...::
 	Set the default signature verification level. For more information, see
diff --git a/etc/pacman.conf.in b/etc/pacman.conf.in
index cfd96e1..06f4846 100644
--- a/etc/pacman.conf.in
+++ b/etc/pacman.conf.in
@@ -37,7 +37,7 @@ Architecture = auto
 #VerbosePkgLists
 #ShowAllOptdeps
 
-#HandleOptdeps = Install
+#HandleOptdeps = Install Ask
 
 # PGP signature checking
 #SigLevel = Optional
diff --git a/src/pacman/conf.c b/src/pacman/conf.c
index e88e916..35de34a 100644
--- a/src/pacman/conf.c
+++ b/src/pacman/conf.c
@@ -339,6 +339,8 @@ static int process_handleoptdeps(alpm_list_t *actions) {
 		const char *action = i->data;
 		if(strcmp(action, "Install") == 0) {
 			config->handleoptdeps |= PM_OPTDEPS_INSTALL;
+		} else if(strcmp(action, "Ask") == 0) {
+			config->handleoptdeps |= PM_OPTDEPS_ASK;
 		} else {
 			pm_printf(ALPM_LOG_ERROR, _("invalid action for 'HandleOptdeps' : '%s'\n"),
 					action);
diff --git a/src/pacman/conf.h b/src/pacman/conf.h
index 384f379..6948abd 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -140,7 +140,8 @@ enum {
 
 /* optdepends handling */
 enum {
-	PM_OPTDEPS_INSTALL = 1
+	PM_OPTDEPS_INSTALL = 1,
+	PM_OPTDEPS_ASK = (1 << 1)
 };
 
 /* global config variable */
diff --git a/src/pacman/sync.c b/src/pacman/sync.c
index 1bb09e9..f073b59 100644
--- a/src/pacman/sync.c
+++ b/src/pacman/sync.c
@@ -618,7 +618,75 @@ static int process_pkg(alpm_pkg_t *pkg, int as_dep)
 
 static int process_optdeps(alpm_list_t *dblist, alpm_pkg_t *pkg)
 {
-	if(config->handleoptdeps & PM_OPTDEPS_INSTALL) {
+	if(config->print == 0 && (config->handleoptdeps & PM_OPTDEPS_ASK)) {
+		alpm_list_t *optdeps = alpm_pkg_get_optdepends(pkg);
+		int retval = 0;
+
+		if(optdeps) {
+			alpm_list_t *i, *depstrings, *optstrings;
+			depstrings = optstrings = NULL;
+
+			if(config->showalloptdeps == 0) {
+				alpm_db_t *db_local = alpm_option_get_localdb(config->handle);
+				alpm_list_t *pkgcache = alpm_db_get_pkgcache(db_local);
+
+				for(i = optdeps; i; i = alpm_list_next(i)) {
+					alpm_optdepend_t *optdep = alpm_list_getdata(i);
+					char *depstring = alpm_dep_compute_string(optdep->depend);
+					if(alpm_find_satisfier(pkgcache, depstring) == NULL) {
+						depstrings = alpm_list_add(depstrings, depstring);
+						optstrings = alpm_list_add(optstrings, alpm_optdep_compute_string(optdep));
+					} else {
+						free(depstring);					
+					}
+				}
+			} else {
+				for(i = optdeps; i; i = alpm_list_next(i)) {
+					alpm_optdepend_t *optdep = alpm_list_getdata(i);
+					depstrings = alpm_list_add(depstrings, alpm_dep_compute_string(optdep->depend));
+					optstrings = alpm_list_add(optstrings, alpm_optdep_compute_string(optdep));
+				}
+			}
+
+			int count = alpm_list_count(optstrings);
+
+			if(count) {
+				printf(_(":: %s has %d optional dependencies:\n"), alpm_pkg_get_name(pkg), count);
+				select_optdep_display(optstrings);   /* use config->showalloptdeps ! */
+
+				char *array = malloc(count);
+				if(!array) {
+					retval = 1;
+					goto cleanup;
+				}
+
+				if(multiselect_question(array, count)) {
+					retval = 1;
+					goto cleanup;
+				}
+
+				int n = 0;
+				for(i = depstrings; i; i = alpm_list_next(i)) {
+					if(array[n++] == 0) { continue; }
+				
+					char *depstring = alpm_list_getdata(i);
+					alpm_pkg_t *pkg = alpm_find_dbs_satisfier(config->handle, dblist, depstring);
+
+					if(process_pkg(pkg, 1) == 1) {
+						retval = 1;
+						goto cleanup;
+					}
+				}
+
+			cleanup:
+				free(array);
+			}
+
+			FREELIST(depstrings);
+			FREELIST(optstrings);
+			return retval;
+		}
+	} else if(config->handleoptdeps & PM_OPTDEPS_INSTALL) {
 		alpm_list_t *optdeps = alpm_pkg_get_optdepends(pkg);
 		alpm_list_t *i;
 
diff --git a/src/pacman/util.c b/src/pacman/util.c
index 1f54f65..72a78d9 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -1091,35 +1091,43 @@ alpm_list_t *optdep_string_list(const alpm_list_t *optlist, int include_installe
 
 void display_new_optdepends(alpm_pkg_t *oldpkg, alpm_pkg_t *newpkg)
 {
-	alpm_list_t *old, *new, *optdeps, *optstrings;
+	/* don't show optdepends if we already asked for them. '*/
+	if(!((config->handleoptdeps & PM_OPTDEPS_ASK) &&
+				alpm_find_satisfier(alpm_trans_get_add(config->handle), alpm_pkg_get_name(newpkg)))) {
+		alpm_list_t *old, *new, *optdeps, *optstrings;
 
-	old = alpm_pkg_get_optdepends(oldpkg);
-	new = alpm_pkg_get_optdepends(newpkg);
-	optdeps = alpm_list_diff(new, old, opt_cmp);
+		old = alpm_pkg_get_optdepends(oldpkg);
+		new = alpm_pkg_get_optdepends(newpkg);
+		optdeps = alpm_list_diff(new, old, opt_cmp);
 
-	optstrings = optdep_string_list(optdeps, config->showalloptdeps);
+		optstrings = optdep_string_list(optdeps, config->showalloptdeps);
 
-	if(optstrings) {
-		printf(_("New optional dependencies for %s\n"), alpm_pkg_get_name(newpkg));
-		list_display_linebreak("   ", optstrings);
+		if(optstrings) {
+			printf(_("New optional dependencies for %s\n"), alpm_pkg_get_name(newpkg));
+			list_display_linebreak("   ", optstrings);
+		}
+
+		alpm_list_free(optdeps);
+		FREELIST(optstrings);
 	}
-
-	alpm_list_free(optdeps);
-	FREELIST(optstrings);
 }
 
 void display_optdepends(alpm_pkg_t *pkg)
 {
-	alpm_list_t *optstrings;
+	/* don't show optdepends if we already asked for them. '*/
+	if(!((config->handleoptdeps & PM_OPTDEPS_ASK) &&
+				alpm_find_satisfier(alpm_trans_get_add(config->handle), alpm_pkg_get_name(pkg)))) {
+		alpm_list_t *optstrings;
 
-	optstrings = optdep_string_list(alpm_pkg_get_optdepends(pkg), config->showalloptdeps);
+		optstrings = optdep_string_list(alpm_pkg_get_optdepends(pkg), config->showalloptdeps);
 
-	if(optstrings) {
-		printf(_("Optional dependencies for %s\n"), alpm_pkg_get_name(pkg));
-		list_display_linebreak("   ", optstrings);
+		if(optstrings) {
+			printf(_("Optional dependencies for %s\n"), alpm_pkg_get_name(pkg));
+			list_display_linebreak("   ", optstrings);
+		}
+
+		FREELIST(optstrings);
 	}
-
-	FREELIST(optstrings);
 }
 
 static void display_repo_list(const char *dbname, alpm_list_t *list)
@@ -1159,6 +1167,21 @@ void select_display(const alpm_list_t *pkglist)
 	FREELIST(list);
 }
 
+void select_optdep_display(alpm_list_t *optstrings)
+{
+	const alpm_list_t *i;
+	int nth = 1;
+	char number[8];   /* 2 padding left, 2 number, 1 ')', 2 padding right, 1 '\0' */
+
+	for(i = optstrings; i; i = i->next, nth++) {
+		char *str = alpm_list_getdata(i);
+		if(str) {
+			snprintf(number, 8, "  %2d)  ", nth);
+			string_display(number, str);
+		}
+	}
+}
+
 static int parseindex(char *s, int *val, int min, int max)
 {
 	char *endptr = NULL;
diff --git a/src/pacman/util.h b/src/pacman/util.h
index 0eac77a..2e35e84 100644
--- a/src/pacman/util.h
+++ b/src/pacman/util.h
@@ -67,6 +67,7 @@ void display_optdepends(alpm_pkg_t *pkg);
 alpm_list_t *optdep_string_list(const alpm_list_t *optdeps, int include_installed);
 void print_packages(const alpm_list_t *packages);
 void select_display(const alpm_list_t *pkglist);
+void select_optdep_display(alpm_list_t *optstrings);
 int select_question(int count);
 int multiselect_question(char *array, int count);
 int yesno(char *fmt, ...);
-- 
1.7.6.1



More information about the pacman-dev mailing list