diff --git a/NEWS b/NEWS index e0905ba3..8682625d 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,12 @@ xbps-0.8.0 (???): + * Added support for virtual packages. A virtual package is one that doesn't + exist in the repository, but other packages can provide it. A new array + in the package properties dictionary has been added to specify which + virtual packages the package supports. As an example, the `rsyslog' + package provides the virtual package `syslog-daemon-0'. Other packages + can depend in `syslog-daemon>=0' and `rsyslog' will satisfy the dependency. + * Merged the `progress_callback' branch that makes possible to specify a function callback to update progress while unpacking binary packages and while fetching files. xbps-bin(8) now reports a percentage while @@ -11,13 +18,15 @@ xbps-0.8.0 (???): found in the first repository registered in the pool. It can also be used to find the newest version found in all registered repositories. - * Improved package dependency sorting algorithm that uses less memory - and as bonus sorts all packages in the way they should be (previously - the sorting was a bit different for packages with no run-time dependencies). + * Improved package dependency sorting algorithm that uses less memory, + it is 15% faster approximately and as bonus sorts all packages in the way + they should be (previously the sorting was a bit different for packages + with no run-time dependencies). - * Hide implementation details in the API, so the ABI is not compatible - anymore with previous versions. ABI will be respected once the API - has been stabilized, but not for now. + * Many structural changes in the API. Made some stuff private and changed + some function arguments in the API, the ABI is not compatible anymore with + previous versions... anyway you shouldn't be using libxbps just yet. + The API documentation has been modified to stay in sync with reality. xbps-0.7.3 (2011-01-16): diff --git a/include/xbps_api.h b/include/xbps_api.h index e2abd6c4..31f94cc0 100644 --- a/include/xbps_api.h +++ b/include/xbps_api.h @@ -53,7 +53,7 @@ * @def XBPS_RELVER * Current library release date. */ -#define XBPS_RELVER "20110125" +#define XBPS_RELVER "20110126" /** * @def XBPS_META_PATH @@ -460,6 +460,26 @@ prop_dictionary_t xbps_find_pkg_from_plist(const char *plist, prop_dictionary_t xbps_find_pkg_dict_installed(const char *str, bool bypattern); +/** + * Finds a package name matching an string object in a proplib array. + * + * @param[in] array The proplib array where to look for. + * @param[in] pkgname The package name to match. + * + * @return true on success, false otherwise and errno is set appropiately. + */ +bool xbps_find_pkgname_in_array(prop_array_t array, const char *pkgname); + +/** + * Finds a package pattern matching an string object in a proplib array. + * + * @param[in] array The proplib array where to look for. + * @param[in] pattern The package pattern to match. + * + * @return true on success, false otherwise and errno is set appropiately. + */ +bool xbps_find_pkgpattern_in_array(prop_array_t array, const char *pattern); + /** * Finds a string matching an object in a proplib array. * diff --git a/lib/plist.c b/lib/plist.c index 6f58e12c..c6f2402c 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -233,6 +233,37 @@ out: return rpkgd; } +static prop_dictionary_t +find_virtual_pkg(prop_dictionary_t d, + const char *key, + const char *str, + bool bypattern) +{ + prop_object_iterator_t iter; + prop_object_t obj; + prop_array_t provides; + bool found = false; + + if ((iter = xbps_get_array_iter_from_dict(d, key)) == NULL) + return NULL; + + while ((obj = prop_object_iterator_next(iter))) { + if ((provides = prop_dictionary_get(obj, "provides")) == NULL) + continue; + + if (bypattern) + found = xbps_find_pkgpattern_in_array(provides, str); + else + found = xbps_find_pkgname_in_array(provides, str); + + if (found) + break; + } + prop_object_iterator_release(iter); + + return obj; +} + prop_dictionary_t xbps_find_pkg_in_dict_by_name(prop_dictionary_t dict, const char *key, @@ -256,8 +287,15 @@ xbps_find_pkg_in_dict_by_name(prop_dictionary_t dict, } prop_object_iterator_release(iter); if (obj == NULL) { - errno = ENOENT; - return NULL; + /* + * If a package couldn't be found by its name, try looking + * for a package providing a virtual package, i.e "provides". + */ + obj = find_virtual_pkg(dict, key, pkgname, false); + if (obj == NULL) { + errno = ENOENT; + return NULL; + } } return obj; @@ -286,18 +324,89 @@ xbps_find_pkg_in_dict_by_pattern(prop_dictionary_t dict, } prop_object_iterator_release(iter); if (obj == NULL) { - errno = ENOENT; - return NULL; + /* + * If a package couldn't be found by a pattern, try looking + * for a package providing a virtual package pattern via + * "provides". + */ + obj = find_virtual_pkg(dict, key, pattern, true); + if (obj == NULL) { + errno = ENOENT; + return NULL; + } } return obj; } +bool +xbps_find_pkgname_in_array(prop_array_t array, const char *pkgname) +{ + prop_object_iterator_t iter; + prop_object_t obj; + const char *pkgdep; + char *curpkgname; + bool found = false; + + assert(array != NULL); + assert(pkgname != NULL); + + iter = prop_array_iterator(array); + if (iter == NULL) + return false; + + while ((obj = prop_object_iterator_next(iter))) { + assert(prop_object_type(obj) == PROP_TYPE_STRING); + pkgdep = prop_string_cstring_nocopy(obj); + curpkgname = xbps_get_pkg_name(pkgdep); + if (curpkgname == NULL) + break; + if (strcmp(curpkgname, pkgname) == 0) { + free(curpkgname); + found = true; + break; + } + free(curpkgname); + } + prop_object_iterator_release(iter); + + return found; +} + +bool +xbps_find_pkgpattern_in_array(prop_array_t array, const char *pattern) +{ + prop_object_iterator_t iter; + prop_object_t obj; + const char *curpkgdep; + bool found = false; + + assert(array != NULL); + assert(pattern != NULL); + + iter = prop_array_iterator(array); + if (iter == NULL) + return false; + + while ((obj = prop_object_iterator_next(iter))) { + assert(prop_object_type(obj) == PROP_TYPE_STRING); + curpkgdep = prop_string_cstring_nocopy(obj); + if (xbps_pkgpattern_match(curpkgdep, __UNCONST(pattern))) { + found = true; + break; + } + } + prop_object_iterator_release(iter); + + return found; +} + bool xbps_find_string_in_array(prop_array_t array, const char *val) { prop_object_iterator_t iter; prop_object_t obj; + bool found = false; assert(array != NULL); assert(val != NULL); @@ -307,17 +416,15 @@ xbps_find_string_in_array(prop_array_t array, const char *val) return false; while ((obj = prop_object_iterator_next(iter)) != NULL) { - if (prop_object_type(obj) != PROP_TYPE_STRING) - continue; + assert(prop_object_type(obj) == PROP_TYPE_STRING); if (prop_string_equals_cstring(obj, val)) { - prop_object_iterator_release(iter); - return true; + found = true; + break; } } - prop_object_iterator_release(iter); - return false; + return found; } prop_object_iterator_t diff --git a/lib/repository_pool.c b/lib/repository_pool.c index 693b0aea..dd306a3a 100644 --- a/lib/repository_pool.c +++ b/lib/repository_pool.c @@ -262,9 +262,6 @@ repo_find_pkg_cb(struct repository_pool_index *rpi, void *arg, bool *done) errno = 0; return 0; } - - xbps_dbg_printf("Didn't find '%s' (%s)\n", - rpf->pattern, rpi->rpi_uri); /* Not found */ errno = ENOENT; return 0;