libxbps: detect and ignore incorrect deps of a pkg if those are virtual pkgs.

This commit is contained in:
Juan RP 2014-04-20 16:54:50 +02:00
parent 119d059c9b
commit bb491e2667
9 changed files with 76 additions and 59 deletions

4
NEWS
View File

@ -1,5 +1,9 @@
xbps-0.36 (???): 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 * 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 anymore, so that any user can use this mode even without write permission to
the target pkgdb. the target pkgdb.

View File

@ -114,7 +114,7 @@ search_array_cb(struct xbps_handle *xhp _unused,
for (x = 0; x < sd->npatterns; x++) { for (x = 0; x < sd->npatterns; x++) {
bool vpkgfound = false; 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; vpkgfound = true;
if ((xbps_pkgpattern_match(pkgver, sd->patterns[x])) || if ((xbps_pkgpattern_match(pkgver, sd->patterns[x])) ||

View File

@ -48,7 +48,7 @@
* *
* This header documents the full API for the XBPS Library. * This header documents the full API for the XBPS Library.
*/ */
#define XBPS_API_VERSION "20140304" #define XBPS_API_VERSION "20140420"
#ifndef XBPS_VERSION #ifndef XBPS_VERSION
#define XBPS_VERSION "UNSET" #define XBPS_VERSION "UNSET"
@ -909,21 +909,28 @@ int xbps_array_foreach_cb_multi(struct xbps_handle *xhp,
xbps_dictionary_t dict, xbps_dictionary_t dict,
int (*fn)(struct xbps_handle *, xbps_object_t obj, const char *, void *arg, bool *done), int (*fn)(struct xbps_handle *, xbps_object_t obj, const char *, void *arg, bool *done),
void *arg); 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 * Match a virtual package name or pattern by looking at package's
* dictionary "provides" array object. * dictionary "provides" array object.
* *
* @param[in] pkgd Package dictionary. * @param[in] pkgd Package dictionary.
* @param[in] str Virtual package name or package pattern to match. * @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 * @return True if \a str matches a virtual package in \a pkgd, false
* otherwise. * otherwise.
*/ */
bool xbps_match_virtual_pkg_in_dict(xbps_dictionary_t pkgd, bool xbps_match_virtual_pkg_in_dict(xbps_dictionary_t pkgd, const char *str);
const char *str,
bool bypattern);
/** /**
* Match any virtual package from array \a provides in they array \a rundeps * Match any virtual package from array \a provides in they array \a rundeps

View File

@ -52,11 +52,7 @@ get_pkg_in_array(xbps_array_t array, const char *str, bool virtual)
* Check if package pattern matches * Check if package pattern matches
* any virtual package version in dictionary. * any virtual package version in dictionary.
*/ */
if (xbps_pkgpattern_version(str)) found = xbps_match_virtual_pkg_in_dict(obj, str);
found = xbps_match_virtual_pkg_in_dict(obj, str, true);
else
found = xbps_match_virtual_pkg_in_dict(obj, str, false);
if (found) if (found)
break; break;
} else if (xbps_pkgpattern_version(str)) { } 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))) { while ((obj = xbps_object_iterator_next(iter))) {
pkgd = xbps_dictionary_get_keysym(d, obj); 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); xbps_object_iterator_release(iter);
return pkgd; return pkgd;
} }

View File

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2008-2012 Juan Romero Pardines. * Copyright (c) 2008-2014 Juan Romero Pardines.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -40,25 +40,27 @@
* all library functions. * all library functions.
*/ */
bool bool
xbps_match_virtual_pkg_in_dict(xbps_dictionary_t d, xbps_match_virtual_pkg_in_array(xbps_array_t a, const char *str)
const char *str, {
bool bypattern) 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; xbps_array_t provides;
bool found = false;
assert(xbps_object_type(d) == XBPS_TYPE_DICTIONARY); assert(xbps_object_type(d) == XBPS_TYPE_DICTIONARY);
if ((provides = xbps_dictionary_get(d, "provides"))) { if ((provides = xbps_dictionary_get(d, "provides")))
if (bypattern) return xbps_match_virtual_pkg_in_array(provides, str);
found = xbps_match_pkgpattern_in_array(provides, str);
else { return false;
if ((xbps_match_pkgname_in_array(provides, str)) ||
(xbps_match_pkgdep_in_array(provides, str)))
return true;
}
}
return found;
} }
bool bool

