Signed-off-by: Benedikt Morbach <[email protected]>
---
 doc/pacman.conf.5.txt |    4 +++
 etc/pacman.conf.in    |    2 +
 lib/libalpm/add.c     |    4 +-
 lib/libalpm/alpm.h    |    2 +-
 src/pacman/conf.c     |   23 ++++++++++++++++++++
 src/pacman/conf.h     |    7 ++++++
 src/pacman/sync.c     |   55 ++++++++++++++++++++++++++++++++++++++++++++----
 src/pacman/upgrade.c  |    2 +-
 8 files changed, 90 insertions(+), 9 deletions(-)

diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt
index ad7fb40..5354358 100644
--- a/doc/pacman.conf.5.txt
+++ b/doc/pacman.conf.5.txt
@@ -156,6 +156,10 @@ Options
        packages are only cleaned if not installed locally and not present in 
any
        known sync database.
 
+*HandleOptdeps =* Install::
+       If set to `Install`, the optional dependencies of all targets are
+       automatically installed.
+
 *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 73445ac..cfd96e1 100644
--- a/etc/pacman.conf.in
+++ b/etc/pacman.conf.in
@@ -37,6 +37,8 @@ Architecture = auto
 #VerbosePkgLists
 #ShowAllOptdeps
 
+#HandleOptdeps = Install
+
 # PGP signature checking
 #SigLevel = Optional
 
diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index b526145..ce5439e 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -50,7 +50,7 @@
 #include "handle.h"
 
 /** Add a package to the transaction. */
-int SYMEXPORT alpm_add_pkg(alpm_handle_t *handle, alpm_pkg_t *pkg)
+int SYMEXPORT alpm_add_pkg(alpm_handle_t *handle, alpm_pkg_t *pkg, 
alpm_pkgreason_t reason)
 {
        const char *pkgname, *pkgver;
        alpm_trans_t *trans;
@@ -98,7 +98,7 @@ int SYMEXPORT alpm_add_pkg(alpm_handle_t *handle, alpm_pkg_t 
*pkg)
        }
 
        /* add the package to the transaction */
-       pkg->reason = ALPM_PKG_REASON_EXPLICIT;
+       pkg->reason = reason;
        _alpm_log(handle, ALPM_LOG_DEBUG, "adding package %s-%s to the 
transaction add list\n",
                                                pkgname, pkgver);
        trans->add = alpm_list_add(trans->add, pkg);
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h
index 868a98b..9e174ac 100644
--- a/lib/libalpm/alpm.h
+++ b/lib/libalpm/alpm.h
@@ -1069,7 +1069,7 @@ int alpm_sync_sysupgrade(alpm_handle_t *handle, int 
enable_downgrade);
  * @param pkg the package to add
  * @return 0 on success, -1 on error (pm_errno is set accordingly)
  */
-int alpm_add_pkg(alpm_handle_t *handle, alpm_pkg_t *pkg);
+int alpm_add_pkg(alpm_handle_t *handle, alpm_pkg_t *pkg, alpm_pkgreason_t 
reason);
 
 /** Add a package removal action to the transaction.
  * @param handle the context handle
diff --git a/src/pacman/conf.c b/src/pacman/conf.c
index f2982e3..e88e916 100644
--- a/src/pacman/conf.c
+++ b/src/pacman/conf.c
@@ -333,6 +333,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, "Install") == 0) {
+                       config->handleoptdeps |= PM_OPTDEPS_INSTALL;
+               } 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.
@@ -439,6 +454,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 23008ea..384f379 100644
--- a/src/pacman/conf.h
+++ b/src/pacman/conf.h
@@ -85,6 +85,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;
@@ -136,6 +138,11 @@ enum {
        PM_CLEAN_KEEPCUR = (1 << 1)
 };
 
+/* optdepends handling */
+enum {
+       PM_OPTDEPS_INSTALL = 1
+};
+
 /* global config variable */
 extern config_t *config;
 
diff --git a/src/pacman/sync.c b/src/pacman/sync.c
index 15eea95..1bb09e9 100644
--- a/src/pacman/sync.c
+++ b/src/pacman/sync.c
@@ -591,9 +591,14 @@ static alpm_db_t *get_db(const char *dbname)
        return NULL;
 }
 
