diff options
Diffstat (limited to 'lib/libalpm/deps.c')
-rw-r--r-- | lib/libalpm/deps.c | 104 |
1 files changed, 73 insertions, 31 deletions
diff --git a/lib/libalpm/deps.c b/lib/libalpm/deps.c index c667daa2..694e5be5 100644 --- a/lib/libalpm/deps.c +++ b/lib/libalpm/deps.c @@ -229,13 +229,13 @@ alpm_list_t SYMEXPORT *alpm_deptest(pmdb_t *db, alpm_list_t *targets) /** Checks dependencies and returns missing ones in a list. * Dependencies can include versions with depmod operators. - * @param db pointer to the local package database + * @param pkglist the list of local packages * @param reversedeps handles the backward dependencies * @param remove an alpm_list_t* of packages to be removed * @param upgrade an alpm_list_t* of packages to be upgraded (remove-then-upgrade) * @return an alpm_list_t* of pmpkg_t* of missing_t pointers. */ -alpm_list_t SYMEXPORT *alpm_checkdeps(pmdb_t *db, int reversedeps, +alpm_list_t SYMEXPORT *alpm_checkdeps(alpm_list_t *pkglist, int reversedeps, alpm_list_t *remove, alpm_list_t *upgrade) { alpm_list_t *i, *j; @@ -245,12 +245,8 @@ alpm_list_t SYMEXPORT *alpm_checkdeps(pmdb_t *db, int reversedeps, ALPM_LOG_FUNC; - if(db == NULL) { - return(NULL); - } - targets = alpm_list_join(alpm_list_copy(remove), alpm_list_copy(upgrade)); - for(i = _alpm_db_get_pkgcache(db); i; i = i->next) { + for(i = pkglist; i; i = i->next) { void *pkg = i->data; if(alpm_list_find(targets, pkg, _alpm_pkg_cmp)) { modified = alpm_list_add(modified, pkg); @@ -273,7 +269,7 @@ alpm_list_t SYMEXPORT *alpm_checkdeps(pmdb_t *db, int reversedeps, if(!_alpm_find_dep_satisfier(upgrade, depend) && !_alpm_find_dep_satisfier(dblist, depend)) { /* Unsatisfied dependency in the upgrade list */ - char *missdepstring = alpm_dep_get_string(depend); + char *missdepstring = alpm_dep_compute_string(depend); _alpm_log(PM_LOG_DEBUG, "checkdeps: missing dependency '%s' for package '%s'\n", missdepstring, alpm_pkg_get_name(tp)); free(missdepstring); @@ -297,7 +293,7 @@ alpm_list_t SYMEXPORT *alpm_checkdeps(pmdb_t *db, int reversedeps, if(causingpkg && !_alpm_find_dep_satisfier(upgrade, depend) && !_alpm_find_dep_satisfier(dblist, depend)) { - char *missdepstring = alpm_dep_get_string(depend); + char *missdepstring = alpm_dep_compute_string(depend); _alpm_log(PM_LOG_DEBUG, "checkdeps: transaction would break '%s' dependency of '%s'\n", missdepstring, alpm_pkg_get_name(lp)); free(missdepstring); @@ -508,8 +504,20 @@ void _alpm_recursedeps(pmdb_t *db, alpm_list_t *targs, int include_explicit) } } -/* helper function for resolvedeps: search for dep satisfier in dbs */ -pmpkg_t *_alpm_resolvedep(pmdepend_t *dep, alpm_list_t *dbs, alpm_list_t *excluding, pmpkg_t *tpkg) +/** + * helper function for resolvedeps: search for dep satisfier in dbs + * + * @param dep is the dependency to search for + * @param dbs are the databases to search + * @param excluding are the packages to exclude from the search + * @param prompt if true, will cause an unresolvable dependency to issue an + * interactive prompt asking whether the package should be removed from + * the transaction or the transaction aborted; if false, simply returns + * an error code without prompting + * @return the resolved package + **/ +pmpkg_t *_alpm_resolvedep(pmdepend_t *dep, alpm_list_t *dbs, + alpm_list_t *excluding, int prompt) { alpm_list_t *i, *j; /* 1. literals */ @@ -517,9 +525,11 @@ pmpkg_t *_alpm_resolvedep(pmdepend_t *dep, alpm_list_t *dbs, alpm_list_t *exclud pmpkg_t *pkg = _alpm_db_get_pkgfromcache(i->data, dep->name); if(pkg && alpm_depcmp(pkg, dep) && !_alpm_pkg_find(excluding, pkg->name)) { if(_alpm_pkg_should_ignore(pkg)) { - int install; - QUESTION(handle->trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, pkg, - tpkg, NULL, &install); + int install = 0; + if (prompt) { + QUESTION(handle->trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, pkg, + NULL, NULL, &install); + } if(!install) { continue; } @@ -534,9 +544,11 @@ pmpkg_t *_alpm_resolvedep(pmdepend_t *dep, alpm_list_t *dbs, alpm_list_t *exclud if(alpm_depcmp(pkg, dep) && strcmp(pkg->name, dep->name) && !_alpm_pkg_find(excluding, pkg->name)) { if(_alpm_pkg_should_ignore(pkg)) { - int install; - QUESTION(handle->trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, pkg, - tpkg, NULL, &install); + int install = 0; + if (prompt) { + QUESTION(handle->trans, PM_TRANS_CONV_INSTALL_IGNOREPKG, + pkg, NULL, NULL, &install); + } if(!install) { continue; } @@ -550,17 +562,33 @@ pmpkg_t *_alpm_resolvedep(pmdepend_t *dep, alpm_list_t *dbs, alpm_list_t *exclud return(NULL); } -/* populates list with packages that need to be installed to satisfy all - * dependencies of packages in list +/* Computes resolvable dependencies for a given package and adds that package + * and those resolvable dependencies to a list. * - * @param remove contains packages elected for removal + * @param local is the local database + * @param dbs_sync are the sync databases + * @param pkg is the package to resolve + * @param packages is a pointer to a list of packages which will be + * searched first for any dependency packages needed to complete the + * resolve, and to which will be added any [pkg] and all of its + * dependencies not already on the list + * @param remove is the set of packages which will be removed in this + * transaction + * @param data returns the dependency which could not be satisfied in the + * event of an error + * @return 0 on success, with [pkg] and all of its dependencies not already on + * the [*packages] list added to that list, or -1 on failure due to an + * unresolvable dependency, in which case the [*packages] list will be + * unmodified by this function */ -int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, alpm_list_t *list, - alpm_list_t *remove, alpm_list_t **data) +int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, pmpkg_t *pkg, + alpm_list_t **packages, alpm_list_t *remove, + alpm_list_t **data) { alpm_list_t *i, *j; alpm_list_t *targ; alpm_list_t *deps = NULL; + alpm_list_t *packages_copy; ALPM_LOG_FUNC; @@ -568,25 +596,36 @@ int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, alpm_list_t *list, return(-1); } + if(_alpm_pkg_find(*packages, pkg->name) != NULL) { + return(0); + } + + /* Create a copy of the packages list, so that it can be restored + on error */ + packages_copy = alpm_list_copy(*packages); + /* [pkg] has not already been resolved into the packages list, so put it + on that list */ + *packages = alpm_list_add(*packages, pkg); + _alpm_log(PM_LOG_DEBUG, "started resolving dependencies\n"); - for(i = list; i; i = i->next) { + for(i = alpm_list_last(*packages); i; i = i->next) { pmpkg_t *tpkg = i->data; targ = alpm_list_add(NULL, tpkg); - deps = alpm_checkdeps(local, 0, remove, targ); + deps = alpm_checkdeps(_alpm_db_get_pkgcache(local), 0, remove, targ); alpm_list_free(targ); for(j = deps; j; j = j->next) { pmdepmissing_t *miss = j->data; pmdepend_t *missdep = alpm_miss_get_dep(miss); - /* check if one of the packages in list already satisfies this dependency */ - if(_alpm_find_dep_satisfier(list, missdep)) { + /* check if one of the packages in the [*packages] list already satisfies this dependency */ + if(_alpm_find_dep_satisfier(*packages, missdep)) { continue; } /* find a satisfier package in the given repositories */ - pmpkg_t *spkg = _alpm_resolvedep(missdep, dbs_sync, list, tpkg); + pmpkg_t *spkg = _alpm_resolvedep(missdep, dbs_sync, *packages, 0); if(!spkg) { pm_errno = PM_ERR_UNSATISFIED_DEPS; - char *missdepstring = alpm_dep_get_string(missdep); - _alpm_log(PM_LOG_ERROR, _("cannot resolve \"%s\", a dependency of \"%s\"\n"), + char *missdepstring = alpm_dep_compute_string(missdep); + _alpm_log(PM_LOG_WARNING, _("cannot resolve \"%s\", a dependency of \"%s\"\n"), missdepstring, tpkg->name); free(missdepstring); if(data) { @@ -596,18 +635,21 @@ int _alpm_resolvedeps(pmdb_t *local, alpm_list_t *dbs_sync, alpm_list_t *list, *data = alpm_list_add(*data, missd); } } + alpm_list_free(*packages); + *packages = packages_copy; alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_depmiss_free); alpm_list_free(deps); return(-1); } else { _alpm_log(PM_LOG_DEBUG, "pulling dependency %s (needed by %s)\n", alpm_pkg_get_name(spkg), alpm_pkg_get_name(tpkg)); - list = alpm_list_add(list, spkg); + *packages = alpm_list_add(*packages, spkg); } } alpm_list_free_inner(deps, (alpm_list_fn_free)_alpm_depmiss_free); alpm_list_free(deps); } + alpm_list_free(packages_copy); _alpm_log(PM_LOG_DEBUG, "finished resolving dependencies\n"); return(0); } @@ -689,7 +731,7 @@ const char SYMEXPORT *alpm_dep_get_version(const pmdepend_t *dep) * @param dep the depend to turn into a string * @return a string-formatted dependency with operator if necessary */ -char SYMEXPORT *alpm_dep_get_string(const pmdepend_t *dep) +char SYMEXPORT *alpm_dep_compute_string(const pmdepend_t *dep) { char *name, *opr, *ver, *str = NULL; size_t len; |