This also shows [installing] after the optdep, if it is part of the same transaction but isn't yet installed Signed-off-by: Benedikt Morbach <benedikt.morbach@googlemail.com> --- doc/pacman.conf.5.txt | 4 +++ etc/pacman.conf.in | 2 + src/pacman/conf.c | 23 +++++++++++++++++ src/pacman/conf.h | 7 +++++ src/pacman/util.c | 35 ++++++++++++++++++++++--- src/pacman/util.h | 1 + test/pacman/tests/{sync061.py => sync062.py} | 8 +++-- 7 files changed, 72 insertions(+), 8 deletions(-) copy test/pacman/tests/{sync061.py => sync062.py} (65%) diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt index 2c1a24b..7232c8b 100644 --- a/doc/pacman.conf.5.txt +++ b/doc/pacman.conf.5.txt @@ -160,6 +160,10 @@ Options packages are only cleaned if not installed locally and not present in any known sync database. +*HandleOptdeps =* ShowAll:: + If set to `ShowAll`, show all optional dependencies on install. + The default is to just show uninstalled optional dependencies. + *SigLevel =* ...:: Set the default signature verification level. For more information, see <<SC,Package and Database Signature Checking>> below. diff --git a/etc/pacman.conf.in b/etc/pacman.conf.in index 932140f..a905757 100644 --- a/etc/pacman.conf.in +++ b/etc/pacman.conf.in @@ -36,6 +36,8 @@ Architecture = auto CheckSpace #VerbosePkgLists +#HandleOptdeps = ShowAll + # PGP signature checking #SigLevel = Optional diff --git a/src/pacman/conf.c b/src/pacman/conf.c index 5328e7c..715399e 100644 --- a/src/pacman/conf.c +++ b/src/pacman/conf.c @@ -361,6 +361,21 @@ static int process_cleanmethods(alpm_list_t *values, return 0; } +static int process_handleoptdeps(alpm_list_t *actions) { + alpm_list_t *i; + for(i = actions; i; i = alpm_list_next(i)) { + const char *action = i->data; + if(strcmp(action, "ShowAll") == 0) { + config->handleoptdeps |= PM_OPTDEPS_SHOWALL; + } else { + pm_printf(ALPM_LOG_ERROR, _("invalid action for 'HandleOptdeps' : '%s'\n"), + action); + return 1; + } + } + return 0; +} + /** Add repeating options such as NoExtract, NoUpgrade, etc to libalpm * settings. Refactored out of the parseconfig code since all of them did * the exact same thing and duplicated code. @@ -464,6 +479,14 @@ static int _parse_options(const char *key, char *value, return 1; } FREELIST(methods); + } else if(strcmp(key, "HandleOptdeps") == 0) { + alpm_list_t *actions = NULL; + setrepeatingoption(value, "HandleOptdeps", &actions); + if(process_handleoptdeps(actions)) { + FREELIST(actions); + return 1; + } + FREELIST(actions); } else if(strcmp(key, "SigLevel") == 0) { alpm_list_t *values = NULL; setrepeatingoption(value, "SigLevel", &values); diff --git a/src/pacman/conf.h b/src/pacman/conf.h index 325fbb6..7ff37ff 100644 --- a/src/pacman/conf.h +++ b/src/pacman/conf.h @@ -83,6 +83,8 @@ typedef struct __config_t { unsigned short totaldownload; /* select -Sc behavior */ unsigned short cleanmethod; + /* wether and how to handle optdeps */ + unsigned short handleoptdeps; alpm_list_t *holdpkg; alpm_list_t *syncfirst; alpm_list_t *ignorepkg; @@ -138,6 +140,11 @@ enum { PM_CLEAN_KEEPCUR = (1 << 1) }; +/* optdepends handling */ +enum { + PM_OPTDEPS_SHOWALL = 1 +}; + /* global config variable */ extern config_t *config; diff --git a/src/pacman/util.c b/src/pacman/util.c index be4647a..1f89663 100644 --- a/src/pacman/util.c +++ b/src/pacman/util.c @@ -1176,20 +1176,45 @@ static int opt_cmp(const void *o1, const void *o2) /** Creates a newly-allocated list of optdepend strings from a list of optdepends. * The list must be freed! * @param optlist an alpm_list_t of optdepends to turn into a strings + * @param include_installed if false, installed packages are excluded from the list. * @return an alpm_list_t of optdepend formatted strings with description */ -alpm_list_t *optdep_string_list(const alpm_list_t *optlist) +alpm_list_t *optdep_string_list(const alpm_list_t *optlist, int include_installed) { alpm_list_t *optstrings = NULL; alpm_optdepend_t *optdep; alpm_db_t *db_local = alpm_option_get_localdb(config->handle); + /* calculate these outside the loop. */ + alpm_list_t *pkgcache = alpm_db_get_pkgcache(db_local); + alpm_list_t *remove = alpm_trans_get_remove(config->handle); + alpm_list_t *add = alpm_trans_get_add(config->handle); + /* turn optdepends list into a text list. */ for( ; optlist; optlist = alpm_list_next(optlist)) { optdep = optlist->data; - if(alpm_db_get_pkg(db_local, optdep->depend->name) == NULL) { - optstrings = alpm_list_add(optstrings, alpm_optdep_compute_string(optdep)); + char *depstr = alpm_dep_compute_string(optdep->depend); + char *tmp, *str = alpm_optdep_compute_string(optdep); + const char *state = NULL; + + if(alpm_find_satisfier(pkgcache, depstr) && alpm_find_satisfier(remove, depstr) == NULL) { + state = include_installed ? _(" [installed]") : NULL; + } else if(alpm_find_satisfier(add, depstr)) { + state = include_installed ? _(" [installing]") : NULL; + } else if(alpm_find_satisfier(remove, depstr)) { + state = _(" [removing]"); + } else { + optstrings = alpm_list_add(optstrings, str); } + + if(state) { + if((tmp = realloc(str, strlen(str) + strlen(state) + 1)) != NULL) { + strcpy(tmp + strlen(tmp), state); + str = tmp; + } /* if realloc fails, we only loose the state information, which is nonfatal. */ + optstrings = alpm_list_add(optstrings, str); + } + free(depstr); } return optstrings; @@ -1203,7 +1228,7 @@ void display_new_optdepends(alpm_pkg_t *oldpkg, alpm_pkg_t *newpkg) new = alpm_pkg_get_optdepends(newpkg); optdeps = alpm_list_diff(new, old, opt_cmp); - optstrings = optdep_string_list(optdeps); + optstrings = optdep_string_list(optdeps, config->handleoptdeps & PM_OPTDEPS_SHOWALL); if(optstrings) { printf(_("New optional dependencies for %s\n"), alpm_pkg_get_name(newpkg)); @@ -1218,7 +1243,7 @@ void display_optdepends(alpm_pkg_t *pkg) { alpm_list_t *optstrings; - optstrings = optdep_string_list(alpm_pkg_get_optdepends(pkg)); + 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)); diff --git a/src/pacman/util.h b/src/pacman/util.h index 6ec962f..ca33752 100644 --- a/src/pacman/util.h +++ b/src/pacman/util.h @@ -69,6 +69,7 @@ void display_targets(void); int str_cmp(const void *s1, const void *s2); void display_new_optdepends(alpm_pkg_t *oldpkg, alpm_pkg_t *newpkg); 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); int select_question(int count); diff --git a/test/pacman/tests/sync061.py b/test/pacman/tests/sync062.py similarity index 65% copy from test/pacman/tests/sync061.py copy to test/pacman/tests/sync062.py index cb5a892..dc90002 100644 --- a/test/pacman/tests/sync061.py +++ b/test/pacman/tests/sync062.py @@ -1,4 +1,6 @@ -self.description = "Install a package from a sync db with installed optdepend and no optdepend output" +self.description = "Install a package from a sync db with installed optdepend and forced optdepend output" + +self.option["HandleOptdeps"] = ["ShowAll"] p1 = pmpkg("dummy") p1.optdepends = ["dep: for foobar"] @@ -10,6 +12,6 @@ self.args = "-S %s" % p1.name self.addrule("PACMAN_RETCODE=0") -self.addrule("!PACMAN_OUTPUT=dep: for foobar") -self.addrule("PKG_EXISTS=dummy") +self.addrule("PACMAN_OUTPUT=dep: for foobar") +self.addrule("PKG_EXIST=dummy") self.addrule("PKG_OPTDEPENDS=dummy|dep: for foobar") -- 1.7.7.3