Major API/ABI cleanup bringing performance improvements and fixes.
These are the core interfaces in the new API: rpool - Interface to interact with the repository pool. rindex - Interface to interact with repository indexes. pkgdb - Interface to interact with local packages. transaction - Interface to interact with a transaction. This also brings new repository index format, making the index file per architecture and being incompatible with previous versions. The transaction frequency flush option has been removed, and due to the nature of package states it was causing more harm than good. More changes coming soon, but the API shall remain stable from now on.
This commit is contained in:
389
lib/plist_find.c
389
lib/plist_find.c
@@ -31,378 +31,89 @@
|
||||
|
||||
#include "xbps_api_impl.h"
|
||||
|
||||
/**
|
||||
* @file lib/plist_find.c
|
||||
* @brief PropertyList generic routines
|
||||
* @defgroup plist PropertyList generic functions
|
||||
*
|
||||
* These functions manipulate plist files and objects shared by almost
|
||||
* all library functions.
|
||||
*/
|
||||
static prop_dictionary_t
|
||||
find_pkg_in_array(struct xbps_handle *xhp,
|
||||
prop_array_t array,
|
||||
const char *str,
|
||||
bool bypattern,
|
||||
bool virtual,
|
||||
const char *targetarch)
|
||||
get_pkg_in_array(prop_array_t array, const char *str, bool virtual)
|
||||
{
|
||||
prop_object_iterator_t iter;
|
||||
prop_object_t obj = NULL;
|
||||
const char *pkgver, *dpkgn, *arch;
|
||||
bool chkarch;
|
||||
|
||||
assert(prop_object_type(array) == PROP_TYPE_ARRAY);
|
||||
assert(str != NULL);
|
||||
|
||||
iter = prop_array_iterator(array);
|
||||
if (iter == NULL)
|
||||
return NULL;
|
||||
|
||||
while ((obj = prop_object_iterator_next(iter))) {
|
||||
chkarch = prop_dictionary_get_cstring_nocopy(obj,
|
||||
"architecture", &arch);
|
||||
if (chkarch && !xbps_pkg_arch_match(xhp, arch, targetarch))
|
||||
continue;
|
||||
const char *pkgver, *dpkgn;
|
||||
size_t i;
|
||||
bool found = false;
|
||||
|
||||
for (i = 0; i < prop_array_count(array); i++) {
|
||||
obj = prop_array_get(array, i);
|
||||
if (virtual) {
|
||||
/*
|
||||
* Check if package pattern matches
|
||||
* any virtual package version in dictionary.
|
||||
*/
|
||||
if (xbps_match_virtual_pkg_in_dict(obj, str, bypattern))
|
||||
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);
|
||||
|
||||
if (found)
|
||||
break;
|
||||
} else if (bypattern) {
|
||||
/*
|
||||
* Check if package pattern matches the
|
||||
* pkgver string object in dictionary.
|
||||
*/
|
||||
} else if (xbps_pkgpattern_version(str)) {
|
||||
/* ,atch by pattern against pkgver */
|
||||
if (!prop_dictionary_get_cstring_nocopy(obj,
|
||||
"pkgver", &pkgver))
|
||||
continue;
|
||||
if (xbps_pkgpattern_match(pkgver, str))
|
||||
if (xbps_pkgpattern_match(pkgver, str)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
} else if (xbps_pkg_version(str)) {
|
||||
/* match by exact pkgver */
|
||||
if (!prop_dictionary_get_cstring_nocopy(obj,
|
||||
"pkgver", &pkgver))
|
||||
continue;
|
||||
if (strcmp(str, pkgver) == 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* match by pkgname */
|
||||
if (!prop_dictionary_get_cstring_nocopy(obj,
|
||||
"pkgname", &dpkgn))
|
||||
continue;
|
||||
if (strcmp(dpkgn, str) == 0)
|
||||
if (strcmp(dpkgn, str) == 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop_object_iterator_release(iter);
|
||||
if (obj == NULL) {
|
||||
errno = ENOENT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
prop_dictionary_t
|
||||
xbps_find_pkg_in_array_by_name(struct xbps_handle *xhp,
|
||||
prop_array_t array,
|
||||
const char *name,
|
||||
const char *targetarch)
|
||||
{
|
||||
return find_pkg_in_array(xhp, array, name, false, false, targetarch);
|
||||
}
|
||||
|
||||
prop_dictionary_t
|
||||
xbps_find_pkg_in_array_by_pattern(struct xbps_handle *xhp,
|
||||
prop_array_t array,
|
||||
const char *pattern,
|
||||
const char *targetarch)
|
||||
{
|
||||
return find_pkg_in_array(xhp, array, pattern, true, false, targetarch);
|
||||
}
|
||||
|
||||
prop_dictionary_t
|
||||
xbps_find_pkg_in_array_by_pkgver(struct xbps_handle *xhp,
|
||||
prop_array_t array,
|
||||
const char *pkgver,
|
||||
const char *targetarch)
|
||||
{
|
||||
prop_object_iterator_t iter;
|
||||
prop_object_t obj = NULL;
|
||||
const char *rpkgver, *arch;
|
||||
bool chkarch, found = false;
|
||||
|
||||
assert(prop_object_type(array) == PROP_TYPE_ARRAY);
|
||||
assert(pkgver != NULL);
|
||||
|
||||
iter = prop_array_iterator(array);
|
||||
if (iter == NULL)
|
||||
return NULL;
|
||||
|
||||
while ((obj = prop_object_iterator_next(iter))) {
|
||||
chkarch = prop_dictionary_get_cstring_nocopy(obj,
|
||||
"architecture", &arch);
|
||||
if (!prop_dictionary_get_cstring_nocopy(obj,
|
||||
"pkgver", &rpkgver))
|
||||
continue;
|
||||
if (chkarch && !xbps_pkg_arch_match(xhp, arch, targetarch))
|
||||
continue;
|
||||
if (strcmp(pkgver, rpkgver) == 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
prop_object_iterator_release(iter);
|
||||
if (found)
|
||||
return obj;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
prop_dictionary_t
|
||||
xbps_find_virtualpkg_in_array_by_name(struct xbps_handle *xhp,
|
||||
prop_array_t array,
|
||||
const char *name)
|
||||
{
|
||||
return find_pkg_in_array(xhp, array, name, false, true, NULL);
|
||||
}
|
||||
|
||||
prop_dictionary_t
|
||||
xbps_find_virtualpkg_in_array_by_pattern(struct xbps_handle *xhp,
|
||||
prop_array_t array,
|
||||
const char *pattern)
|
||||
{
|
||||
return find_pkg_in_array(xhp, array, pattern, true, true, NULL);
|
||||
}
|
||||
|
||||
static const char *
|
||||
find_virtualpkg_user_in_conf(struct xbps_handle *xhp,
|
||||
const char *vpkg,
|
||||
bool bypattern)
|
||||
{
|
||||
const char *vpkgver, *pkg = NULL;
|
||||
char *vpkgname = NULL, *tmp;
|
||||
size_t i, j, cnt;
|
||||
|
||||
if (xhp->cfg == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((cnt = cfg_size(xhp->cfg, "virtual-package")) == 0) {
|
||||
/* no virtual packages configured */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < cnt; i++) {
|
||||
cfg_t *sec = cfg_getnsec(xhp->cfg, "virtual-package", i);
|
||||
for (j = 0; j < cfg_size(sec, "targets"); j++) {
|
||||
tmp = NULL;
|
||||
vpkgver = cfg_getnstr(sec, "targets", j);
|
||||
if (strchr(vpkgver, '_') == NULL) {
|
||||
tmp = xbps_xasprintf("%s_1", vpkgver);
|
||||
vpkgname = xbps_pkg_name(tmp);
|
||||
free(tmp);
|
||||
} else {
|
||||
vpkgname = xbps_pkg_name(vpkgver);
|
||||
}
|
||||
if (vpkgname == NULL)
|
||||
break;
|
||||
if (bypattern) {
|
||||
if (!xbps_pkgpattern_match(vpkgver, vpkg)) {
|
||||
free(vpkgname);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (strcmp(vpkg, vpkgname)) {
|
||||
free(vpkgname);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* virtual package matched in conffile */
|
||||
pkg = cfg_title(sec);
|
||||
xbps_dbg_printf(xhp,
|
||||
"matched vpkg in conf `%s' for %s\n",
|
||||
pkg, vpkg);
|
||||
free(vpkgname);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return pkg;
|
||||
}
|
||||
|
||||
static prop_dictionary_t
|
||||
find_virtualpkg_user_in_array(struct xbps_handle *xhp,
|
||||
prop_array_t array,
|
||||
const char *str,
|
||||
bool bypattern)
|
||||
{
|
||||
const char *vpkgname;
|
||||
|
||||
assert(prop_object_type(array) == PROP_TYPE_ARRAY);
|
||||
assert(str != NULL);
|
||||
|
||||
vpkgname = find_virtualpkg_user_in_conf(xhp, str, bypattern);
|
||||
if (vpkgname == NULL)
|
||||
return NULL;
|
||||
|
||||
return find_pkg_in_array(xhp, array, vpkgname, false, false, NULL);
|
||||
return found ? obj : NULL;
|
||||
}
|
||||
|
||||
prop_dictionary_t HIDDEN
|
||||
xbps_find_virtualpkg_conf_in_array_by_name(struct xbps_handle *xhp,
|
||||
prop_array_t array,
|
||||
const char *name)
|
||||
xbps_find_pkg_in_array(prop_array_t a, const char *s)
|
||||
{
|
||||
return find_virtualpkg_user_in_array(xhp, array, name, false);
|
||||
assert(prop_object_type(a) == PROP_TYPE_ARRAY);
|
||||
assert(s);
|
||||
|
||||
return get_pkg_in_array(a, s, false);
|
||||
}
|
||||
|
||||
prop_dictionary_t HIDDEN
|
||||
xbps_find_virtualpkg_conf_in_array_by_pattern(struct xbps_handle *xhp,
|
||||
prop_array_t array,
|
||||
const char *p)
|
||||
xbps_find_virtualpkg_in_array(struct xbps_handle *x,
|
||||
prop_array_t a,
|
||||
const char *s)
|
||||
{
|
||||
return find_virtualpkg_user_in_array(xhp, array, p, true);
|
||||
}
|
||||
prop_dictionary_t pkgd;
|
||||
const char *vpkg;
|
||||
bool bypattern = false;
|
||||
|
||||
static prop_dictionary_t
|
||||
find_pkg_in_dict(struct xbps_handle *xhp,
|
||||
prop_dictionary_t d,
|
||||
const char *key,
|
||||
const char *str,
|
||||
bool bypattern,
|
||||
bool virtual)
|
||||
{
|
||||
prop_array_t array;
|
||||
assert(x);
|
||||
assert(prop_object_type(a) == PROP_TYPE_ARRAY);
|
||||
assert(s);
|
||||
|
||||
assert(prop_object_type(d) == PROP_TYPE_DICTIONARY);
|
||||
assert(str != NULL);
|
||||
assert(key != NULL);
|
||||
if (xbps_pkgpattern_version(s))
|
||||
bypattern = true;
|
||||
|
||||
array = prop_dictionary_get(d, key);
|
||||
if (prop_object_type(array) != PROP_TYPE_ARRAY)
|
||||
return NULL;
|
||||
|
||||
return find_pkg_in_array(xhp, array, str, bypattern, virtual, NULL);
|
||||
}
|
||||
|
||||
prop_dictionary_t
|
||||
xbps_find_pkg_in_dict_by_name(struct xbps_handle *xhp,
|
||||
prop_dictionary_t d,
|
||||
const char *key,
|
||||
const char *pkgname)
|
||||
{
|
||||
return find_pkg_in_dict(xhp, d, key, pkgname, false, false);
|
||||
}
|
||||
|
||||
prop_dictionary_t
|
||||
xbps_find_pkg_in_dict_by_pattern(struct xbps_handle *xhp,
|
||||
prop_dictionary_t d,
|
||||
const char *key,
|
||||
const char *pattern)
|
||||
{
|
||||
return find_pkg_in_dict(xhp, d, key, pattern, true, false);
|
||||
}
|
||||
|
||||
prop_dictionary_t
|
||||
xbps_find_pkg_in_dict_by_pkgver(struct xbps_handle *xhp,
|
||||
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(xhp, array, pkgver, NULL);
|
||||
}
|
||||
|
||||
prop_dictionary_t
|
||||
xbps_find_virtualpkg_in_dict_by_name(struct xbps_handle *xhp,
|
||||
prop_dictionary_t d,
|
||||
const char *key,
|
||||
const char *name)
|
||||
{
|
||||
return find_pkg_in_dict(xhp, d, key, name, false, true);
|
||||
}
|
||||
|
||||
prop_dictionary_t
|
||||
xbps_find_virtualpkg_in_dict_by_pattern(struct xbps_handle *xhp,
|
||||
prop_dictionary_t d,
|
||||
const char *key,
|
||||
const char *pattern)
|
||||
{
|
||||
return find_pkg_in_dict(xhp, d, key, pattern, true, true);
|
||||
}
|
||||
|
||||
static prop_dictionary_t
|
||||
find_pkgd_installed(struct xbps_handle *xhp,
|
||||
const char *str,
|
||||
bool bypattern,
|
||||
bool virtual)
|
||||
{
|
||||
prop_dictionary_t pkgd = NULL;
|
||||
pkg_state_t state = 0;
|
||||
int rv;
|
||||
|
||||
assert(str != NULL);
|
||||
|
||||
if ((rv = xbps_pkgdb_init(xhp)) != 0) {
|
||||
if (rv != ENOENT) {
|
||||
xbps_dbg_printf(xhp, "%s: couldn't initialize "
|
||||
"pkgdb: %s\n", strerror(rv));
|
||||
return NULL;
|
||||
} else if (rv == ENOENT)
|
||||
return NULL;
|
||||
if ((vpkg = vpkg_user_conf(x, s, bypattern))) {
|
||||
if ((pkgd = get_pkg_in_array(a, vpkg, true)))
|
||||
return pkgd;
|
||||
}
|
||||
|
||||
/* try normal pkg */
|
||||
if (virtual == false) {
|
||||
pkgd = find_pkg_in_array(xhp, xhp->pkgdb, str,
|
||||
bypattern, false, NULL);
|
||||
} else {
|
||||
/* virtual pkg set by user in conf */
|
||||
pkgd = find_virtualpkg_user_in_array(xhp, xhp->pkgdb,
|
||||
str, bypattern);
|
||||
if (pkgd == NULL) {
|
||||
/* any virtual pkg in array matching pattern */
|
||||
pkgd = find_pkg_in_array(xhp, xhp->pkgdb,
|
||||
str, bypattern, true, NULL);
|
||||
}
|
||||
}
|
||||
/* pkg not found */
|
||||
if (pkgd == NULL)
|
||||
return NULL;
|
||||
|
||||
if (xbps_pkg_state_dictionary(pkgd, &state) != 0)
|
||||
return NULL;
|
||||
|
||||
switch (state) {
|
||||
case XBPS_PKG_STATE_INSTALLED:
|
||||
case XBPS_PKG_STATE_UNPACKED:
|
||||
return pkgd;
|
||||
/* NOTREACHED */
|
||||
default:
|
||||
/* not fully installed */
|
||||
errno = ENOENT;
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
prop_dictionary_t
|
||||
xbps_find_pkg_dict_installed(struct xbps_handle *xhp,
|
||||
const char *str,
|
||||
bool bypattern)
|
||||
{
|
||||
return find_pkgd_installed(xhp, str, bypattern, false);
|
||||
}
|
||||
|
||||
prop_dictionary_t
|
||||
xbps_find_virtualpkg_dict_installed(struct xbps_handle *xhp,
|
||||
const char *str,
|
||||
bool bypattern)
|
||||
{
|
||||
return find_pkgd_installed(xhp, str, bypattern, true);
|
||||
return get_pkg_in_array(a, s, true);
|
||||
}
|
||||
|
Reference in New Issue
Block a user