libxbps: detect and ignore incorrect deps of a pkg if those are virtual pkgs.
This commit is contained in:
		
							
								
								
									
										4
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								NEWS
									
									
									
									
									
								
							@@ -1,5 +1,9 @@
 | 
			
		||||
xbps-0.36 (???):
 | 
			
		||||
 | 
			
		||||
 * libxbps: the dependency solver is now able to detect and ignore invalid
 | 
			
		||||
   dependencies of a package that are depending on itself, if those are
 | 
			
		||||
   declared as virtual packages.
 | 
			
		||||
 | 
			
		||||
 * xbps-install(8): the -n,--dry-run option does not acquire the pkgdb file lock
 | 
			
		||||
   anymore, so that any user can use this mode even without write permission to
 | 
			
		||||
   the target pkgdb.
 | 
			
		||||
 
 | 
			
		||||
@@ -114,7 +114,7 @@ search_array_cb(struct xbps_handle *xhp _unused,
 | 
			
		||||
		for (x = 0; x < sd->npatterns; x++) {
 | 
			
		||||
			bool vpkgfound = false;
 | 
			
		||||
 | 
			
		||||
			if (xbps_match_virtual_pkg_in_dict(obj, sd->patterns[x], false))
 | 
			
		||||
			if (xbps_match_virtual_pkg_in_dict(obj, sd->patterns[x]))
 | 
			
		||||
				vpkgfound = true;
 | 
			
		||||
 | 
			
		||||
			if ((xbps_pkgpattern_match(pkgver, sd->patterns[x])) ||
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,7 @@
 | 
			
		||||
 *
 | 
			
		||||
 * This header documents the full API for the XBPS Library.
 | 
			
		||||
 */
 | 
			
		||||
#define XBPS_API_VERSION	"20140304"
 | 
			
		||||
#define XBPS_API_VERSION	"20140420"
 | 
			
		||||
 | 
			
		||||
#ifndef XBPS_VERSION
 | 
			
		||||
 #define XBPS_VERSION		"UNSET"
 | 
			
		||||
@@ -909,21 +909,28 @@ int xbps_array_foreach_cb_multi(struct xbps_handle *xhp,
 | 
			
		||||
		xbps_dictionary_t dict,
 | 
			
		||||
		int (*fn)(struct xbps_handle *, xbps_object_t obj, const char *, void *arg, bool *done),
 | 
			
		||||
		void *arg);
 | 
			
		||||
/**
 | 
			
		||||
 * Match a virtual package name or pattern by looking at proplib array
 | 
			
		||||
 * of strings.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] array Proplib array of strings.
 | 
			
		||||
 * @param[in] str Virtual package name or package pattern to match.
 | 
			
		||||
 *
 | 
			
		||||
 * @return True if \a str matches a virtual package in \a array, false
 | 
			
		||||
 * otherwise.
 | 
			
		||||
 */
 | 
			
		||||
bool xbps_match_virtual_pkg_in_array(xbps_array_t array, const char *str);
 | 
			
		||||
/**
 | 
			
		||||
 * Match a virtual package name or pattern by looking at package's
 | 
			
		||||
 * dictionary "provides" array object.
 | 
			
		||||
 *
 | 
			
		||||
 * @param[in] pkgd Package dictionary.
 | 
			
		||||
 * @param[in] str Virtual package name or package pattern to match.
 | 
			
		||||
 * @param[in] bypattern If true, \a str should be a package name,
 | 
			
		||||
 * otherwise it should be a package pattern, i.e `foo>=0' or `foo<1'.
 | 
			
		||||
 *
 | 
			
		||||
 * @return True if \a str matches a virtual package in \a pkgd, false
 | 
			
		||||
 * otherwise.
 | 
			
		||||
 */
 | 
			
		||||
bool xbps_match_virtual_pkg_in_dict(xbps_dictionary_t pkgd,
 | 
			
		||||
				   const char *str,
 | 
			
		||||
				   bool bypattern);
 | 
			
		||||
bool xbps_match_virtual_pkg_in_dict(xbps_dictionary_t pkgd, const char *str);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Match any virtual package from array \a provides in they array \a rundeps
 | 
			
		||||
 
 | 
			
		||||
@@ -52,11 +52,7 @@ get_pkg_in_array(xbps_array_t array, const char *str, bool virtual)
 | 
			
		||||
			 * Check if package pattern matches
 | 
			
		||||
			 * any virtual package version in dictionary.
 | 
			
		||||
			 */
 | 
			
		||||
			if (xbps_pkgpattern_version(str))
 | 
			
		||||
				found = xbps_match_virtual_pkg_in_dict(obj, str, true);
 | 
			
		||||
			else
 | 
			
		||||
				found = xbps_match_virtual_pkg_in_dict(obj, str, false);
 | 
			
		||||
 | 
			
		||||
			found = xbps_match_virtual_pkg_in_dict(obj, str);
 | 
			
		||||
			if (found)
 | 
			
		||||
				break;
 | 
			
		||||
		} else if (xbps_pkgpattern_version(str)) {
 | 
			
		||||
@@ -269,7 +265,7 @@ xbps_find_virtualpkg_in_dict(struct xbps_handle *xhp,
 | 
			
		||||
 | 
			
		||||
	while ((obj = xbps_object_iterator_next(iter))) {
 | 
			
		||||
		pkgd = xbps_dictionary_get_keysym(d, obj);
 | 
			
		||||
		if (xbps_match_virtual_pkg_in_dict(pkgd, pkg, bypattern)) {
 | 
			
		||||
		if (xbps_match_virtual_pkg_in_dict(pkgd, pkg)) {
 | 
			
		||||
			xbps_object_iterator_release(iter);
 | 
			
		||||
			return pkgd;
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright (c) 2008-2012 Juan Romero Pardines.
 | 
			
		||||
 * Copyright (c) 2008-2014 Juan Romero Pardines.
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
@@ -40,25 +40,27 @@
 | 
			
		||||
 * all library functions.
 | 
			
		||||
 */
 | 
			
		||||
bool
 | 
			
		||||
xbps_match_virtual_pkg_in_dict(xbps_dictionary_t d,
 | 
			
		||||
			       const char *str,
 | 
			
		||||
			       bool bypattern)
 | 
			
		||||
xbps_match_virtual_pkg_in_array(xbps_array_t a, const char *str)
 | 
			
		||||
{
 | 
			
		||||
	if ((xbps_match_pkgname_in_array(a, str)) ||
 | 
			
		||||
	    (xbps_match_pkgdep_in_array(a, str)) ||
 | 
			
		||||
	    (xbps_match_pkgpattern_in_array(a, str)))
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool
 | 
			
		||||
xbps_match_virtual_pkg_in_dict(xbps_dictionary_t d, const char *str)
 | 
			
		||||
{
 | 
			
		||||
	xbps_array_t provides;
 | 
			
		||||
	bool found = false;
 | 
			
		||||
 | 
			
		||||
	assert(xbps_object_type(d) == XBPS_TYPE_DICTIONARY);
 | 
			
		||||
 | 
			
		||||
	if ((provides = xbps_dictionary_get(d, "provides"))) {
 | 
			
		||||
		if (bypattern)
 | 
			
		||||
			found = xbps_match_pkgpattern_in_array(provides, str);
 | 
			
		||||
		else {
 | 
			
		||||
			if ((xbps_match_pkgname_in_array(provides, str)) ||
 | 
			
		||||
			    (xbps_match_pkgdep_in_array(provides, str)))
 | 
			
		||||
				return true;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return found;
 | 
			
		||||
	if ((provides = xbps_dictionary_get(d, "provides")))
 | 
			
		||||
		return xbps_match_virtual_pkg_in_array(provides, str);
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool
 | 
			
		||||
 
 | 
			
		||||
@@ -152,13 +152,14 @@ 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;
 | 
			
		||||
	xbps_array_t curpkgrdeps = NULL, curpkgprovides = NULL;
 | 
			
		||||
	pkg_state_t state;
 | 
			
		||||
	const char *reqpkg, *pkgver_q, *reason = NULL;
 | 
			
		||||
	char *pkgname, *reqpkgname;
 | 
			
		||||
@@ -191,7 +192,16 @@ find_repo_deps(struct xbps_handle *xhp,
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		/*
 | 
			
		||||
		 * Pass 1: check if required dependency has been already
 | 
			
		||||
		 * 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)) ||
 | 
			
		||||
@@ -199,10 +209,11 @@ find_repo_deps(struct xbps_handle *xhp,
 | 
			
		||||
			xbps_dictionary_get_cstring_nocopy(curpkgd,
 | 
			
		||||
			    "pkgver", &pkgver_q);
 | 
			
		||||
			xbps_dbg_printf_append(xhp, " (%s queued)\n", pkgver_q);
 | 
			
		||||
			free(pkgname);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		/*
 | 
			
		||||
		 * Pass 2: check if required dependency is already installed
 | 
			
		||||
		 * Pass 3: check if required dependency is already installed
 | 
			
		||||
		 * and its version is fully matched.
 | 
			
		||||
		 */
 | 
			
		||||
		if (((curpkgd = xbps_pkgdb_get_pkg(xhp, pkgname)) == NULL) &&
 | 
			
		||||
@@ -233,7 +244,7 @@ find_repo_deps(struct xbps_handle *xhp,
 | 
			
		||||
			/* Check its state */
 | 
			
		||||
			if ((rv = xbps_pkg_state_dictionary(curpkgd, &state)) != 0)
 | 
			
		||||
				break;
 | 
			
		||||
			if (xbps_match_virtual_pkg_in_dict(curpkgd, reqpkg, true)) {
 | 
			
		||||
			if (xbps_match_virtual_pkg_in_dict(curpkgd, reqpkg)) {
 | 
			
		||||
				/*
 | 
			
		||||
				 * Check if required dependency is a virtual
 | 
			
		||||
				 * package and is satisfied by an
 | 
			
		||||
@@ -292,7 +303,7 @@ find_repo_deps(struct xbps_handle *xhp,
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		/*
 | 
			
		||||
		 * Pass 3: find required dependency in repository pool.
 | 
			
		||||
		 * 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.
 | 
			
		||||
		 */
 | 
			
		||||
@@ -365,6 +376,8 @@ find_repo_deps(struct xbps_handle *xhp,
 | 
			
		||||
		if (curpkgrdeps == NULL)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		curpkgprovides = xbps_dictionary_get(curpkgd, "provides");
 | 
			
		||||
 | 
			
		||||
		if (xhp->flags & XBPS_FLAG_DEBUG) {
 | 
			
		||||
			xbps_dbg_printf(xhp, "");
 | 
			
		||||
			for (unsigned short x = 0; x < *depth; x++)
 | 
			
		||||
@@ -378,7 +391,7 @@ find_repo_deps(struct xbps_handle *xhp,
 | 
			
		||||
		 */
 | 
			
		||||
		(*depth)++;
 | 
			
		||||
		rv = find_repo_deps(xhp, unsorted, curpkgrdeps,
 | 
			
		||||
				pkgver_q, depth);
 | 
			
		||||
				curpkgprovides, pkgver_q, depth);
 | 
			
		||||
		if (rv != 0) {
 | 
			
		||||
			xbps_dbg_printf(xhp, "Error checking %s for rundeps: %s\n",
 | 
			
		||||
			    reqpkg, strerror(rv));
 | 
			
		||||
@@ -396,7 +409,7 @@ xbps_repository_find_deps(struct xbps_handle *xhp,
 | 
			
		||||
			  xbps_array_t unsorted,
 | 
			
		||||
			  xbps_dictionary_t repo_pkgd)
 | 
			
		||||
{
 | 
			
		||||
	xbps_array_t pkg_rdeps;
 | 
			
		||||
	xbps_array_t pkg_rdeps, pkg_provides = NULL;
 | 
			
		||||
	const char *pkgver;
 | 
			
		||||
	unsigned short depth = 0;
 | 
			
		||||
 | 
			
		||||
@@ -410,5 +423,6 @@ xbps_repository_find_deps(struct xbps_handle *xhp,
 | 
			
		||||
	 * This will find direct and indirect deps, if any of them is not
 | 
			
		||||
	 * there it will be added into the missing_deps array.
 | 
			
		||||
	 */
 | 
			
		||||
	return find_repo_deps(xhp, unsorted, pkg_rdeps, pkgver, &depth);
 | 
			
		||||
	pkg_provides = xbps_dictionary_get(repo_pkgd, "provides");
 | 
			
		||||
	return find_repo_deps(xhp, unsorted, pkg_rdeps, pkg_provides, pkgver, &depth);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -114,10 +114,7 @@ xbps_transaction_package_replace(struct xbps_handle *xhp)
 | 
			
		||||
			 * package that we want to replace we should respect
 | 
			
		||||
			 * the automatic-install object.
 | 
			
		||||
			 */
 | 
			
		||||
			if (xbps_match_virtual_pkg_in_dict(obj,
 | 
			
		||||
			    pattern, true) ||
 | 
			
		||||
			    xbps_match_virtual_pkg_in_dict(instd,
 | 
			
		||||
			    pkgname, false)) {
 | 
			
		||||
			if (xbps_match_virtual_pkg_in_dict(obj, pattern)) {
 | 
			
		||||
				xbps_dictionary_set_bool(obj,
 | 
			
		||||
				    "automatic-install", instd_auto);
 | 
			
		||||
			}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright (c) 2009-2013 Juan Romero Pardines.
 | 
			
		||||
 * Copyright (c) 2009-2014 Juan Romero Pardines.
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
@@ -79,7 +79,7 @@ pkgdep_find(const char *pkg)
 | 
			
		||||
		if (xbps_pkgpattern_match(pkgver, pkg))
 | 
			
		||||
			return pd;
 | 
			
		||||
		/* virtualpkg expression match */
 | 
			
		||||
		if (xbps_match_virtual_pkg_in_dict(pd->d, pkg, true))
 | 
			
		||||
		if (xbps_match_virtual_pkg_in_dict(pd->d, pkg))
 | 
			
		||||
			return pd;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -115,7 +115,7 @@ pkgdep_find_idx(const char *pkg)
 | 
			
		||||
		if (xbps_pkgpattern_match(pkgver, pkg))
 | 
			
		||||
			return idx;
 | 
			
		||||
		/* virtualpkg expression match */
 | 
			
		||||
		if (xbps_match_virtual_pkg_in_dict(pd->d, pkg, true))
 | 
			
		||||
		if (xbps_match_virtual_pkg_in_dict(pd->d, pkg))
 | 
			
		||||
			return idx;
 | 
			
		||||
 | 
			
		||||
		idx++;
 | 
			
		||||
@@ -164,9 +164,10 @@ sort_pkg_rundeps(struct xbps_handle *xhp,
 | 
			
		||||
		 xbps_array_t pkg_rundeps,
 | 
			
		||||
		 xbps_array_t unsorted)
 | 
			
		||||
{
 | 
			
		||||
	xbps_array_t provides;
 | 
			
		||||
	xbps_dictionary_t curpkgd;
 | 
			
		||||
	struct pkgdep *lpd, *pdn;
 | 
			
		||||
	const char *str, *tract;
 | 
			
		||||
	const char *str;
 | 
			
		||||
	int32_t pkgdepidx, curpkgidx;
 | 
			
		||||
	uint32_t i, idx = 0;
 | 
			
		||||
	int rv = 0;
 | 
			
		||||
@@ -201,19 +202,18 @@ again:
 | 
			
		||||
		}
 | 
			
		||||
		if (((curpkgd = xbps_find_pkg_in_array(unsorted, str)) == NULL) &&
 | 
			
		||||
		    ((curpkgd = xbps_find_virtualpkg_in_array(xhp, unsorted, str)) == NULL)) {
 | 
			
		||||
			xbps_dbg_printf_append(xhp, "cannot find %s in unsorted array\n", str);
 | 
			
		||||
			rv = EINVAL;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		if ((xbps_match_virtual_pkg_in_dict(curpkgd, str, true)) ||
 | 
			
		||||
		    (xbps_match_virtual_pkg_in_dict(curpkgd, str, false))) {
 | 
			
		||||
			xbps_dbg_printf_append(xhp, "ignore wrong "
 | 
			
		||||
			    "dependency %s (depends on itself)\n", str);
 | 
			
		||||
			continue;
 | 
			
		||||
		if (pd->d) {
 | 
			
		||||
			provides = xbps_dictionary_get(pd->d, "provides");
 | 
			
		||||
			if (provides && xbps_match_virtual_pkg_in_array(provides, str)) {
 | 
			
		||||
				xbps_dbg_printf_append(xhp, "%s is a vpkg provided by %s, ignored.\n", str, pd->name);
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		xbps_dictionary_get_cstring_nocopy(curpkgd,
 | 
			
		||||
		    "transaction", &tract);
 | 
			
		||||
		lpd = pkgdep_alloc(curpkgd, str);
 | 
			
		||||
 | 
			
		||||
		if (pdn == NULL) {
 | 
			
		||||
			/*
 | 
			
		||||
			 * If package is not in the list, add to the tail
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright (c) 2012 Juan Romero Pardines.
 | 
			
		||||
 * Copyright (c) 2012-2014 Juan Romero Pardines.
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
@@ -80,12 +80,9 @@ ATF_TC_BODY(match_virtual_pkg_dict_test, tc)
 | 
			
		||||
	xbps_dictionary_t d;
 | 
			
		||||
 | 
			
		||||
	d = pkgdict_init();
 | 
			
		||||
	ATF_REQUIRE_EQ(
 | 
			
		||||
		xbps_match_virtual_pkg_in_dict(d, "cron-daemon", false), true);
 | 
			
		||||
	ATF_REQUIRE_EQ(
 | 
			
		||||
		xbps_match_virtual_pkg_in_dict(d, "cron-daemon>=0", true), true);
 | 
			
		||||
	ATF_REQUIRE_EQ(
 | 
			
		||||
		xbps_match_virtual_pkg_in_dict(d, "cron-daemon>2", true), false);
 | 
			
		||||
	ATF_REQUIRE_EQ(xbps_match_virtual_pkg_in_dict(d, "cron-daemon"), true);
 | 
			
		||||
	ATF_REQUIRE_EQ(xbps_match_virtual_pkg_in_dict(d, "cron-daemon>=0"), true);
 | 
			
		||||
	ATF_REQUIRE_EQ(xbps_match_virtual_pkg_in_dict(d, "cron-daemon>2"), false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ATF_TC(match_any_virtualpkg_rundeps_test);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user