Ejemplo n.º 1
0
/** Find a package satisfying a specified dependency.
 * The dependency can include versions with depmod operators.
 * @param pkgs an alpm_list_t* of alpm_pkg_t where the satisfier will be searched
 * @param depstring package or provision name, versioned or not
 * @return a alpm_pkg_t* satisfying depstring
 */
alpm_pkg_t SYMEXPORT *alpm_find_satisfier(alpm_list_t *pkgs, const char *depstring)
{
	alpm_depend_t *dep = _alpm_splitdep(depstring);
	if(!dep) {
		return NULL;
	}
	alpm_pkg_t *pkg = find_dep_satisfier(pkgs, dep);
	_alpm_dep_free(dep);
	return pkg;
}
Ejemplo n.º 2
0
/** Checks dependencies and returns missing ones in a list.
 * Dependencies can include versions with depmod operators.
 * @param handle the context handle
 * @param pkglist the list of local packages
 * @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)
 * @param reversedeps handles the backward dependencies
 * @return an alpm_list_t* of alpm_depmissing_t pointers.
 */
alpm_list_t SYMEXPORT *alpm_checkdeps(alpm_handle_t *handle,
		alpm_list_t *pkglist, alpm_list_t *rem, alpm_list_t *upgrade,
		int reversedeps)
{
	alpm_list_t *i, *j;
	alpm_list_t *dblist = NULL, *modified = NULL;
	alpm_list_t *baddeps = NULL;
	int nodepversion;

	CHECK_HANDLE(handle, return NULL);

	for(i = pkglist; i; i = i->next) {
		alpm_pkg_t *pkg = i->data;
		if(alpm_pkg_find(rem, pkg->name) || alpm_pkg_find(upgrade, pkg->name)) {
			modified = alpm_list_add(modified, pkg);
		} else {
			dblist = alpm_list_add(dblist, pkg);
		}
	}

	nodepversion = no_dep_version(handle);

	/* look for unsatisfied dependencies of the upgrade list */
	for(i = upgrade; i; i = i->next) {
		alpm_pkg_t *tp = i->data;
		_alpm_log(handle, ALPM_LOG_DEBUG, "checkdeps: package %s-%s\n",
				tp->name, tp->version);

		for(j = alpm_pkg_get_depends(tp); j; j = j->next) {
			alpm_depend_t *depend = j->data;
			depend = filtered_depend(depend, nodepversion);
			/* 1. we check the upgrade list */
			/* 2. we check database for untouched satisfying packages */
			if(!find_dep_satisfier(upgrade, depend) &&
					!find_dep_satisfier(dblist, depend)) {
				/* Unsatisfied dependency in the upgrade list */
				alpm_depmissing_t *miss;
				char *missdepstring = alpm_dep_compute_string(depend);
				_alpm_log(handle, ALPM_LOG_DEBUG, "checkdeps: missing dependency '%s' for package '%s'\n",
						missdepstring, tp->name);
				free(missdepstring);
				miss = depmiss_new(tp->name, depend, NULL);
				baddeps = alpm_list_add(baddeps, miss);
			}
			release_filtered_depend(depend, nodepversion);
		}
	}

	if(reversedeps) {
		/* reversedeps handles the backwards dependencies, ie,
		 * the packages listed in the requiredby field. */
		for(i = dblist; i; i = i->next) {
			alpm_pkg_t *lp = i->data;
			for(j = alpm_pkg_get_depends(lp); j; j = j->next) {
				alpm_depend_t *depend = j->data;
				depend = filtered_depend(depend, nodepversion);
				alpm_pkg_t *causingpkg = find_dep_satisfier(modified, depend);
				/* we won't break this depend, if it is already broken, we ignore it */
				/* 1. check upgrade list for satisfiers */
				/* 2. check dblist for satisfiers */
				if(causingpkg &&
				   !find_dep_satisfier(upgrade, depend) &&
				   !find_dep_satisfier(dblist, depend)) {
					alpm_depmissing_t *miss;
					char *missdepstring = alpm_dep_compute_string(depend);
					_alpm_log(handle, ALPM_LOG_DEBUG, "checkdeps: transaction would break '%s' dependency of '%s'\n",
							missdepstring, lp->name);
					free(missdepstring);
					miss = depmiss_new(lp->name, depend, causingpkg->name);
					baddeps = alpm_list_add(baddeps, miss);
				}
				release_filtered_depend(depend, nodepversion);
			}
		}
	}

	alpm_list_free(modified);
	alpm_list_free(dblist);

	return baddeps;
}
Ejemplo n.º 3
0
Archivo: deps.c Proyecto: mineo/pacman
/**
 * Computes resolvable dependencies for a given package and adds that package
 * and those resolvable dependencies to a list.
 *
 * @param handle the context handle
 * @param localpkgs is the list of local packages
 * @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(pmhandle_t *handle, alpm_list_t *localpkgs, pmpkg_t *pkg,
                      alpm_list_t *preferred, alpm_list_t **packages,
                      alpm_list_t *remove, alpm_list_t **data)
{
	int ret = 0;
	alpm_list_t *i, *j;
	alpm_list_t *targ;
	alpm_list_t *deps = NULL;
	alpm_list_t *packages_copy;

	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(handle, PM_LOG_DEBUG, "started resolving dependencies\n");
	for(i = alpm_list_last(*packages); i; i = i->next) {
		pmpkg_t *tpkg = i->data;
		targ = alpm_list_add(NULL, tpkg);
		deps = alpm_checkdeps(handle, localpkgs, remove, targ, 0);
		alpm_list_free(targ);

		for(j = deps; j; j = j->next) {
			pmdepmissing_t *miss = j->data;
			pmdepend_t *missdep = miss->depend;
			/* check if one of the packages in the [*packages] list already satisfies
			 * this dependency */
			if(find_dep_satisfier(*packages, missdep)) {
				_alpm_depmiss_free(miss);
				continue;
			}
			/* check if one of the packages in the [preferred] list already satisfies
			 * this dependency */
			pmpkg_t *spkg = find_dep_satisfier(preferred, missdep);
			if(!spkg) {
				/* find a satisfier package in the given repositories */
				spkg = resolvedep(handle, missdep, handle->dbs_sync, *packages, 0);
			}
			if(!spkg) {
				handle->pm_errno = PM_ERR_UNSATISFIED_DEPS;
				char *missdepstring = alpm_dep_compute_string(missdep);
				_alpm_log(handle, PM_LOG_WARNING,
						_("cannot resolve \"%s\", a dependency of \"%s\"\n"),
						missdepstring, tpkg->name);
				free(missdepstring);
				if(data) {
					*data = alpm_list_add(*data, miss);
				}
				ret = -1;
			} else {
				_alpm_log(handle, PM_LOG_DEBUG, "pulling dependency %s (needed by %s)\n",
						alpm_pkg_get_name(spkg), alpm_pkg_get_name(tpkg));
				*packages = alpm_list_add(*packages, spkg);
				_alpm_depmiss_free(miss);
			}
		}
		alpm_list_free(deps);
	}

	if(ret != 0) {
		alpm_list_free(*packages);
		*packages = packages_copy;
	} else {
		alpm_list_free(packages_copy);
	}
	_alpm_log(handle, PM_LOG_DEBUG, "finished resolving dependencies\n");
	return ret;
}