summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/libalpm/alpm.h1
-rw-r--r--lib/libalpm/deps.c38
-rw-r--r--src/pacman/callback.c13
-rw-r--r--src/pacman/util.c55
-rw-r--r--src/pacman/util.h2
-rw-r--r--test/pacman/tests/provision002.py2
-rw-r--r--test/pacman/tests/provision003.py2
7 files changed, 106 insertions, 7 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 {
diff --git a/src/pacman/callback.c b/src/pacman/callback.c
index e3feea16..43c56d00 100644
--- a/src/pacman/callback.c
+++ b/src/pacman/callback.c
@@ -302,6 +302,19 @@ void cb_trans_conv(pmtransconv_t event, void *data1, void *data2,
alpm_list_free(namelist);
}
break;
+ case PM_TRANS_CONV_SELECT_PROVIDER:
+ {
+ alpm_list_t *providers = (alpm_list_t *)data1;
+ int count = alpm_list_count(providers);
+ char *depstring = alpm_dep_compute_string((pmdepend_t *)data2);
+ printf(_(":: There are %d providers available for %s:\n"), count,
+ depstring);
+ free(depstring);
+ select_display(providers);
+ printf("\n");
+ *response = select_question(count);
+ }
+ break;
case PM_TRANS_CONV_LOCAL_NEWER:
if(!config->op_s_downloadonly) {
*response = yesno(_(":: %s-%s: local version is newer. Upgrade anyway?"),
diff --git a/src/pacman/util.c b/src/pacman/util.c
index 0377bf79..133dccc2 100644
--- a/src/pacman/util.c
+++ b/src/pacman/util.c
@@ -677,6 +677,61 @@ void display_optdepends(pmpkg_t *pkg)
}
}
+void select_display(const alpm_list_t *pkglist)
+{
+ const alpm_list_t *i;
+ int nth = 1;
+ alpm_list_t *list = NULL;
+ char *string = NULL;
+
+ for (i = pkglist; i; i = i->next) {
+ string = NULL;
+ pm_asprintf(&string, "%d) %s", nth, alpm_pkg_get_name(i->data));
+ list = alpm_list_add(list, string);
+ nth++;
+ }
+ list_display(" ", list);
+ FREELIST(list);
+}
+
+int select_question(int count)
+{
+ char response[32];
+ FILE *stream;
+ int preset = 1;
+
+ if(config->noconfirm) {
+ stream = stdout;
+ } else {
+ /* Use stderr so questions are always displayed when redirecting output */
+ stream = stderr;
+ }
+
+ fprintf(stream, _("Enter a number (default=%d)"), preset);
+ fprintf(stream, ": ");
+
+ if(config->noconfirm) {
+ fprintf(stream, "\n");
+ return(preset-1);
+ }
+
+ if(fgets(response, sizeof(response), stdin)) {
+ strtrim(response);
+ if(strlen(response) > 0) {
+ char *endptr = NULL;
+ int n = strtol(response, &endptr, 10);
+ if(*endptr == '\0' && n >= 1 && n <= count) {
+ return(n-1);
+ } else {
+ fprintf(stream, _("Invalid number: %s\n"), response);
+ return(-1);
+ }
+ }
+ }
+ return(preset-1);
+}
+
+
/* presents a prompt and gets a Y/N answer */
static int question(short preset, char *fmt, va_list args)
{
diff --git a/src/pacman/util.h b/src/pacman/util.h
index 78fe5b59..399f9bc8 100644
--- a/src/pacman/util.h
+++ b/src/pacman/util.h
@@ -59,6 +59,8 @@ int str_cmp(const void *s1, const void *s2);
void display_new_optdepends(pmpkg_t *oldpkg, pmpkg_t *newpkg);
void display_optdepends(pmpkg_t *pkg);
void print_packages(const alpm_list_t *packages);
+void select_display(const alpm_list_t *pkglist);
+int select_question(int count);
int yesno(char *fmt, ...);
int noyes(char *fmt, ...);
int pm_printf(pmloglevel_t level, const char *format, ...) __attribute__((format(printf,2,3)));
diff --git a/test/pacman/tests/provision002.py b/test/pacman/tests/provision002.py
index 49b88a18..46deb1da 100644
--- a/test/pacman/tests/provision002.py
+++ b/test/pacman/tests/provision002.py
@@ -18,5 +18,3 @@ self.addrule("PACMAN_RETCODE=0")
self.addrule("!PKG_EXIST=pkg1")
self.addrule("PKG_EXIST=pkg2")
self.addrule("PKG_VERSION=pkg2|1.0-2")
-
-self.expectfailure = True
diff --git a/test/pacman/tests/provision003.py b/test/pacman/tests/provision003.py
index 9308be6e..08647501 100644
--- a/test/pacman/tests/provision003.py
+++ b/test/pacman/tests/provision003.py
@@ -19,5 +19,3 @@ self.addrule("PACMAN_RETCODE=0")
self.addrule("!PKG_EXIST=pkg1")
self.addrule("PKG_EXIST=pkg2")
self.addrule("PKG_VERSION=pkg2|1.0-2")
-
-self.expectfailure = True