View File

@ -152,13 +152,14 @@ static int
find_repo_deps(struct xbps_handle *xhp, find_repo_deps(struct xbps_handle *xhp,
xbps_array_t unsorted, /* array of unsorted deps */ xbps_array_t unsorted, /* array of unsorted deps */
xbps_array_t pkg_rdeps_array, /* current pkg rundeps array */ xbps_array_t pkg_rdeps_array, /* current pkg rundeps array */
xbps_array_t pkg_provides, /* current pkg provides array */
const char *curpkg, /* current pkgver */ const char *curpkg, /* current pkgver */
unsigned short *depth) /* max recursion depth */ unsigned short *depth) /* max recursion depth */
{ {
xbps_dictionary_t curpkgd = NULL; xbps_dictionary_t curpkgd = NULL;
xbps_object_t obj; xbps_object_t obj;
xbps_object_iterator_t iter; xbps_object_iterator_t iter;
xbps_array_t curpkgrdeps; xbps_array_t curpkgrdeps = NULL, curpkgprovides = NULL;
pkg_state_t state; pkg_state_t state;
const char *reqpkg, *pkgver_q, *reason = NULL; const char *reqpkg, *pkgver_q, *reason = NULL;
char *pkgname, *reqpkgname; char *pkgname, *reqpkgname;
@ -191,7 +192,16 @@ find_repo_deps(struct xbps_handle *xhp,
break; 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. * added in the transaction dictionary.
*/ */
if ((curpkgd = xbps_find_pkg_in_array(unsorted, reqpkg)) || 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, xbps_dictionary_get_cstring_nocopy(curpkgd,
"pkgver", &pkgver_q); "pkgver", &pkgver_q);
xbps_dbg_printf_append(xhp, " (%s queued)\n", pkgver_q); xbps_dbg_printf_append(xhp, " (%s queued)\n", pkgver_q);
free(pkgname);
continue; 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. * and its version is fully matched.
*/ */
if (((curpkgd = xbps_pkgdb_get_pkg(xhp, pkgname)) == NULL) && if (((curpkgd = xbps_pkgdb_get_pkg(xhp, pkgname)) == NULL) &&
@ -233,7 +244,7 @@ find_repo_deps(struct xbps_handle *xhp,
/* Check its state */ /* Check its state */
if ((rv = xbps_pkg_state_dictionary(curpkgd, &state)) != 0) if ((rv = xbps_pkg_state_dictionary(curpkgd, &state)) != 0)
break; 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 * Check if required dependency is a virtual
* package and is satisfied by an * 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 * If dependency does not match add pkg into the missing
* deps array and pass to next one. * deps array and pass to next one.
*/ */
@ -365,6 +376,8 @@ find_repo_deps(struct xbps_handle *xhp,
if (curpkgrdeps == NULL) if (curpkgrdeps == NULL)
continue; continue;
curpkgprovides = xbps_dictionary_get(curpkgd, "provides");
if (xhp->flags & XBPS_FLAG_DEBUG) { if (xhp->flags & XBPS_FLAG_DEBUG) {
xbps_dbg_printf(xhp, ""); xbps_dbg_printf(xhp, "");
for (unsigned short x = 0; x < *depth; x++) for (unsigned short x = 0; x < *depth; x++)
@ -378,7 +391,7 @@ find_repo_deps(struct xbps_handle *xhp,
*/ */
(*depth)++; (*depth)++;
rv = find_repo_deps(xhp, unsorted, curpkgrdeps, rv = find_repo_deps(xhp, unsorted, curpkgrdeps,
pkgver_q, depth); curpkgprovides, pkgver_q, depth);
if (rv != 0) { if (rv != 0) {
xbps_dbg_printf(xhp, "Error checking %s for rundeps: %s\n", xbps_dbg_printf(xhp, "Error checking %s for rundeps: %s\n",
reqpkg, strerror(rv)); reqpkg, strerror(rv));
@ -396,7 +409,7 @@ xbps_repository_find_deps(struct xbps_handle *xhp,
xbps_array_t unsorted, xbps_array_t unsorted,
xbps_dictionary_t repo_pkgd) xbps_dictionary_t repo_pkgd)
{ {
xbps_array_t pkg_rdeps; xbps_array_t pkg_rdeps, pkg_provides = NULL;
const char *pkgver; const char *pkgver;
unsigned short depth = 0; 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 * This will find direct and indirect deps, if any of them is not
* there it will be added into the missing_deps array. * 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);
} }

View File

@ -114,10 +114,7 @@ xbps_transaction_package_replace(struct xbps_handle *xhp)
* package that we want to replace we should respect * package that we want to replace we should respect
* the automatic-install object. * the automatic-install object.
*/ */
if (xbps_match_virtual_pkg_in_dict(obj, if (xbps_match_virtual_pkg_in_dict(obj, pattern)) {
pattern, true) ||
xbps_match_virtual_pkg_in_dict(instd,
pkgname, false)) {
xbps_dictionary_set_bool(obj, xbps_dictionary_set_bool(obj,
"automatic-install", instd_auto); "automatic-install", instd_auto);
} }

View File

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2009-2013 Juan Romero Pardines. * Copyright (c) 2009-2014 Juan Romero Pardines.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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)) if (xbps_pkgpattern_match(pkgver, pkg))
return pd; return pd;
/* virtualpkg expression match */ /* 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; return pd;
} }
@ -115,7 +115,7 @@ pkgdep_find_idx(const char *pkg)
if (xbps_pkgpattern_match(pkgver, pkg)) if (xbps_pkgpattern_match(pkgver, pkg))
return idx; return idx;
/* virtualpkg expression match */ /* 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; return idx;
idx++; idx++;
@ -164,9 +164,10 @@ sort_pkg_rundeps(struct xbps_handle *xhp,
xbps_array_t pkg_rundeps, xbps_array_t pkg_rundeps,
xbps_array_t unsorted) xbps_array_t unsorted)
{ {
xbps_array_t provides;
xbps_dictionary_t curpkgd; xbps_dictionary_t curpkgd;
struct pkgdep *lpd, *pdn; struct pkgdep *lpd, *pdn;
const char *str, *tract; const char *str;
int32_t pkgdepidx, curpkgidx; int32_t pkgdepidx, curpkgidx;
uint32_t i, idx = 0; uint32_t i, idx = 0;
int rv = 0; int rv = 0;
@ -201,19 +202,18 @@ again:
} }
if (((curpkgd = xbps_find_pkg_in_array(unsorted, str)) == NULL) && if (((curpkgd = xbps_find_pkg_in_array(unsorted, str)) == NULL) &&
((curpkgd = xbps_find_virtualpkg_in_array(xhp, 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; rv = EINVAL;
break; break;
} }
if ((xbps_match_virtual_pkg_in_dict(curpkgd, str, true)) || if (pd->d) {
(xbps_match_virtual_pkg_in_dict(curpkgd, str, false))) { provides = xbps_dictionary_get(pd->d, "provides");
xbps_dbg_printf_append(xhp, "ignore wrong " if (provides && xbps_match_virtual_pkg_in_array(provides, str)) {
"dependency %s (depends on itself)\n", str); xbps_dbg_printf_append(xhp, "%s is a vpkg provided by %s, ignored.\n", str, pd->name);
continue; continue;
}
} }
xbps_dictionary_get_cstring_nocopy(curpkgd,
"transaction", &tract);
lpd = pkgdep_alloc(curpkgd, str); lpd = pkgdep_alloc(curpkgd, str);
if (pdn == NULL) { if (pdn == NULL) {
/* /*
* If package is not in the list, add to the tail * If package is not in the list, add to the tail

View File

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2012 Juan Romero Pardines. * Copyright (c) 2012-2014 Juan Romero Pardines.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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; xbps_dictionary_t d;
d = pkgdict_init(); d = pkgdict_init();
ATF_REQUIRE_EQ( ATF_REQUIRE_EQ(xbps_match_virtual_pkg_in_dict(d, "cron-daemon"), true);
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);
ATF_REQUIRE_EQ( ATF_REQUIRE_EQ(xbps_match_virtual_pkg_in_dict(d, "cron-daemon>2"), false);
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_TC(match_any_virtualpkg_rundeps_test); ATF_TC(match_any_virtualpkg_rundeps_test);