Signed-off-by: Benedikt Morbach <[email protected]>
---
 doc/pacman.conf.5.txt |    7 ++++-
 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, 122 insertions(+), 22 deletions(-)

diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt
index 985f22d..7e9017a 100644
--- a/doc/pacman.conf.5.txt
+++ b/doc/pacman.conf.5.txt
@@ -160,11 +160,16 @@ Options
        packages are only cleaned if not installed locally and not present in 
any
        known sync database.
 
-*HandleOptdeps =* ShowAll &| Install::
+*HandleOptdeps =* ShowAll &| Install &| Ask::
        If set to `ShowAll`, show all optional dependencies on install.
        The default is to just show uninstalled optional dependencies.
        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.
+       If `ShowAll` and `Ask` are set, the prompt also shows optional 
dependencies
+       which are already installed.
 
 *SigLevel =* ...::
        Set the default signature verification level. For more information, see
diff --git a/etc/pacman.conf.in b/etc/pacman.conf.in
index bf9f200..889afc3 100644
--- a/etc/pacman.conf.in
+++ b/etc/pacman.conf.in
@@ -36,7 +36,7 @@ Architecture = auto
 CheckSpace
 #VerbosePkgLists
 
-#HandleOptdeps = ShowAll Install
+#HandleOptdeps = ShowAll Install Ask
 
 # PGP signature checking
 #SigLevel = Optional
diff --git a/src/pacman/conf.c b/src/pacman/conf.c
index 4d06bfc..1c45a80 100644
--- a/src/pacman/conf.c
+++ b/src/pacman/conf.c
@@ -369,6 +369,8 @@ static int process_handleoptdeps(alpm_list_t *actions) {
                        config->handleoptdeps |= PM_OPTDEPS_SHOWALL;
                } else 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 9128c48..71f049e 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -144,7 +144,8 @@ enum {
 /* optdepends handling */
 enum {
        PM_OPTDEPS_SHOWALL =  1,
-       PM_OPTDEPS_INSTALL = (1 << 1)
+       PM_OPTDEPS_INSTALL = (1 << 1),
+       PM_OPTDEPS_ASK     = (1 << 2)
 };
 
 /* global config variable */
diff --git a/src/pacman/sync.c b/src/pacman/sync.c
index b9c1901..8fbdf78 100644
--- a/src/pacman/sync.c
+++ b/src/pacman/sync.c
@@ -623,7 +623,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->handleoptdeps & PM_OPTDEPS_SHOWALL) == 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 = i->data;
+                                       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 = i->data;
+                                       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);
+
+                               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 = i->data;
+                                       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 c54975e..8e5e480 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -1235,35 +1235,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->handleoptdeps & 
PM_OPTDEPS_SHOWALL);
+               optstrings = optdep_string_list(optdeps, config->handleoptdeps 
& PM_OPTDEPS_SHOWALL);
 
-       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->handleoptdeps & PM_OPTDEPS_SHOWALL);
+               optstrings = optdep_string_list(alpm_pkg_get_optdepends(pkg), 
config->handleoptdeps & PM_OPTDEPS_SHOWALL);
 
-       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)
@@ -1303,6 +1311,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 = i->data;
+               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 ffff4b5..0fbc6b9 100644
--- a/src/pacman/util.h
+++ b/src/pacman/util.h
@@ -73,6 +73,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.7.3


Reply via email to