From bb491e2667465ffaf660b4ddf94e43b07aeffe6b Mon Sep 17 00:00:00 2001 From: Juan RP Date: Sun, 20 Apr 2014 16:54:50 +0200 Subject: [PATCH] libxbps: detect and ignore incorrect deps of a pkg if those are virtual pkgs. --- NEWS | 4 +++ bin/xbps-query/search.c | 2 +- include/xbps.h.in | 19 +++++++---- lib/plist_find.c | 8 ++--- lib/plist_match.c | 32 ++++++++++--------- lib/repo_pkgdeps.c | 30 ++++++++++++----- lib/transaction_package_replace.c | 5 +-- lib/transaction_sortdeps.c | 24 +++++++------- tests/xbps/libxbps/plist_match_virtual/main.c | 11 +++---- 9 files changed, 76 insertions(+), 59 deletions(-) diff --git a/NEWS b/NEWS index 19eaf590..e875b1e4 100644 --- a/NEWS +++ b/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. diff --git a/bin/xbps-query/search.c b/bin/xbps-query/search.c index f0ac9a8f..b3f8d24b 100644 --- a/bin/xbps-query/search.c +++ b/bin/xbps-query/search.c @@ -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])) || diff --git a/include/xbps.h.in b/include/xbps.h.in index f8ac0551..7a85e041 100644 --- a/include/xbps.h.in +++ b/include/xbps.h.in @@ -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 diff --git a/lib/plist_find.c b/lib/plist_find.c index f8736ec2..ddc01831 100644 --- a/lib/plist_find.c +++ b/lib/plist_find.c @@ -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; } diff --git a/lib/plist_match.c b/lib/plist_match.c index 1e9dd34f..dbcea9ae 100644 --- a/lib/plist_match.c +++ b/lib/plist_match.c @@ -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 diff --git a/lib/repo_pkgdeps.c b/lib/repo_pkgdeps.c index 1cc8eceb..e983e0d5 100644 --- a/lib/repo_pkgdeps.c +++ b/lib/repo_pkgdeps.c @@ -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); } diff --git a/lib/transaction_package_replace.c b/lib/transaction_package_replace.c index 46717485..cc668574 100644 --- a/lib/transaction_package_replace.c +++ b/lib/transaction_package_replace.c @@ -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); } diff --git a/lib/transaction_sortdeps.c b/lib/transaction_sortdeps.c index 597ac408..c7114ddf 100644 --- a/lib/transaction_sortdeps.c +++ b/lib/transaction_sortdeps.c @@ -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 diff --git a/tests/xbps/libxbps/plist_match_virtual/main.c b/tests/xbps/libxbps/plist_match_virtual/main.c index 849fce80..789209ac 100644 --- a/tests/xbps/libxbps/plist_match_virtual/main.c +++ b/tests/xbps/libxbps/plist_match_virtual/main.c @@ -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);