libxbps: extend the API, new func: xbps_repository_pool_find_pkg.

prop_dictionary_t xbps_repository_pool_find_pkg(const char *pkg, bool bypattern, bool best)

This function iterates over the repository pool and returns a pkg
dictionary matching its pkgname if "bypattern" is false, otherwise
if "pkg" matches the pkgdep pattern. If "best" is true, it will look
in all repos and will return the newer version, otherwise the first one
that matches the arguments specified.

With this addition supporting many small registered repos is cheap, because
it checks by-package rather than by-package-list. This also helped to removed
some duplicated code and fix some rare bugs.

Bump XBPS_RELVER to 20110118.
This commit is contained in:
Juan RP 2011-01-18 14:44:39 +01:00
parent 1125963da8
commit 503afdd48d
5 changed files with 260 additions and 326 deletions

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2008-2010 Juan Romero Pardines.
* Copyright (c) 2008-2011 Juan Romero Pardines.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -51,7 +51,7 @@
* @def XBPS_RELVER
* Current library release date.
*/
#define XBPS_RELVER "20101118"
#define XBPS_RELVER "20110118"
/**
* @def XBPS_META_PATH
@ -763,9 +763,9 @@ void xbps_repository_pool_release(void);
* set to true, otherwise it will only be stopped if it returns a
* non-zero value.
*
* @param fn Function callback to execute for every repository registered in
* @param[in] fn Function callback to execute for every repository registered in
* the pool.
* @param arg Opaque data passed in to the \a fn function callback for
* @param[in] arg Opaque data passed in to the \a fn function callback for
* client data.
*
* @return 0 on success, otherwise an errno value.
@ -774,6 +774,20 @@ int xbps_repository_pool_foreach(
int (*fn)(struct repository_pool_index *, void *, bool *),
void *arg);
/**
* Finds a package dictionary in the repository pool by specifying a
* package pattern or a package name.
*
* @param[in] pkg Package pattern or name.
* @param[in] bypattern True if \a pkg is a pattern, 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.
*
* @return The package dictionary if found, NULL otherwise.
*/
prop_dictionary_t
xbps_repository_pool_find_pkg(const char *pkg, bool bypattern, bool best);
/*@}*/
/** @addtogroup reposync */

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2008-2010 Juan Romero Pardines.
* Copyright (c) 2008-2011 Juan Romero Pardines.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -32,25 +32,24 @@
#include "xbps_api_impl.h"
static int
store_dependency(prop_dictionary_t trans_dict, prop_dictionary_t repo_pkg_dict,
const char *repoloc)
store_dependency(prop_dictionary_t trans_dict, prop_dictionary_t repo_pkgd)
{
prop_dictionary_t dict;
prop_array_t array;
const char *pkgname, *pkgver;
const char *pkgname, *pkgver, *repoloc;
int rv = 0;
pkg_state_t state = 0;
assert(trans_dict != NULL);
assert(repo_pkg_dict != NULL);
assert(repoloc != NULL);
assert(repo_pkgd != NULL);
/*
* Get some info about dependencies and current repository.
*/
prop_dictionary_get_cstring_nocopy(repo_pkg_dict, "pkgname", &pkgname);
prop_dictionary_get_cstring_nocopy(repo_pkg_dict, "pkgver", &pkgver);
prop_dictionary_get_cstring_nocopy(repo_pkgd, "pkgname", &pkgname);
prop_dictionary_get_cstring_nocopy(repo_pkgd, "pkgver", &pkgver);
prop_dictionary_get_cstring_nocopy(repo_pkgd, "repository", &repoloc);
dict = prop_dictionary_copy(repo_pkg_dict);
dict = prop_dictionary_copy(repo_pkgd);
if (dict == NULL)
return errno;
@ -69,7 +68,6 @@ store_dependency(prop_dictionary_t trans_dict, prop_dictionary_t repo_pkg_dict,
prop_object_release(dict);
return rv;
}
/*
* Overwrite package state in dictionary if it was unpacked
* previously.
@ -83,10 +81,6 @@ store_dependency(prop_dictionary_t trans_dict, prop_dictionary_t repo_pkg_dict,
/*
* Add required objects into package dep's dictionary.
*/
if (!prop_dictionary_set_cstring(dict, "repository", repoloc)) {
prop_object_release(dict);
return errno;
}
if (!prop_dictionary_set_bool(dict, "automatic-install", true)) {
prop_object_release(dict);
return errno;
@ -105,9 +99,8 @@ store_dependency(prop_dictionary_t trans_dict, prop_dictionary_t repo_pkg_dict,
}
static int
add_missing_reqdep(prop_dictionary_t trans_dict, const char *reqpkg)
add_missing_reqdep(prop_array_t missing_rdeps, const char *reqpkg)
{
prop_array_t missing_rdeps;
prop_string_t reqpkg_str;
prop_object_iterator_t iter = NULL;
prop_object_t obj;
@ -115,7 +108,7 @@ add_missing_reqdep(prop_dictionary_t trans_dict, const char *reqpkg)
bool add_pkgdep, pkgfound, update_pkgdep;
int rv = 0;
assert(trans_dict != NULL);
assert(missing_rdeps != NULL);
assert(reqpkg != NULL);
add_pkgdep = update_pkgdep = pkgfound = false;
@ -124,7 +117,6 @@ add_missing_reqdep(prop_dictionary_t trans_dict, const char *reqpkg)
if (reqpkg_str == NULL)
return errno;
missing_rdeps = prop_dictionary_get(trans_dict, "missing_deps");
iter = prop_array_iterator(missing_rdeps);
if (iter == NULL)
goto out;
@ -192,19 +184,17 @@ out:
}
static int
remove_missing_reqdep(prop_dictionary_t trans_dict, const char *reqpkg)
remove_missing_reqdep(prop_array_t missing_rdeps, const char *reqpkg)
{
prop_array_t missing_rdeps;
prop_object_iterator_t iter = NULL;
prop_object_t obj;
size_t idx = 0;
int rv = 0;
bool found = false;
assert(trans_dict != NULL);
assert(missing_rdeps != NULL);
assert(reqpkg != NULL);
missing_rdeps = prop_dictionary_get(trans_dict, "missing_deps");
iter = prop_array_iterator(missing_rdeps);
if (iter == NULL)
return errno;
@ -247,16 +237,17 @@ out:
}
static int
find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
const char *repoloc, const char *originpkgn,
prop_array_t pkg_rdeps_array)
find_repo_deps(prop_dictionary_t trans_dict, /* transaction dictionary */
prop_array_t mrdeps, /* missing rundeps array */
const char *originpkgn, /* origin pkgname */
prop_array_t pkg_rdeps_array) /* current pkg rundeps array */
{
prop_dictionary_t curpkgd, tmpd;
prop_array_t curpkg_rdeps;
prop_object_t obj;
prop_object_iterator_t iter;
pkg_state_t state = 0;
const char *reqpkg, *reqvers, *pkg_queued, *repo_pkgver;
const char *reqpkg, *reqvers, *pkg_queued;
char *pkgname;
int rv = 0;
@ -269,6 +260,7 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
* current package.
*/
while ((obj = prop_object_iterator_next(iter)) != NULL) {
curpkgd = NULL;
reqpkg = prop_string_cstring_nocopy(obj);
if (reqpkg == NULL) {
rv = EINVAL;
@ -320,7 +312,7 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
rv = errno;
break;
}
} else if (curpkgd) {
} else {
prop_dictionary_get_cstring_nocopy(curpkgd,
"pkgver", &pkg_queued);
if (xbps_pkgpattern_match(pkg_queued,
@ -330,14 +322,14 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
free(pkgname);
continue;
}
curpkgd = NULL;
}
/*
* If required package is not in repo, add it into the
* If required pkgdep is not in repo, add it into the
* missing deps array and pass to the next one.
*/
curpkgd = xbps_find_pkg_in_dict_by_name(repo_dict,
"packages", pkgname);
curpkgd = xbps_repository_pool_find_pkg(reqpkg, true, false);
if (curpkgd == NULL) {
if (errno && errno != ENOENT) {
free(pkgname);
@ -345,7 +337,7 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
break;
}
rv = add_missing_reqdep(trans_dict, reqpkg);
rv = add_missing_reqdep(mrdeps, reqpkg);
if (rv != 0 && rv != EEXIST) {
xbps_dbg_printf_append("add missing reqdep "
"failed %s\n", reqpkg);
@ -359,31 +351,23 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
continue;
} else {
xbps_dbg_printf_append(
"missing package in repository!\n");
"missing dep '%s' in repository!\n",
reqpkg);
free(pkgname);
continue;
}
}
/*
* If version in repo does not satisfy the rundep, pass
* to the next rundep.
*/
prop_dictionary_get_cstring_nocopy(curpkgd, "pkgver", &repo_pkgver);
if (xbps_pkgpattern_match(repo_pkgver, __UNCONST(reqpkg)) < 1) {
free(pkgname);
continue;
}
/*
* If package is installed but version doesn't satisfy
* the dependency mark it as an update, otherwise as
* an install. Packages that were unpacked previously
* will be marked as pending to be configured.
*/
tmpd = xbps_find_pkg_dict_installed(pkgname, false);
tmpd = xbps_find_pkg_dict_installed(reqpkg, true);
if (tmpd == NULL) {
if (errno && errno != ENOENT) {
free(pkgname);
prop_object_release(curpkgd);
rv = errno;
break;
}
@ -394,6 +378,7 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
if (rv != 0) {
free(pkgname);
prop_object_release(tmpd);
prop_object_release(curpkgd);
break;
}
if (state == XBPS_PKG_STATE_INSTALLED)
@ -408,11 +393,11 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
/*
* Package is on repo, add it into the dictionary.
*/
rv = store_dependency(trans_dict, curpkgd, repoloc);
if (rv != 0) {
if ((rv = store_dependency(trans_dict, curpkgd)) != 0) {
xbps_dbg_printf("store_dependency failed %s",
reqpkg);
free(pkgname);
prop_object_release(curpkgd);
break;
}
@ -420,7 +405,7 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
* If package was added in the missing_deps array, we
* can remove it now it has been found in current repository.
*/
rv = remove_missing_reqdep(trans_dict, reqpkg);
rv = remove_missing_reqdep(mrdeps, reqpkg);
if (rv == ENOENT) {
rv = 0;
} else if (rv == 0) {
@ -429,6 +414,7 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
xbps_dbg_printf("Removing missing dep %s "
"returned %s\n", reqpkg, strerror(rv));
free(pkgname);
prop_object_release(curpkgd);
break;
}
@ -438,8 +424,10 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
curpkg_rdeps = prop_dictionary_get(curpkgd, "run_depends");
if (curpkg_rdeps == NULL) {
free(pkgname);
prop_object_release(curpkgd);
continue;
}
prop_object_release(curpkgd);
/*
* Iterate on required pkg to find more deps.
@ -449,8 +437,8 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
pkgname, reqvers, originpkgn ? "direct" : "indirect");
free(pkgname);
if ((rv = find_repo_deps(trans_dict, repo_dict, repoloc,
NULL, curpkg_rdeps)) != 0) {
rv = find_repo_deps(trans_dict, mrdeps, NULL, curpkg_rdeps);
if (rv != 0) {
xbps_dbg_printf("Error checking %s for rundeps: %s\n",
reqpkg, strerror(rv));
break;
@ -461,100 +449,34 @@ find_repo_deps(prop_dictionary_t trans_dict, prop_dictionary_t repo_dict,
return rv;
}
struct rpool_index_data {
prop_dictionary_t transd;
prop_array_t rdeps;
const char *pkgname;
};
static int
find_repo_deps_in_pool(struct repository_pool_index *rpi, void *arg, bool *done)
{
struct rpool_index_data *rid = arg;
int rv;
(void)done;
rv = find_repo_deps(rid->transd, rpi->rpi_repod, rpi->rpi_uri,
rid->pkgname, rid->rdeps);
return rv;
}
int HIDDEN
xbps_repository_find_pkg_deps(prop_dictionary_t trans_dict,
prop_dictionary_t repo_pkg_dict)
prop_dictionary_t repo_pkgd)
{
prop_array_t pkg_rdeps, missing_rdeps;
struct rpool_index_data *rid;
const char *pkgname, *pkgver;
int rv = 0;
assert(trans_dict != NULL);
assert(repo_pkg_dict != NULL);
assert(repo_pkgd != NULL);
pkg_rdeps = prop_dictionary_get(repo_pkg_dict, "run_depends");
pkg_rdeps = prop_dictionary_get(repo_pkgd, "run_depends");
if (pkg_rdeps == NULL)
return 0;
rid = malloc(sizeof(struct rpool_index_data));
if (rid == NULL)
return ENOMEM;
prop_dictionary_get_cstring_nocopy(repo_pkg_dict, "pkgname", &pkgname);
prop_dictionary_get_cstring_nocopy(repo_pkg_dict, "pkgver", &pkgver);
if ((rv = xbps_repository_pool_init()) != 0)
goto out;
prop_dictionary_get_cstring_nocopy(repo_pkgd, "pkgname", &pkgname);
prop_dictionary_get_cstring_nocopy(repo_pkgd, "pkgver", &pkgver);
xbps_dbg_printf("Finding required dependencies for '%s':\n", pkgver);
/*
* Iterate over the repository pool and find out if we have
* all available binary packages.
*/
rid->transd = trans_dict;
rid->rdeps = pkg_rdeps;
rid->pkgname = pkgname;
/*
* This will find direct and indirect deps,
* if any of them is not there it will be added
* into the missing_deps array.
*/
rv = xbps_repository_pool_foreach(find_repo_deps_in_pool, rid);
if (rv != 0) {
xbps_dbg_printf("Error '%s' while checking rundeps!\n",
strerror(errno));
goto out;
}
/*
* If there are no missing deps, there's nothing to do.
* This will find direct and indirect deps, if any of them is not
* there it will be added into the missing_deps array.
*/
missing_rdeps = prop_dictionary_get(trans_dict, "missing_deps");
if (prop_array_count(missing_rdeps) == 0)
goto out;
/*
* Iterate one more time, but this time with missing deps
* that were found in previous pass.
*/
rid->rdeps = missing_rdeps;
rid->pkgname = NULL;
xbps_dbg_printf("Checking for missing deps in %s.\n", pkgname);
rv = xbps_repository_pool_foreach(find_repo_deps_in_pool, rid);
rv = find_repo_deps(trans_dict, missing_rdeps, pkgname, pkg_rdeps);
if (rv != 0) {
xbps_dbg_printf("Error '%s' while checking for "
"missing rundeps!\n", strerror(errno));
goto out;
xbps_dbg_printf("Error '%s' while checking rundeps!\n",
strerror(rv));
}
out:
if (rid)
free(rid);
xbps_repository_pool_release();
return rv;
}

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2009-2010 Juan Romero Pardines.
* Copyright (c) 2009-2011 Juan Romero Pardines.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -285,117 +285,33 @@ out:
return rv;
}
struct rpool_index_data {
prop_dictionary_t pkg_repod;
const char *pkgname;
const char *repo_uri;
bool newpkgfound;
};
static int
repo_find_updated_pkg_cb(struct repository_pool_index *rpi, void *arg, bool *done)
{
struct rpool_index_data *rid = arg;
prop_dictionary_t instpkgd;
const char *repover, *instver;
/*
* Get the package dictionary from current repository.
* If it's not there, pass to the next repository.
*/
rid->pkg_repod = xbps_find_pkg_in_dict_by_name(rpi->rpi_repod,
"packages", rid->pkgname);
if (rid->pkg_repod == NULL) {
if (errno && errno != ENOENT)
return errno;
xbps_dbg_printf("Package '%s' not found in repository "
"'%s'.\n", rid->pkgname, rpi->rpi_uri);
} else {
/*
* Check if version in repository is greater than
* the version currently installed.
*/
instpkgd = xbps_find_pkg_dict_installed(rid->pkgname, false);
prop_dictionary_get_cstring_nocopy(instpkgd,
"version", &instver);
prop_dictionary_get_cstring_nocopy(rid->pkg_repod,
"version", &repover);
prop_object_release(instpkgd);
if (xbps_cmpver(repover, instver) > 0) {
xbps_dbg_printf("Found '%s-%s' (installed: %s) "
"in repository '%s'.\n", rid->pkgname, repover,
instver, rpi->rpi_uri);
/*
* New package version found, exit from the loop.
*/
rid->newpkgfound = true;
rid->repo_uri = rpi->rpi_uri;
*done = true;
return 0;
}
xbps_dbg_printf("Skipping '%s-%s' (installed: %s) "
"from repository '%s'\n", rid->pkgname, repover, instver,
rpi->rpi_uri);
}
return 0;
}
int
xbps_repository_update_pkg(const char *pkgname)
{
prop_array_t unsorted;
prop_dictionary_t pkgd;
struct rpool_index_data *rid;
prop_dictionary_t pkg_repod;
int rv = 0;
assert(pkgname != NULL);
/*
* Prepare repository pool queue.
*/
if ((rv = xbps_repository_pool_init()) != 0)
return rv;
rid = calloc(1, sizeof(struct rpool_index_data));
if (rid == NULL) {
rv = errno;
goto out;
}
/*
* Check if package is not installed.
*/
pkgd = xbps_find_pkg_dict_installed(pkgname, false);
if (pkgd == NULL) {
pkg_repod = xbps_find_pkg_dict_installed(pkgname, false);
if (pkg_repod == NULL) {
rv = ENODEV;
goto out;
}
prop_object_release(pkgd);
prop_object_release(pkg_repod);
/*
* Find out if a new package version exists in repositories.
*/
rid->pkgname = pkgname;
rv = xbps_repository_pool_foreach(repo_find_updated_pkg_cb, rid);
if (rv != 0)
goto out;
/*
* No new versions found in repository pool.
*/
if (rid->newpkgfound == false) {
rv = EEXIST;
goto out;
}
/*
* Package couldn't be found in repository pool.
*/
if (rid->pkg_repod == NULL) {
rv = ENOENT;
pkg_repod = xbps_repository_pool_find_pkg(pkgname, false, true);
xbps_dbg_printf("xbps_repository_pool_find_pkg returned %s for %s\n",
strerror(errno), pkgname);
if (pkg_repod == NULL) {
rv = errno;
errno = 0;
goto out;
}
/*
@ -404,19 +320,10 @@ xbps_repository_update_pkg(const char *pkgname)
if ((rv = create_transaction_dictionary()) != 0)
goto out;
/*
* Set repository in pkg dictionary.
*/
if (!prop_dictionary_set_cstring(rid->pkg_repod,
"repository", rid->repo_uri)) {
rv = errno;
goto out;
}
/*
* Construct the dependency chain for this package.
*/
rv = xbps_repository_find_pkg_deps(trans_dict, rid->pkg_repod);
rv = xbps_repository_find_pkg_deps(trans_dict, pkg_repod);
if (rv != 0)
goto out;
@ -434,13 +341,13 @@ xbps_repository_update_pkg(const char *pkgname)
* Always set "not-installed" package state. Will be overwritten
* to its correct state later.
*/
if ((rv = set_pkg_state(rid->pkg_repod, pkgname)) != 0)
if ((rv = set_pkg_state(pkg_repod, pkgname)) != 0)
goto out;
/*
* Set trans-action obj in pkg dictionary to "update".
*/
if (!prop_dictionary_set_cstring_nocopy(rid->pkg_repod,
if (!prop_dictionary_set_cstring_nocopy(pkg_repod,
"trans-action", "update")) {
rv = errno;
goto out;
@ -450,126 +357,66 @@ xbps_repository_update_pkg(const char *pkgname)
* Added package dictionary from repository into the "unsorted"
* array in the transaction dictionary.
*/
if (!prop_array_add(unsorted, rid->pkg_repod)) {
if (!prop_array_add(unsorted, pkg_repod)) {
rv = errno;
goto out;
}
out:
if (rid)
free(rid);
xbps_repository_pool_release();
if (pkg_repod)
prop_object_release(pkg_repod);
return rv;
}
static int
repo_find_new_pkg_cb(struct repository_pool_index *rpi, void *arg, bool *done)
{
struct rpool_index_data *rid = arg;
const char *pkgver;
/*
* Finds a package dictionary from a repository pkg-index dictionary.
*/
rid->pkg_repod = xbps_find_pkg_in_dict_by_pattern(
rpi->rpi_repod, "packages", rid->pkgname);
if (rid->pkg_repod == NULL) {
if (errno && errno != ENOENT)
return errno;
} else {
prop_dictionary_get_cstring_nocopy(rid->pkg_repod,
"pkgver", &pkgver);
xbps_dbg_printf("Found package '%s' from repository %s.\n",
pkgver, rpi->rpi_uri);
rid->repo_uri = rpi->rpi_uri;
*done = true;
}
return 0;
}
int
xbps_repository_install_pkg(const char *pkg)
{
prop_dictionary_t origin_pkgrd = NULL;
prop_dictionary_t pkg_repod = NULL, origin_pkgrd = NULL;
prop_array_t unsorted;
struct rpool_index_data *rid;
const char *pkgname;
int rv = 0;
assert(pkg != NULL);
if ((rv = xbps_repository_pool_init()) != 0)
return rv;
rid = calloc(1, sizeof(struct rpool_index_data));
if (rid == NULL) {
rv = errno;
goto out;
}
/*
* Get the package dictionary from current repository.
* If it's not there, pass to the next repository.
*/
rid->pkgname = pkg;
rv = xbps_repository_pool_foreach(repo_find_new_pkg_cb, rid);
if (rv != 0)
goto out;
/*
* Package couldn't be found in repository pool... EAGAIN.
*/
if (rid->pkg_repod == NULL) {
pkg_repod = xbps_repository_pool_find_pkg(pkg, true, false);
if (pkg_repod == NULL) {
/*
* Package couldn't be found in repository pool... EAGAIN.
*/
rv = EAGAIN;
goto out;
}
/*
* Create the transaction dictionary.
*/
if ((rv = create_transaction_dictionary()) != 0)
goto out;
origin_pkgrd = prop_dictionary_copy(pkg_repod);
prop_dictionary_get_cstring_nocopy(pkg_repod, "pkgname", &pkgname);
/*
* Check that this pkg hasn't been added previously into
* the transaction.
*/
if (xbps_find_pkg_in_dict_by_pattern(trans_dict,
"unsorted_deps", pkg))
goto out;
/*
* Set repository location in pkg dictionary.
*/
if (!prop_dictionary_set_cstring(rid->pkg_repod,
"repository", rid->repo_uri)) {
rv = EINVAL;
"unsorted_deps", pkg)) {
xbps_dbg_printf("package '%s' already queued in transaction\n",
pkg);
goto out;
}
origin_pkgrd = prop_dictionary_copy(rid->pkg_repod);
prop_dictionary_get_cstring_nocopy(rid->pkg_repod, "pkgname", &pkgname);
/*
* Prepare required package dependencies and add them into the
* "unsorted" array in transaction dictionary.
*/
rv = xbps_repository_find_pkg_deps(trans_dict, rid->pkg_repod);
rv = xbps_repository_find_pkg_deps(trans_dict, origin_pkgrd);
if (rv != 0)
goto out;
/*
* Add required package dictionary into the unsorted array and
* set package state as not yet installed.
*/
unsorted = prop_dictionary_get(trans_dict, "unsorted_deps");
if (unsorted == NULL) {
rv = EINVAL;
goto out;
}
if ((rv = set_pkg_state(origin_pkgrd, pkgname)) != 0)
goto out;
@ -581,6 +428,16 @@ xbps_repository_install_pkg(const char *pkg)
rv = EINVAL;
goto out;
}
/*
* Add required package dictionary into the unsorted array and
* set package state as not yet installed.
*/
unsorted = prop_dictionary_get(trans_dict, "unsorted_deps");
if (unsorted == NULL) {
rv = EINVAL;
goto out;
}
/*
* Add the pkg dictionary from repository's index dictionary into
* the "unsorted" array in transaction dictionary.
@ -591,13 +448,13 @@ xbps_repository_install_pkg(const char *pkg)
}
out:
if (rid)
free(rid);
if (pkg_repod)
prop_object_release(pkg_repod);
if (origin_pkgrd)
prop_object_release(origin_pkgrd);
xbps_repository_pool_release();
xbps_dbg_printf("%s: returned %s for '%s'\n\n",
__func__, strerror(rv), pkg);
return rv;
}

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2009-2010 Juan Romero Pardines.
* Copyright (c) 2009-2011 Juan Romero Pardines.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -28,6 +28,7 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <xbps_api.h>
#include "xbps_api_impl.h"
@ -35,8 +36,8 @@
/**
* @file lib/repository_pool.c
* @brief Repository pool init/fini routines
* @defgroup repopool Repository pool init/fini functions
* @brief Repository pool routines
* @defgroup repopool Repository pool functions
*/
struct repository_pool {
@ -49,6 +50,7 @@ static SIMPLEQ_HEAD(rpool_head, repository_pool) rpool_queue =
static size_t repolist_refcnt;
static bool repolist_initialized;
static pthread_mutex_t mtx_refcnt = PTHREAD_MUTEX_INITIALIZER;
int
xbps_repository_pool_init(void)
@ -62,8 +64,12 @@ xbps_repository_pool_init(void)
char *plist;
int rv = 0;
xbps_dbg_printf("%s: repolist_refcnt %zu\n", __func__, repolist_refcnt);
if (repolist_initialized) {
pthread_mutex_lock(&mtx_refcnt);
repolist_refcnt++;
pthread_mutex_unlock(&mtx_refcnt);
return 0;
}
@ -156,7 +162,9 @@ xbps_repository_pool_init(void)
goto out;
repolist_initialized = true;
pthread_mutex_lock(&mtx_refcnt);
repolist_refcnt = 1;
pthread_mutex_unlock(&mtx_refcnt);
xbps_dbg_printf("%s: initialized ok.\n", __func__);
out:
if (iter)
@ -174,20 +182,28 @@ void
xbps_repository_pool_release(void)
{
struct repository_pool *rpool;
size_t cnt;
if (--repolist_refcnt > 0)
pthread_mutex_lock(&mtx_refcnt);
cnt = repolist_refcnt--;
pthread_mutex_unlock(&mtx_refcnt);
xbps_dbg_printf("%s: repolist_refcnt %zu\n", __func__, cnt);
if (cnt != 1)
return;
while ((rpool = SIMPLEQ_FIRST(&rpool_queue)) != NULL) {
SIMPLEQ_REMOVE(&rpool_queue, rpool, repository_pool, rp_entries);
xbps_dbg_printf("Unregistered repository '%s'\n",
xbps_dbg_printf("Unregistering repository '%s'...",
rpool->rpi->rpi_uri);
prop_object_release(rpool->rpi->rpi_repod);
free(rpool->rpi->rpi_uri);
free(rpool->rpi);
free(rpool);
rpool = NULL;
xbps_dbg_printf_append("done\n");
}
repolist_refcnt = 0;
repolist_initialized = false;
xbps_dbg_printf("%s: released ok.\n", __func__);
}
@ -202,7 +218,7 @@ xbps_repository_pool_foreach(
bool done = false;
if (!repolist_initialized)
return 0;
return EINVAL;
SIMPLEQ_FOREACH(rpool, &rpool_queue, rp_entries) {
rv = (*fn)(rpool->rpi, arg, &done);
@ -212,3 +228,127 @@ xbps_repository_pool_foreach(
return rv;
}
struct repo_pool_fpkg {
prop_dictionary_t pkgd;
const char *pattern;
bool bypattern;
bool newpkg_found;
};
static int
repo_find_pkg_cb(struct repository_pool_index *rpi, void *arg, bool *done)
{
struct repo_pool_fpkg *rpf = arg;
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) {
xbps_dbg_printf("Found pkg '%s' (%s)\n",
rpf->pattern, rpi->rpi_uri);
/*
* Package dictionary found, add the "repository"
* object with the URI.
*/
prop_dictionary_set_cstring(rpf->pkgd, "repository",
rpi->rpi_uri);
*done = true;
errno = 0;
return 0;
}
xbps_dbg_printf("Didn't find '%s' (%s)\n",
rpf->pattern, rpi->rpi_uri);
/* Not found */
errno = ENOENT;
return 0;
}
static int
repo_find_best_pkg_cb(struct repository_pool_index *rpi,
void *arg,
bool *done)
{
struct repo_pool_fpkg *rpf = arg;
prop_dictionary_t instpkgd;
const char *instver, *repover;
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("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);
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("Found '%s-%s' (installed: %s) "
"in repository '%s'.\n", rpf->pattern, repover,
instver, rpi->rpi_uri);
/*
* New package version found, exit from the loop.
*/
rpf->newpkg_found = true;
prop_dictionary_set_cstring(rpf->pkgd, "repository",
rpi->rpi_uri);
errno = 0;
*done = true;
return 0;
}
xbps_dbg_printf("Skipping '%s-%s' (installed: %s) "
"from repository '%s'\n", rpf->pattern, repover, instver,
rpi->rpi_uri);
errno = EEXIST;
}
return 0;
}
prop_dictionary_t
xbps_repository_pool_find_pkg(const char *pkg, bool bypattern, bool best)
{
struct repo_pool_fpkg *rpf;
prop_dictionary_t pkgd = NULL;
int rv = 0;
assert(pkg != NULL);
rpf = calloc(1, sizeof(*rpf));
if (rpf == NULL)
return NULL;
rpf->pattern = pkg;
rpf->bypattern = bypattern;
if (best)
rv = xbps_repository_pool_foreach(repo_find_best_pkg_cb, rpf);
else
rv = xbps_repository_pool_foreach(repo_find_pkg_cb, rpf);
if (rv != 0 || (rv == 0 && (errno == ENOENT || errno == EEXIST)))
goto out;
pkgd = prop_dictionary_copy(rpf->pkgd);
out:
free(rpf);
return pkgd;
}

View File

@ -67,7 +67,6 @@ xbps_sort_pkg_deps(prop_dictionary_t transd)
"continue sorting\n");
return ENOENT;
}
sorted = prop_array_create();
if (sorted == NULL)
return ENOMEM;
@ -79,7 +78,6 @@ xbps_sort_pkg_deps(prop_dictionary_t transd)
rv = EINVAL;
goto out;
}
/*
* All required deps are satisfied (already installed).
*/
@ -205,6 +203,8 @@ again:
* objects than the total number of required dependencies.
*/
if (ndeps != prop_array_count(sorted)) {
xbps_dbg_printf("wrong sorted deps cnt %zu vs %zu\n",
ndeps, prop_array_count(sorted));
rv = EINVAL;
goto out;
}
@ -215,9 +215,10 @@ again:
prop_dictionary_remove(transd, "unsorted_deps");
out:
if (rv != 0) {
if (rv != 0)
prop_dictionary_remove(transd, "packages");
prop_object_release(sorted);
}
prop_object_release(sorted);
return rv;
}