diff options
author | Xavier Chantry <chantry.xavier@gmail.com> | 2010-10-16 12:28:01 +0200 |
---|---|---|
committer | Xavier Chantry <chantry.xavier@gmail.com> | 2011-01-29 19:33:15 +0100 |
commit | 4097c98c1ee65d6b3a659d042c6c84e0632673bf (patch) | |
tree | 2468e89522839b9e2d8f66cddc11c23076c8be0a /lib | |
parent | ba97a22ce10df2966a9e1117b48a84b93eae0538 (diff) | |
download | pacman-4097c98c1ee65d6b3a659d042c6c84e0632673bf.tar.xz |
Add interactive provider selection
If there are multiple providers in one db, pacman used to just stop at
the first one (both during dependency resolution or for pacman -S
'provision' which uses the same code).
This adds a new conversation callback so that the user can choose which
provider to install. By default (user press enter or --noconfirm), the
first provider is still chosen, so for example the behavior of sync402
and 403 is preserved. But at least the user now has the possibility to
make the right choice in a manual run.
If one of the provider is already installed, it is picked for
reinstall/upgrade, so that provision 002/003 pactest now pass.
$ pacman -S community/smtp-server
:: There are 3 providers available for smtp-server:
1) courier-mta 2) esmtp 3) exim
Which one do you want to install?
Enter a number (default=1):
Signed-off-by: Xavier Chantry <chantry.xavier@gmail.com>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libalpm/alpm.h | 1 | ||||
-rw-r--r-- | lib/libalpm/deps.c | 38 |
2 files changed, 36 insertions, 3 deletions
diff --git a/lib/libalpm/alpm.h b/lib/libalpm/alpm.h index 95482f07..6724bf78 100644 --- a/lib/libalpm/alpm.h +++ b/lib/libalpm/alpm.h @@ -383,6 +383,7 @@ typedef enum _pmtransconv_t { PM_TRANS_CONV_CORRUPTED_PKG = (1 << 3), PM_TRANS_CONV_LOCAL_NEWER = (1 << 4), PM_TRANS_CONV_REMOVE_PKGS = (1 << 5), + PM_TRANS_CONV_SELECT_PROVIDER = (1 << 6), } pmtransconv_t; /* Transaction Progress */ diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index a7203b4b..28a51bcf 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -511,6 +511,10 @@ pmpkg_t *_alpm_resolvedep(pmdepend_t *dep, alpm_list_t *dbs, { alpm_list_t *i, *j; int ignored = 0; + + alpm_list_t *providers = NULL; + int count; + /* 1. literals */ for(i = dbs; i; i = i->next) { pmpkg_t *pkg = _alpm_db_get_pkgfromcache(i->data, dep->name); @@ -550,12 +554,40 @@ pmpkg_t *_alpm_resolvedep(pmdepend_t *dep, alpm_list_t *dbs, continue; } } - _alpm_log(PM_LOG_WARNING, _("provider package was selected (%s provides %s)\n"), - pkg->name, dep->name); - return(pkg); + _alpm_log(PM_LOG_DEBUG, "provider found (%s provides %s)\n", + pkg->name, dep->name); + providers = alpm_list_add(providers, pkg); + /* keep looking for other providers in the all dbs */ } } } + + /* first check if one provider is already installed locally */ + for(i = providers; i; i = i->next) { + pmpkg_t *pkg = i->data; + if (_alpm_pkg_find(_alpm_db_get_pkgcache(handle->db_local), pkg->name)) { + alpm_list_free(providers); + return(pkg); + } + } + count = alpm_list_count(providers); + if (count >= 1) { + /* default to first provider if there is no QUESTION callback */ + int index = 0; + if(count > 1) { + /* if there is more than one provider, we ask the user */ + QUESTION(handle->trans, PM_TRANS_CONV_SELECT_PROVIDER, + providers, dep, NULL, &index); + } + if(index >= 0 && index < count) { + pmpkg_t *pkg = alpm_list_getdata(alpm_list_nth(providers, index)); + alpm_list_free(providers); + return(pkg); + } + alpm_list_free(providers); + providers = NULL; + } + if(ignored) { /* resolvedeps will override these */ pm_errno = PM_ERR_PKG_IGNORED; } else { |