diff --git a/NEWS b/NEWS index fb984865..43cf081b 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,16 @@ xbps-0.16 (???): + * libxbps: extended rpool with a new function: + xbps_repository_pool_find_virtualpkg_conf. This function will match + a virtual package as was specified in configuration file. That means + that the find_xxx functions now do exactly what the API documents. + While resolving packages, the order to look for them is the following: + + find_virtualpkg_conf -> find_pkg -> find_virtualpkg + + If no virtual pkg from conf matched, look for a real pkg, otherwise + use the first virtual package from rpool that matches our pattern. + * libxbps: introduce the concept of "soft replace". When a package contains that boolean object set in pkg's metadata props.plist, some steps will be skipped at remove time for the package being diff --git a/include/xbps_api.h b/include/xbps_api.h index e97d44f3..9eb05444 100644 --- a/include/xbps_api.h +++ b/include/xbps_api.h @@ -56,7 +56,7 @@ */ #define XBPS_PKGINDEX_VERSION "1.4" -#define XBPS_API_VERSION "20120525-3" +#define XBPS_API_VERSION "20120530" #define XBPS_VERSION "0.16" /** @@ -1537,13 +1537,13 @@ int xbps_repository_pool_foreach( /** * Finds a package dictionary in the repository pool by specifying a * package pattern or a package name. This function does not take into - * account virtual packages set in configuration file. + * account virtual packages, just matches real packages. * * @param[in] pkg Package pattern or name. * @param[in] bypattern Set it to true if \a pkg is a pkgpattern (foo>=0), * false if it is a pkgname. * @param[in] best True to find the best version available in repo, false to - * fetch the first package found matching its pkgname. + * fetch the first package found matching \a pkg. * * @return The package dictionary if found, NULL otherwise. * @note When returned dictionary is no longer needed, you must release it @@ -1564,6 +1564,21 @@ prop_dictionary_t */ prop_dictionary_t xbps_repository_pool_find_pkg_exact(const char *pkgver); +/** + * Finds a package dictionary in repository pool by specifying a + * virtual package pattern or a package name. + * + * @param[in] pkg Virtual package pattern or name to match. + * @param[in] bypattern Set it to true if \a pkg is a pkgpattern (foo>=0), + * false if it is a pkgname. + * + * @return The package dictionary if found, NULL otherwise. + * @note When returned dictionary is no longer needed, you must release it + * with prop_object_release(3). + */ +prop_dictionary_t + xbps_repository_pool_find_virtualpkg(const char *pkg, bool bypattern); + /** * Finds a package dictionary in repository pool by specifying a * package pattern or a package name. Only virtual packages set in @@ -1578,7 +1593,7 @@ prop_dictionary_t xbps_repository_pool_find_pkg_exact(const char *pkgver); * with prop_object_release(3). */ prop_dictionary_t - xbps_repository_pool_find_virtualpkg(const char *pkg, bool bypattern); + xbps_repository_pool_find_virtualpkg_conf(const char *pkg, bool bypattern); /** * Iterate over the the repository pool and search for a metadata plist diff --git a/lib/repository_finddeps.c b/lib/repository_finddeps.c index 96216115..0b940214 100644 --- a/lib/repository_finddeps.c +++ b/lib/repository_finddeps.c @@ -386,37 +386,33 @@ find_repo_deps(prop_dictionary_t transd, /* transaction dictionary */ * If dependency does not match add pkg into the missing * deps array and pass to next one. */ - curpkgd = xbps_repository_pool_find_virtualpkg(reqpkg, true); - if (curpkgd == NULL) { - curpkgd = xbps_repository_pool_find_pkg(reqpkg, true, - true); - if (curpkgd == NULL) { - /* pkg not found, there was some error */ - if (errno && errno != ENOENT) { - xbps_dbg_printf("failed to find pkg " - "for `%s' in rpool: %s\n", - reqpkg, strerror(errno)); - rv = errno; - break; - } - - rv = add_missing_reqdep(trans_mdeps, reqpkg); - if (rv != 0 && rv != EEXIST) { - xbps_dbg_printf_append("`%s': " - "add_missing_reqdep failed %s\n", - reqpkg); - break; - } else if (rv == EEXIST) { - xbps_dbg_printf_append("`%s' missing " - "dep already added.\n", reqpkg); - rv = 0; - continue; - } else { - xbps_dbg_printf_append("`%s' added " - "into the missing deps array.\n", - reqpkg); - continue; - } + if (((curpkgd = xbps_repository_pool_find_virtualpkg_conf(reqpkg, true)) == NULL) && + ((curpkgd = xbps_repository_pool_find_pkg(reqpkg, true, true)) == NULL) && + ((curpkgd = xbps_repository_pool_find_virtualpkg(reqpkg, true)) == NULL)) { + /* pkg not found, there was some error */ + if (errno && errno != ENOENT) { + xbps_dbg_printf("failed to find pkg " + "for `%s' in rpool: %s\n", + reqpkg, strerror(errno)); + rv = errno; + break; + } + rv = add_missing_reqdep(trans_mdeps, reqpkg); + if (rv != 0 && rv != EEXIST) { + xbps_dbg_printf_append("`%s': " + "add_missing_reqdep failed %s\n", + reqpkg); + break; + } else if (rv == EEXIST) { + xbps_dbg_printf_append("`%s' missing " + "dep already added.\n", reqpkg); + rv = 0; + continue; + } else { + xbps_dbg_printf_append("`%s' added " + "into the missing deps array.\n", + reqpkg); + continue; } } prop_dictionary_set_cstring_nocopy(curpkgd, "transaction", reason); diff --git a/lib/repository_pool_find.c b/lib/repository_pool_find.c index 57c72cdf..fb72d099 100644 --- a/lib/repository_pool_find.c +++ b/lib/repository_pool_find.c @@ -51,6 +51,33 @@ repo_find_virtualpkg_cb(struct repository_pool_index *rpi, void *arg, bool *done assert(rpi != NULL); + if (rpf->bypattern) { + rpf->pkgd = + xbps_find_virtualpkg_in_array_by_pattern(rpi->rpi_repo, + rpf->pattern); + } else { + rpf->pkgd = + xbps_find_virtualpkg_in_array_by_name(rpi->rpi_repo, + rpf->pattern); + } + if (rpf->pkgd) { + prop_dictionary_set_cstring(rpf->pkgd, "repository", + rpi->rpi_uri); + *done = true; + return 0; + } + /* not found */ + return 0; +} + +static int +repo_find_virtualpkg_conf_cb(struct repository_pool_index *rpi, + void *arg, bool *done) +{ + struct repo_pool_fpkg *rpf = arg; + + assert(rpi != NULL); + if (rpf->bypattern) { rpf->pkgd = xbps_find_virtualpkg_conf_in_array_by_pattern(rpi->rpi_repo, @@ -61,10 +88,6 @@ repo_find_virtualpkg_cb(struct repository_pool_index *rpi, void *arg, bool *done rpf->pattern); } if (rpf->pkgd) { -#ifdef DEBUG - xbps_dbg_printf("%s: found pkg in repository\n", __func__); - xbps_dbg_printf_append("%s", prop_dictionary_externalize(rpf->pkgd)); -#endif prop_dictionary_set_cstring(rpf->pkgd, "repository", rpi->rpi_uri); *done = true; @@ -89,20 +112,10 @@ repo_find_pkg_cb(struct repository_pool_index *rpi, void *arg, bool *done) /* match by pkgpattern in pkgver*/ rpf->pkgd = xbps_find_pkg_in_array_by_pattern(rpi->rpi_repo, rpf->pattern); - /* If no pkg exists matching pattern, look for virtual packages */ - if (rpf->pkgd == NULL) { - rpf->pkgd = xbps_find_virtualpkg_in_array_by_pattern( - rpi->rpi_repo, rpf->pattern); - } } else { /* match by pkgname */ rpf->pkgd = xbps_find_pkg_in_array_by_name(rpi->rpi_repo, rpf->pattern); - /* If no pkg exists matching pattern, look for virtual packages */ - if (rpf->pkgd == NULL) { - rpf->pkgd = xbps_find_virtualpkg_in_array_by_name( - rpi->rpi_repo, rpf->pattern); - } } if (rpf->pkgd) { /* @@ -170,9 +183,16 @@ repo_find_best_pkg_cb(struct repository_pool_index *rpi, return 0; } +typedef enum { + BEST_PKG = 1, + EXACT_PKG, + VIRTUAL_PKG, + VIRTUAL_CONF_PKG, + REAL_PKG +} pkg_repo_type_t; + static struct repo_pool_fpkg * -repo_find_pkg(const char *pkg, bool bypattern, bool best, bool exact, - bool virtual) +repo_find_pkg(const char *pkg, bool bypattern, pkg_repo_type_t type) { struct repo_pool_fpkg *rpf; int rv = 0; @@ -185,43 +205,45 @@ repo_find_pkg(const char *pkg, bool bypattern, bool best, bool exact, rpf->pattern = pkg; rpf->bypattern = bypattern; - rpf->exact = exact; + rpf->exact = false; rpf->pkgd = NULL; rpf->bestpkgver = NULL; - if (exact) { + switch (type) { + case EXACT_PKG: /* - * Look for exact package match with pkgver in all repos. + * Find exact pkg version. */ + rpf->exact = true; rv = xbps_repository_pool_foreach(repo_find_pkg_cb, rpf); - if (rv != 0) - errno = rv; - } else if (best) { + break; + case BEST_PKG: /* - * Look for the best package version of a package name or - * pattern in all repositories. + * Find best pkg version. */ rv = xbps_repository_pool_foreach(repo_find_best_pkg_cb, rpf); - if (rv != 0) - errno = rv; - } else { - if (virtual) { - /* - * No package found. Look for virtual package - * set by the user or any virtual pkg available. - */ - rv = xbps_repository_pool_foreach(repo_find_virtualpkg_cb, rpf); - if (rv != 0) - errno = rv; - } else { - /* - * Look for a package (non virtual) in repositories. - */ - rv = xbps_repository_pool_foreach(repo_find_pkg_cb, rpf); - if (rv != 0) - errno = rv; - } + break; + case VIRTUAL_PKG: + /* + * Find virtual pkg. + */ + rv = xbps_repository_pool_foreach(repo_find_virtualpkg_cb, rpf); + break; + case VIRTUAL_CONF_PKG: + /* + * Find virtual pkg as specified in configuration file. + */ + rv = xbps_repository_pool_foreach(repo_find_virtualpkg_conf_cb, rpf); + break; + case REAL_PKG: + /* + * Find real pkg. + */ + rv = xbps_repository_pool_foreach(repo_find_pkg_cb, rpf); + break; } + if (rv != 0) + errno = rv; return rpf; } @@ -234,7 +256,23 @@ xbps_repository_pool_find_virtualpkg(const char *pkg, bool bypattern) assert(pkg != NULL); - rpf = repo_find_pkg(pkg, bypattern, false, false, true); + rpf = repo_find_pkg(pkg, bypattern, VIRTUAL_PKG); + if (prop_object_type(rpf->pkgd) == PROP_TYPE_DICTIONARY) + pkgd = prop_dictionary_copy(rpf->pkgd); + free(rpf); + + return pkgd; +} + +prop_dictionary_t +xbps_repository_pool_find_virtualpkg_conf(const char *pkg, bool bypattern) +{ + struct repo_pool_fpkg *rpf; + prop_dictionary_t pkgd = NULL; + + assert(pkg != NULL); + + rpf = repo_find_pkg(pkg, bypattern, VIRTUAL_CONF_PKG); if (prop_object_type(rpf->pkgd) == PROP_TYPE_DICTIONARY) pkgd = prop_dictionary_copy(rpf->pkgd); free(rpf); @@ -250,7 +288,11 @@ xbps_repository_pool_find_pkg(const char *pkg, bool bypattern, bool best) assert(pkg != NULL); - rpf = repo_find_pkg(pkg, bypattern, best, false, false); + if (best) + rpf = repo_find_pkg(pkg, bypattern, BEST_PKG); + else + rpf = repo_find_pkg(pkg, bypattern, REAL_PKG); + if (prop_object_type(rpf->pkgd) == PROP_TYPE_DICTIONARY) pkgd = prop_dictionary_copy(rpf->pkgd); free(rpf); @@ -266,7 +308,7 @@ xbps_repository_pool_find_pkg_exact(const char *pkgver) assert(pkgver != NULL); - rpf = repo_find_pkg(pkgver, false, false, true, false); + rpf = repo_find_pkg(pkgver, false, EXACT_PKG); if (prop_object_type(rpf->pkgd) == PROP_TYPE_DICTIONARY) pkgd = prop_dictionary_copy(rpf->pkgd); free(rpf); diff --git a/lib/transaction_ops.c b/lib/transaction_ops.c index cd85c0b1..2b90340f 100644 --- a/lib/transaction_ops.c +++ b/lib/transaction_ops.c @@ -84,16 +84,13 @@ transaction_find_pkg(const char *pkg, bool bypattern, bool bestpkg, int action) /* * Find out if the pkg has been found in repository pool. */ - pkg_repod = xbps_repository_pool_find_pkg(pkg, bypattern, bestpkg); - if (pkg_repod == NULL) { - pkg_repod = - xbps_repository_pool_find_virtualpkg(pkg, bypattern); - if (pkg_repod == NULL) { - /* not found */ - rv = errno; - errno = 0; - goto out; - } + if (((pkg_repod = xbps_repository_pool_find_virtualpkg_conf(pkg, bypattern)) == NULL) && + ((pkg_repod = xbps_repository_pool_find_pkg(pkg, bypattern, bestpkg)) == NULL) && + ((pkg_repod = xbps_repository_pool_find_virtualpkg(pkg, bypattern)) == NULL)) { + /* not found */ + rv = errno; + errno = 0; + goto out; } prop_dictionary_get_cstring_nocopy(pkg_repod, "pkgver", &pkgver); prop_dictionary_get_cstring_nocopy(pkg_repod, "repository", &repoloc);