-static int process_pkg(alpm_pkg_t *pkg)
+static int process_pkg(alpm_pkg_t *pkg, int as_dep)
 {
-       int ret = alpm_add_pkg(config->handle, pkg);
+       int ret;
+       if(as_dep) {
+               ret = alpm_add_pkg(config->handle, pkg, ALPM_PKG_REASON_DEPEND);
+       } else {
+               ret = alpm_add_pkg(config->handle, pkg, 
ALPM_PKG_REASON_EXPLICIT);
+       }
 
        if(ret == -1) {
                enum _alpm_errno_t err = alpm_errno(config->handle);
@@ -611,6 +616,34 @@ static int process_pkg(alpm_pkg_t *pkg)
        return 0;
 }
 
+static int process_optdeps(alpm_list_t *dblist, alpm_pkg_t *pkg)
+{
+       if(config->handleoptdeps & PM_OPTDEPS_INSTALL) {
+               alpm_list_t *optdeps = alpm_pkg_get_optdepends(pkg);
+               alpm_list_t *i;
+
+               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);
+                       alpm_pkg_t *pkg = 
alpm_find_dbs_satisfier(config->handle, dblist, depstring);
+                       free(depstring);
+
+                       if(alpm_errno(config->handle) == ALPM_ERR_PKG_IGNORED) {
+                               pm_printf(ALPM_LOG_WARNING, _("skipping 
optdepend: %s\n"), optdep->depend->name);
+                               continue;
+                       }
+
+                       if(pkg) {
+                               if(process_pkg(pkg, 1) == 1) {
+                                       return 1;
+                               }
+                       }
+               }
+       }
+
+       return 0;
+}
+
 static int process_group(alpm_list_t *dbs, const char *group)
 {
        int ret = 0;
@@ -644,7 +677,11 @@ static int process_group(alpm_list_t *dbs, const char 
*group)
                                continue;
                        alpm_pkg_t *pkg = alpm_list_getdata(i);
 
-                       if(process_pkg(pkg) == 1) {
+                       if(process_pkg(pkg, 0) == 1) {
+                               ret = 1;
+                               free(array);
+                               goto cleanup;
+                       } else if(process_optdeps(dbs, pkg) == 1) {
                                ret = 1;
                                free(array);
                                goto cleanup;
@@ -655,7 +692,10 @@ static int process_group(alpm_list_t *dbs, const char 
*group)
                for(i = pkgs; i; i = alpm_list_next(i)) {
                        alpm_pkg_t *pkg = alpm_list_getdata(i);
 
-                       if(process_pkg(pkg) == 1) {
+                       if(process_pkg(pkg, 0) == 1) {
+                               ret = 1;
+                               goto cleanup;
+                       } else if(process_optdeps(dbs, pkg) == 1) {
                                ret = 1;
                                goto cleanup;
                        }
@@ -669,6 +709,7 @@ cleanup:
 static int process_targname(alpm_list_t *dblist, const char *targname)
 {
        alpm_pkg_t *pkg = alpm_find_dbs_satisfier(config->handle, dblist, 
targname);
+       int retval = 0;
 
        /* #FS#23342 - skip ignored packages when user says no */
        if(alpm_errno(config->handle) == ALPM_ERR_PKG_IGNORED) {
@@ -677,7 +718,11 @@ static int process_targname(alpm_list_t *dblist, const 
char *targname)
        }
 
        if(pkg) {
-               return process_pkg(pkg);
+               retval = process_pkg(pkg, 0);
+               if(retval == 0) {
+                       retval = process_optdeps(dblist, pkg);
+               }
+               return retval;
        }
        /* fallback on group */
        return process_group(dblist, targname);
diff --git a/src/pacman/upgrade.c b/src/pacman/upgrade.c
index dcd0d66..6dba50b 100644
--- a/src/pacman/upgrade.c
+++ b/src/pacman/upgrade.c
@@ -82,7 +82,7 @@ int pacman_upgrade(alpm_list_t *targets)
                        trans_release();
                        return 1;
                }
-               if(alpm_add_pkg(config->handle, pkg) == -1) {
+               if(alpm_add_pkg(config->handle, pkg, ALPM_PKG_REASON_EXPLICIT) 
== -1) {
                        pm_fprintf(stderr, ALPM_LOG_ERROR, "'%s': %s\n",
                                        targ, 
alpm_strerror(alpm_errno(config->handle)));
                        alpm_pkg_free(pkg);
-- 
1.7.6.1


Reply via email to