In addition to the names of the conflicting packages, the origin and versions will be displayed to the user. This introduces a slight API change in the PM_TRANS_CONV_CONFLICT_PKG conversation callback. The format of the first two strings has changed from package names to strings of the format "db/name-version". Fixes FS#12536 --- I rewrote the patch to pre-format the package information rather than changing the API completely, as per Dan's suggestion. This still introduces a bit of an API change as the two string can no longer be used as package identifiers, e.g. in alpm_db_get_pkg(). $ sudo ./src/pacman/pacman -S qemu-kvm resolving dependencies... looking for inter-conflicts... :: extra/qemu-kvm-0.14.0-1 and local/qemu-0.14.0-1 are in conflict (qemu). Remove local/qemu-0.14.0-1? [y/N] n error: unresolvable package conflicts detected error: failed to prepare transaction (conflicting dependencies) :: qemu-kvm and qemu are in conflict lib/libalpm/sync.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 48 insertions(+), 3 deletions(-) diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c index 5428e40..90eeb5d 100644 --- a/lib/libalpm/sync.c +++ b/lib/libalpm/sync.c @@ -299,6 +299,47 @@ static int compute_download_size(pmpkg_t *newpkg) return 0; } +/** Format package details to "db/name-version". + * + * If the package's origin is not found, it will be omitted + * (i.e. "name-version"). + * + * The returned string must be freed by the caller. + * + * Sets pm_errno on error. + * + * @param pkg the package which details are to be formatted. + * @return Formatting package string, or NULL on error. + */ +static char *format_full_pkgname(pmpkg_t *pkg) { + char *full_pkgname; + size_t size = 1; /* Reserve for NULL */ + pmdb_t *origin; + + ASSERT(pkg != NULL, RET_ERR(PM_ERR_WRONG_ARGS, NULL)); + + /* Calulate length and allocate memory */ + origin = alpm_pkg_get_db(pkg); + if(origin != NULL) { + size += strlen(alpm_db_get_name(origin)) + 1; /* Additional for '/' */ + } + size += strlen(alpm_pkg_get_name(pkg)) + 1; /* Additional for hyphen */ + size += strlen(alpm_pkg_get_version(pkg)); + MALLOC(full_pkgname, size, RET_ERR(PM_ERR_MEMORY, NULL)); + + if(origin != NULL) { + snprintf(full_pkgname, size, "%s/%s-%s", + alpm_db_get_name(origin), + alpm_pkg_get_name(pkg), + alpm_pkg_get_version(pkg)); + } else { + snprintf(full_pkgname, size, "%s-%s", + alpm_pkg_get_name(pkg), + alpm_pkg_get_version(pkg)); + } + return full_pkgname; +} + int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync, alpm_list_t **data) { alpm_list_t *deps = NULL; @@ -485,12 +526,14 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync pmpkg_t *sync = _alpm_pkg_find(trans->add, conflict->package1); pmpkg_t *local = _alpm_db_get_pkgfromcache(db_local, conflict->package2); + char *sync_pkgname = format_full_pkgname(sync); + char *local_pkgname = format_full_pkgname(local); int doremove = 0; - QUESTION(trans, PM_TRANS_CONV_CONFLICT_PKG, conflict->package1, - conflict->package2, conflict->reason, &doremove); + QUESTION(trans, PM_TRANS_CONV_CONFLICT_PKG, sync_pkgname, local_pkgname, + conflict->reason, &doremove); if(doremove) { /* append to the removes list */ - _alpm_log(PM_LOG_DEBUG, "electing '%s' for removal\n", conflict->package2); + _alpm_log(PM_LOG_DEBUG, "electing '%s' for removal\n", local_pkgname); sync->removes = alpm_list_add(sync->removes, local); } else { /* abort */ _alpm_log(PM_LOG_ERROR, _("unresolvable package conflicts detected\n")); @@ -506,6 +549,8 @@ int _alpm_sync_prepare(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t *dbs_sync alpm_list_free(deps); goto cleanup; } + FREE(sync_pkgname); + FREE(local_pkgname); } EVENT(trans, PM_TRANS_EVT_INTERCONFLICTS_DONE, NULL, NULL); alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_conflict_free); -- 1.7.4.4