Ejemplo n.º 1
0
int
repo_show_pkg_deps(struct xbps_handle *xhp, const char *pattern, bool full)
{
	xbps_array_t rdeps;
	xbps_dictionary_t pkgd;
	int indent = 0;

	if (((pkgd = xbps_rpool_get_pkg(xhp, pattern)) == NULL) &&
	    ((pkgd = xbps_rpool_get_virtualpkg(xhp, pattern)) == NULL))
		return errno;

	rdeps = xbps_dictionary_get(pkgd, "run_depends");
	if (rdeps != NULL)
		print_rdeps(xhp, rdeps, full, true, true, &indent);

	return 0;
}
Ejemplo n.º 2
0
static void
print_rdeps(struct xbps_handle *xhp, xbps_array_t rdeps,
	    bool full, bool repo, bool origin, int *indent)
{
	xbps_array_t currdeps;
	xbps_dictionary_t pkgd;
	const char *pkgdep;
	unsigned int i;
	int j;

	if (!origin)
		(*indent)++;

	for (i = 0; i < xbps_array_count(rdeps); i++) {
		xbps_array_get_cstring_nocopy(rdeps, i, &pkgdep);
		if (!origin || !full)
			for (j = 0; j < *indent; j++)
				putchar(' ');

		printf("%s\n", pkgdep);
		if (!full)
			continue;

		if (repo) {
			pkgd = xbps_rpool_get_pkg(xhp, pkgdep);
			if (pkgd == NULL)
				pkgd = xbps_rpool_get_virtualpkg(xhp, pkgdep);
		} else {
			pkgd = xbps_pkgdb_get_pkg(xhp, pkgdep);
			if (pkgd == NULL)
				pkgd = xbps_pkgdb_get_virtualpkg(xhp, pkgdep);
		}
		if (pkgd != NULL) {
			currdeps = xbps_dictionary_get(pkgd, "run_depends");
			if (currdeps != NULL)
				print_rdeps(xhp, currdeps,
				    full, repo, false, indent);
		}
	}
	(*indent)--;
}
Ejemplo n.º 3
0
static int
find_repo_deps(struct xbps_handle *xhp,
	       xbps_array_t unsorted,		/* array of unsorted deps */
	       xbps_array_t pkg_rdeps_array,	/* current pkg rundeps array  */
	       xbps_array_t pkg_provides,	/* current pkg provides array */
	       const char *curpkg,		/* current pkgver */
	       unsigned short *depth)		/* max recursion depth */
{
	xbps_dictionary_t curpkgd = NULL;
	xbps_object_t obj;
	xbps_object_iterator_t iter;
	xbps_array_t curpkgrdeps = NULL, curpkgprovides = NULL;
	pkg_state_t state;
	const char *reqpkg, *pkgver_q, *reason = NULL;
	char *pkgname, *reqpkgname;
	int rv = 0;
	bool foundvpkg;

	if (*depth >= MAX_DEPTH)
		return ELOOP;

	/*
	 * Iterate over the list of required run dependencies for
	 * current package.
	 */
	iter = xbps_array_iterator(pkg_rdeps_array);
	assert(iter);

	while ((obj = xbps_object_iterator_next(iter))) {
		foundvpkg = false;
		reqpkg = xbps_string_cstring_nocopy(obj);
		if (xhp->flags & XBPS_FLAG_DEBUG) {
			xbps_dbg_printf(xhp, "%s", "");
			for (unsigned short x = 0; x < *depth; x++) {
				xbps_dbg_printf_append(xhp, " ");
			}
			xbps_dbg_printf_append(xhp, "%s: requires dependency '%s': ", curpkg ? curpkg : " ", reqpkg);
		}
		if (((pkgname = xbps_pkgpattern_name(reqpkg)) == NULL) &&
		    ((pkgname = xbps_pkg_name(reqpkg)) == NULL)) {
			xbps_dbg_printf(xhp, "%s: can't guess pkgname for dependency: %s\n", curpkg, reqpkg);
			xbps_set_cb_state(xhp, XBPS_STATE_INVALID_DEP, ENXIO, NULL,
			    "%s: can't guess pkgname for dependency '%s'", curpkg, reqpkg);
			rv = ENXIO;
			break;
		}
		/*
		 * Pass 1: check if required dependency is provided as virtual
		 * package via "provides", if true ignore dependency.
		 */
		if (pkg_provides && xbps_match_virtual_pkg_in_array(pkg_provides, reqpkg)) {
			xbps_dbg_printf_append(xhp, "%s is a vpkg provided by %s, ignored.\n", pkgname, curpkg);
			free(pkgname);
			continue;
		}
		/*
		 * Pass 2: check if required dependency has been already
		 * added in the transaction dictionary.
		 */
		if ((curpkgd = xbps_find_pkg_in_array(unsorted, reqpkg, NULL)) ||
		    (curpkgd = xbps_find_virtualpkg_in_array(xhp, unsorted, reqpkg, NULL))) {
			xbps_dictionary_get_cstring_nocopy(curpkgd, "pkgver", &pkgver_q);
			xbps_dbg_printf_append(xhp, " (%s queued)\n", pkgver_q);
			free(pkgname);
			continue;
		}
		/*
		 * Pass 3: check if required dependency is already installed
		 * and its version is fully matched.
		 */
		if ((curpkgd = xbps_pkgdb_get_pkg(xhp, pkgname)) == NULL) {
			if ((curpkgd = xbps_pkgdb_get_virtualpkg(xhp, pkgname))) {
				foundvpkg = true;
			}
		}
		if (curpkgd == NULL) {
			if (errno && errno != ENOENT) {
				/* error */
				rv = errno;
				xbps_dbg_printf(xhp, "failed to find installed pkg for `%s': %s\n", reqpkg, strerror(rv));
				free(pkgname);
				break;
			}
			free(pkgname);
			/* Required dependency not installed */
			xbps_dbg_printf_append(xhp, "not installed.\n");
			reason = "install";
			state = XBPS_PKG_STATE_NOT_INSTALLED;
		} else {
			/*
			 * Required dependency is installed, check if its version can
			 * satisfy the requirements.
			 */
			xbps_dictionary_get_cstring_nocopy(curpkgd, "pkgver", &pkgver_q);

			/* Check its state */
			if ((rv = xbps_pkg_state_dictionary(curpkgd, &state)) != 0) {
				free(pkgname);
				break;
			}

			if (foundvpkg && xbps_match_virtual_pkg_in_dict(curpkgd, reqpkg)) {
				/*
				 * Check if required dependency is a virtual package and is satisfied
				 * by an installed package.
				 */
				xbps_dbg_printf_append(xhp, "[virtual] satisfied by `%s'.\n", pkgver_q);
				free(pkgname);
				continue;
			}
			rv = xbps_pkgpattern_match(pkgver_q, reqpkg);
			if (rv == 0) {
				char *curpkgname;
				/*
				 * The version requirement is not satisfied.
				 */
				curpkgname = xbps_pkg_name(pkgver_q);
				assert(curpkgname);
				if (strcmp(pkgname, curpkgname)) {
					xbps_dbg_printf_append(xhp, "not installed `%s (vpkg)'", pkgver_q);
					if (xbps_dictionary_get(curpkgd, "hold")) {
						xbps_dbg_printf_append(xhp, " on hold state! ignoring package.\n");
					} else {
						xbps_dbg_printf_append(xhp, "\n");
						reason = "install";
					}
				} else {
					xbps_dbg_printf_append(xhp, "installed `%s', must be updated", pkgver_q);
					if (xbps_dictionary_get(curpkgd, "hold")) {
						xbps_dbg_printf_append(xhp, " on hold state! ignoring package.\n");
					} else {
						xbps_dbg_printf_append(xhp, "\n");
						reason = "update";
					}
				}
				free(curpkgname);
				free(pkgname);
			} else if (rv == 1) {
				/*
				 * The version requirement is satisfied.
				 */
				free(pkgname);
				rv = 0;
				if (state == XBPS_PKG_STATE_UNPACKED) {
					/*
					 * Package matches the dependency pattern but was only unpacked,
					 * configure pkg.
					 */
					xbps_dbg_printf_append(xhp, "installed `%s', must be configured.\n", pkgver_q);
					reason = "configure";
				} else if (state == XBPS_PKG_STATE_INSTALLED) {
					/*
					 * Package matches the dependency pattern and is fully installed,
					 * skip to next one.
					 */
					xbps_dbg_printf_append(xhp, "installed `%s'.\n", pkgver_q);
					continue;
				}
			} else {
				/* error matching pkgpattern */
				xbps_dbg_printf(xhp, "failed to match pattern %s with %s\n", reqpkg, pkgver_q);
				free(pkgname);
				break;
			}
		}
		if (xbps_dictionary_get(curpkgd, "hold")) {
			xbps_dbg_printf(xhp, "%s on hold state! ignoring package.\n", curpkg);
			continue;
		}
		/*
		 * Pass 4: find required dependency in repository pool.
		 * If dependency does not match add pkg into the missing
		 * deps array and pass to next one.
		 */
		if (((curpkgd = xbps_rpool_get_pkg(xhp, reqpkg)) == NULL) &&
		    ((curpkgd = xbps_rpool_get_virtualpkg(xhp, reqpkg)) == NULL)) {
			/* pkg not found, there was some error */
			if (errno && errno != ENOENT) {
				xbps_dbg_printf(xhp, "failed to find pkg for `%s' in rpool: %s\n", reqpkg, strerror(errno));
				rv = errno;
				break;
			}
			rv = add_missing_reqdep(xhp, reqpkg);
			if (rv != 0 && rv != EEXIST) {
				xbps_dbg_printf(xhp, "`%s': add_missing_reqdep failed\n", reqpkg);
				break;
			} else if (rv == EEXIST) {
				xbps_dbg_printf(xhp, "`%s' missing dep already added.\n", reqpkg);
				rv = 0;
				continue;
			} else {
				xbps_dbg_printf(xhp, "`%s' added into the missing deps array.\n", reqpkg);
				continue;
			}
		}
		xbps_dictionary_get_cstring_nocopy(curpkgd, "pkgver", &pkgver_q);
		reqpkgname = xbps_pkg_name(pkgver_q);
		assert(reqpkgname);
		/*
		 * Check dependency validity.
		 */
		pkgname = xbps_pkg_name(curpkg);
		assert(pkgname);
		if (strcmp(pkgname, reqpkgname) == 0) {
			xbps_dbg_printf_append(xhp, "[ignoring wrong dependency %s (depends on itself)]\n", reqpkg);
			xbps_remove_string_from_array(pkg_rdeps_array, reqpkg);
			free(pkgname);
			free(reqpkgname);
			continue;
		}
		free(pkgname);
		free(reqpkgname);
		/*
		 * If package doesn't have rundeps, pass to the next one.
		 */
		curpkgrdeps = xbps_dictionary_get(curpkgd, "run_depends");
		if (curpkgrdeps == NULL) {
			/*
			 * Package is on repo, add it into the transaction dictionary.
			 */
			xbps_dictionary_set_cstring_nocopy(curpkgd, "transaction", reason);
			rv = xbps_transaction_store(xhp, unsorted, curpkgd, reason, true);
			if (rv != 0) {
				xbps_dbg_printf(xhp, "xbps_transaction_store failed for `%s': %s\n", reqpkg, strerror(rv));
				break;
			}
			continue;
		}

		if (xhp->flags & XBPS_FLAG_DEBUG) {
			xbps_dbg_printf(xhp, "%s", "");
			for (unsigned short x = 0; x < *depth; x++) {
				xbps_dbg_printf_append(xhp, " ");
			}
			xbps_dbg_printf_append(xhp, "%s: finding dependencies:\n", pkgver_q);
		}
		/*
		 * Recursively find rundeps for current pkg dictionary.
		 */
		(*depth)++;
		curpkgprovides = xbps_dictionary_get(curpkgd, "provides");
		rv = find_repo_deps(xhp, unsorted, curpkgrdeps, curpkgprovides, pkgver_q, depth);
		if (rv != 0) {
			xbps_dbg_printf(xhp, "Error checking %s for rundeps: %s\n", reqpkg, strerror(rv));
			break;
		}
		/*
		 * Package is on repo, add it into the transaction dictionary.
		 */
		xbps_dictionary_set_cstring_nocopy(curpkgd, "transaction", reason);
		rv = xbps_transaction_store(xhp, unsorted, curpkgd, reason, true);
		if (rv != 0) {
			xbps_dbg_printf(xhp, "xbps_transaction_store failed for `%s': %s\n", reqpkg, strerror(rv));
			break;
		}
	}
	xbps_object_iterator_release(iter);
	(*depth)--;

	return rv;
}