diff --git a/include/xbps_api.h b/include/xbps_api.h index a84c59bc..f7db8e51 100644 --- a/include/xbps_api.h +++ b/include/xbps_api.h @@ -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 */ diff --git a/lib/repository_finddeps.c b/lib/repository_finddeps.c index 8a8d8ef4..bbb4d5da 100644 --- a/lib/repository_finddeps.c +++ b/lib/repository_finddeps.c @@ -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; } diff --git a/lib/repository_findpkg.c b/lib/repository_findpkg.c index a124573c..4bec6fe0 100644 --- a/lib/repository_findpkg.c +++ b/lib/repository_findpkg.c @@ -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; } diff --git a/lib/repository_pool.c b/lib/repository_pool.c index 91dec27b..b3a4e404 100644 --- a/lib/repository_pool.c +++ b/lib/repository_pool.c @@ -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 #include #include +#include #include #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; +} diff --git a/lib/sortdeps.c b/lib/sortdeps.c index 2af1dc01..8404d213 100644 --- a/lib/sortdeps.c +++ b/lib/sortdeps.c @@ -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; }