Improved pkg best matching in rpool, and support for exact pkgver matches.
- xbps_repository_pool_find_pkg in best match case, now returns the newest package version available in rpool. - Added xbps_repository_pool_find_pkg_exact that returns a package by exact matching a pkgver. - Removed xbps_handle_alloc(), the user is free to use memory allocated from heap or stack. - Improved API documentation in preparation for 0.12. Bumped XBPS_API_VERSION again.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2011 Juan Romero Pardines.
|
||||
* Copyright (c) 2011-2012 Juan Romero Pardines.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -205,8 +205,6 @@ xbps_end(struct xbps_handle *xh)
|
||||
if (xh->cachedir_priv != NULL)
|
||||
free(xh->cachedir_priv);
|
||||
|
||||
free(xh);
|
||||
xh = NULL;
|
||||
xhp = NULL;
|
||||
}
|
||||
|
||||
@@ -217,12 +215,6 @@ xbps_handle_get(void)
|
||||
return xhp;
|
||||
}
|
||||
|
||||
struct xbps_handle *
|
||||
xbps_handle_alloc(void)
|
||||
{
|
||||
return calloc(1, sizeof(struct xbps_handle));
|
||||
}
|
||||
|
||||
static void
|
||||
common_printf(FILE *f, const char *msg, const char *fmt, va_list ap)
|
||||
{
|
||||
|
@@ -57,9 +57,6 @@ static int
|
||||
set_new_state(prop_dictionary_t dict, pkg_state_t state)
|
||||
{
|
||||
const struct state *stp;
|
||||
#ifdef DEBUG
|
||||
const char *pkgname;
|
||||
#endif
|
||||
|
||||
assert(prop_object_type(dict) == PROP_TYPE_DICTIONARY);
|
||||
|
||||
@@ -73,13 +70,6 @@ set_new_state(prop_dictionary_t dict, pkg_state_t state)
|
||||
if (!prop_dictionary_set_cstring_nocopy(dict, "state", stp->string))
|
||||
return EINVAL;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (prop_dictionary_get_cstring_nocopy(dict, "pkgname", &pkgname)) {
|
||||
xbps_dbg_printf("%s: changed pkg state to '%s'\n",
|
||||
pkgname, stp->string);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2008-2011 Juan Romero Pardines.
|
||||
* Copyright (c) 2008-2012 Juan Romero Pardines.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -574,7 +574,7 @@ out:
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
int HIDDEN
|
||||
xbps_unpack_binary_pkg(prop_dictionary_t pkg_repod)
|
||||
{
|
||||
struct archive *ar = NULL;
|
||||
|
@@ -266,6 +266,24 @@ xbps_find_pkg_in_dict_by_pattern(prop_dictionary_t d,
|
||||
return find_pkg_in_dict(d, key, pattern, true, false);
|
||||
}
|
||||
|
||||
prop_dictionary_t
|
||||
xbps_find_pkg_in_dict_by_pkgver(prop_dictionary_t d,
|
||||
const char *key,
|
||||
const char *pkgver)
|
||||
{
|
||||
prop_array_t array;
|
||||
|
||||
assert(d != NULL);
|
||||
assert(key != NULL);
|
||||
assert(pkgver != NULL);
|
||||
|
||||
array = prop_dictionary_get(d, key);
|
||||
if (array == NULL)
|
||||
return NULL;
|
||||
|
||||
return xbps_find_pkg_in_array_by_pkgver(array, pkgver);
|
||||
}
|
||||
|
||||
prop_dictionary_t HIDDEN
|
||||
xbps_find_virtualpkg_in_dict_by_name(prop_dictionary_t d,
|
||||
const char *key,
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2009-2011 Juan Romero Pardines.
|
||||
* Copyright (c) 2009-2012 Juan Romero Pardines.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -39,7 +39,10 @@
|
||||
struct repo_pool_fpkg {
|
||||
prop_dictionary_t pkgd;
|
||||
const char *pattern;
|
||||
const char *bestpkgver;
|
||||
const char *repo_bestmatch;
|
||||
bool bypattern;
|
||||
bool exact;
|
||||
};
|
||||
|
||||
static int
|
||||
@@ -79,7 +82,16 @@ repo_find_pkg_cb(struct repository_pool_index *rpi, void *arg, bool *done)
|
||||
|
||||
assert(rpi != NULL);
|
||||
|
||||
if (rpf->bypattern) {
|
||||
if (rpf->exact) {
|
||||
if (rpf->repo_bestmatch != NULL) {
|
||||
if (strcmp(rpf->repo_bestmatch, rpi->rpi_uri))
|
||||
return 0;
|
||||
}
|
||||
/* exact match by pkgver */
|
||||
rpf->pkgd = xbps_find_pkg_in_dict_by_pkgver(rpi->rpi_repod,
|
||||
"packages", rpf->pattern);
|
||||
} else if (rpf->bypattern) {
|
||||
/* match by pkgpattern in pkgver*/
|
||||
rpf->pkgd = xbps_find_pkg_in_dict_by_pattern(rpi->rpi_repod,
|
||||
"packages", rpf->pattern);
|
||||
/* If no pkg exists matching pattern, look for virtual packages */
|
||||
@@ -88,6 +100,7 @@ repo_find_pkg_cb(struct repository_pool_index *rpi, void *arg, bool *done)
|
||||
rpi->rpi_repod, "packages", rpf->pattern);
|
||||
}
|
||||
} else {
|
||||
/* match by pkgname */
|
||||
rpf->pkgd = xbps_find_pkg_in_dict_by_name(rpi->rpi_repod,
|
||||
"packages", rpf->pattern);
|
||||
/* If no pkg exists matching pattern, look for virtual packages */
|
||||
@@ -101,10 +114,6 @@ repo_find_pkg_cb(struct repository_pool_index *rpi, void *arg, bool *done)
|
||||
* Package dictionary found, add the "repository"
|
||||
* object with the URI.
|
||||
*/
|
||||
#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;
|
||||
@@ -120,61 +129,52 @@ repo_find_best_pkg_cb(struct repository_pool_index *rpi,
|
||||
bool *done)
|
||||
{
|
||||
struct repo_pool_fpkg *rpf = arg;
|
||||
prop_dictionary_t instpkgd;
|
||||
const char *instver, *repover;
|
||||
const char *repopkgver;
|
||||
|
||||
assert(rpi != NULL);
|
||||
|
||||
rpf->pkgd = xbps_find_pkg_in_dict_by_name(rpi->rpi_repod,
|
||||
"packages", rpf->pattern);
|
||||
(void)done;
|
||||
|
||||
if (rpf->bypattern) {
|
||||
rpf->pkgd = xbps_find_pkg_in_dict_by_pattern(rpi->rpi_repod,
|
||||
"packages", rpf->pattern);
|
||||
} else {
|
||||
rpf->pkgd = xbps_find_pkg_in_dict_by_name(rpi->rpi_repod,
|
||||
"packages", rpf->pattern);
|
||||
}
|
||||
if (rpf->pkgd == NULL) {
|
||||
if (errno && errno != ENOENT)
|
||||
return errno;
|
||||
|
||||
xbps_dbg_printf("[rpool] Package '%s' not found in repository "
|
||||
"'%s'.\n", rpf->pattern, rpi->rpi_uri);
|
||||
} else {
|
||||
/*
|
||||
* Check if version in repository is greater than
|
||||
* the version currently installed.
|
||||
*/
|
||||
instpkgd = xbps_find_pkg_dict_installed(rpf->pattern, false);
|
||||
if (instpkgd == NULL) {
|
||||
xbps_dbg_printf("[rpool] `%s' not installed, "
|
||||
"ignoring...\n", rpf->pattern);
|
||||
rpf->pkgd = NULL;
|
||||
return ENODEV;
|
||||
}
|
||||
prop_dictionary_get_cstring_nocopy(instpkgd,
|
||||
"version", &instver);
|
||||
prop_dictionary_get_cstring_nocopy(rpf->pkgd,
|
||||
"version", &repover);
|
||||
prop_object_release(instpkgd);
|
||||
|
||||
if (xbps_cmpver(repover, instver) <= 0) {
|
||||
xbps_dbg_printf("[rpool] Skipping '%s-%s' "
|
||||
"(installed: %s) from repository `%s'\n",
|
||||
rpf->pattern, repover, instver,
|
||||
rpi->rpi_uri);
|
||||
rpf->pkgd = NULL;
|
||||
errno = EEXIST;
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* New package version found, exit from the loop.
|
||||
*/
|
||||
xbps_dbg_printf("[rpool] Found '%s-%s' (installed: %s) "
|
||||
"in repository '%s'.\n", rpf->pattern, repover,
|
||||
instver, rpi->rpi_uri);
|
||||
prop_dictionary_set_cstring(rpf->pkgd, "repository",
|
||||
rpi->rpi_uri);
|
||||
*done = true;
|
||||
return 0;
|
||||
}
|
||||
prop_dictionary_get_cstring_nocopy(rpf->pkgd,
|
||||
"pkgver", &repopkgver);
|
||||
if (rpf->bestpkgver == NULL) {
|
||||
xbps_dbg_printf("[rpool] Found best match '%s' (%s).\n",
|
||||
repopkgver, rpi->rpi_uri);
|
||||
rpf->bestpkgver = repopkgver;
|
||||
rpf->repo_bestmatch = rpi->rpi_uri;
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Compare current stored version against new
|
||||
* version from current package in repository.
|
||||
*/
|
||||
if (xbps_cmpver(repopkgver, rpf->bestpkgver)) {
|
||||
xbps_dbg_printf("[rpool] Found best match '%s' (%s).\n",
|
||||
repopkgver, rpi->rpi_uri);
|
||||
rpf->bestpkgver = repopkgver;
|
||||
rpf->repo_bestmatch = rpi->rpi_uri;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct repo_pool_fpkg *
|
||||
repo_find_pkg(const char *pkg, bool bypattern, bool best, bool virtual)
|
||||
repo_find_pkg(const char *pkg, bool bypattern, bool best, bool exact,
|
||||
bool virtual)
|
||||
{
|
||||
struct repo_pool_fpkg *rpf;
|
||||
int rv = 0;
|
||||
@@ -187,9 +187,19 @@ repo_find_pkg(const char *pkg, bool bypattern, bool best, bool virtual)
|
||||
|
||||
rpf->pattern = pkg;
|
||||
rpf->bypattern = bypattern;
|
||||
rpf->exact = exact;
|
||||
rpf->pkgd = NULL;
|
||||
rpf->bestpkgver = NULL;
|
||||
rpf->repo_bestmatch = NULL;
|
||||
|
||||
if (best) {
|
||||
if (exact) {
|
||||
/*
|
||||
* Look for exact package match with pkgver in all repos.
|
||||
*/
|
||||
rv = xbps_repository_pool_foreach(repo_find_pkg_cb, rpf);
|
||||
if (rv != 0)
|
||||
errno = rv;
|
||||
} else if (best) {
|
||||
/*
|
||||
* Look for the best package version of a package name or
|
||||
* pattern in all repositories.
|
||||
@@ -197,6 +207,10 @@ repo_find_pkg(const char *pkg, bool bypattern, bool best, bool virtual)
|
||||
rv = xbps_repository_pool_foreach(repo_find_best_pkg_cb, rpf);
|
||||
if (rv != 0)
|
||||
errno = rv;
|
||||
|
||||
if (rpf->bestpkgver != NULL)
|
||||
rpf->pkgd =
|
||||
xbps_repository_pool_find_pkg_exact(rpf->bestpkgver);
|
||||
} else {
|
||||
if (virtual) {
|
||||
/*
|
||||
@@ -227,7 +241,7 @@ xbps_repository_pool_find_virtualpkg(const char *pkg, bool bypattern, bool best)
|
||||
|
||||
assert(pkg != NULL);
|
||||
|
||||
rpf = repo_find_pkg(pkg, bypattern, best, true);
|
||||
rpf = repo_find_pkg(pkg, bypattern, best, false, true);
|
||||
if (prop_object_type(rpf->pkgd) == PROP_TYPE_DICTIONARY)
|
||||
pkgd = prop_dictionary_copy(rpf->pkgd);
|
||||
free(rpf);
|
||||
@@ -243,7 +257,23 @@ xbps_repository_pool_find_pkg(const char *pkg, bool bypattern, bool best)
|
||||
|
||||
assert(pkg != NULL);
|
||||
|
||||
rpf = repo_find_pkg(pkg, bypattern, best, false);
|
||||
rpf = repo_find_pkg(pkg, bypattern, best, false, false);
|
||||
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_pkg_exact(const char *pkgver)
|
||||
{
|
||||
struct repo_pool_fpkg *rpf;
|
||||
prop_dictionary_t pkgd = NULL;
|
||||
|
||||
assert(pkgver != NULL);
|
||||
|
||||
rpf = repo_find_pkg(pkgver, false, false, true, false);
|
||||
if (prop_object_type(rpf->pkgd) == PROP_TYPE_DICTIONARY)
|
||||
pkgd = prop_dictionary_copy(rpf->pkgd);
|
||||
free(rpf);
|
||||
|
@@ -51,44 +51,48 @@
|
||||
* Text inside of white boxes are the key associated with the object, its
|
||||
* data type is specified on its edge, i.e string, array, integer, dictionary.
|
||||
*/
|
||||
enum {
|
||||
TRANS_INSTALL = 1,
|
||||
TRANS_UPDATE
|
||||
};
|
||||
|
||||
static int
|
||||
transaction_find_pkg(const char *pattern, const char *reason)
|
||||
transaction_find_pkg(const char *pattern, int action)
|
||||
{
|
||||
prop_dictionary_t pkg_repod = NULL;
|
||||
prop_dictionary_t pkg_regpkgdb, pkg_repod = NULL;
|
||||
prop_dictionary_t transd;
|
||||
prop_array_t mdeps, unsorted;
|
||||
const char *pkgname, *pkgver, *repoloc;
|
||||
const char *pkgname, *pkgver, *repoloc, *repover, *instver, *reason;
|
||||
int rv = 0;
|
||||
bool bypattern = false, bestpkg;
|
||||
bool bypattern, bestpkg;
|
||||
pkg_state_t state = 0;
|
||||
|
||||
assert(pattern != NULL);
|
||||
assert(reason != NULL);
|
||||
|
||||
if (strcmp(reason, "install") == 0) {
|
||||
if (action == TRANS_INSTALL) {
|
||||
/* install */
|
||||
bypattern = true;
|
||||
bestpkg = false;
|
||||
reason = "install";
|
||||
} else {
|
||||
/* update */
|
||||
pkg_repod = xbps_find_pkg_dict_installed(pattern, false);
|
||||
if (pkg_repod == NULL) {
|
||||
pkg_regpkgdb = xbps_find_pkg_dict_installed(pattern, false);
|
||||
if (pkg_regpkgdb == NULL) {
|
||||
rv = ENODEV;
|
||||
goto out;
|
||||
}
|
||||
prop_object_release(pkg_repod);
|
||||
pkg_repod = NULL;
|
||||
bypattern = false;
|
||||
bestpkg = true;
|
||||
reason = "update";
|
||||
}
|
||||
|
||||
xbps_dbg_printf("%s: pattern %s reason %s\n", __func__, pattern, reason);
|
||||
/*
|
||||
* Find out if the pkg has been found in repository pool.
|
||||
*/
|
||||
pkg_repod = xbps_repository_pool_find_pkg(pattern,
|
||||
bypattern, bestpkg);
|
||||
if (pkg_repod == NULL) {
|
||||
if (bestpkg == false) {
|
||||
if (!bestpkg) {
|
||||
pkg_repod = xbps_repository_pool_find_virtualpkg(
|
||||
pattern, bypattern, bestpkg);
|
||||
}
|
||||
@@ -99,6 +103,27 @@ transaction_find_pkg(const char *pattern, const char *reason)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
prop_dictionary_get_cstring_nocopy(pkg_repod, "pkgver", &pkgver);
|
||||
prop_dictionary_get_cstring_nocopy(pkg_repod, "repository", &repoloc);
|
||||
prop_dictionary_get_cstring_nocopy(pkg_repod, "pkgname", &pkgname);
|
||||
|
||||
if (bestpkg) {
|
||||
/*
|
||||
* Compare installed version vs best pkg available in repos.
|
||||
*/
|
||||
prop_dictionary_get_cstring_nocopy(pkg_regpkgdb,
|
||||
"version", &instver);
|
||||
prop_dictionary_get_cstring_nocopy(pkg_repod,
|
||||
"version", &repover);
|
||||
prop_object_release(pkg_regpkgdb);
|
||||
if (xbps_cmpver(repover, instver) <= 0) {
|
||||
xbps_dbg_printf("[rpool] Skipping `%s' "
|
||||
"(installed: %s) from repository `%s'\n",
|
||||
pkgver, instver, repoloc);
|
||||
rv = EEXIST;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Prepare transaction dictionary and missing deps array.
|
||||
*/
|
||||
@@ -111,9 +136,6 @@ transaction_find_pkg(const char *pattern, const char *reason)
|
||||
goto out;
|
||||
}
|
||||
|
||||
prop_dictionary_get_cstring_nocopy(pkg_repod, "pkgname", &pkgname);
|
||||
prop_dictionary_get_cstring_nocopy(pkg_repod, "pkgver", &pkgver);
|
||||
prop_dictionary_get_cstring_nocopy(pkg_repod, "repository", &repoloc);
|
||||
/*
|
||||
* Prepare required package dependencies and add them into the
|
||||
* "unsorted" array in transaction dictionary.
|
||||
@@ -217,13 +239,13 @@ xbps_transaction_update_packages(void)
|
||||
int
|
||||
xbps_transaction_update_pkg(const char *pkgname)
|
||||
{
|
||||
return transaction_find_pkg(pkgname, "update");
|
||||
return transaction_find_pkg(pkgname, TRANS_UPDATE);
|
||||
}
|
||||
|
||||
int
|
||||
xbps_transaction_install_pkg(const char *pkgpattern)
|
||||
{
|
||||
return transaction_find_pkg(pkgpattern, "install");
|
||||
return transaction_find_pkg(pkgpattern, TRANS_INSTALL);
|
||||
}
|
||||
|
||||
int
|
||||
|
Reference in New Issue
Block a user