From 1a5d19dca2ef4eca1f74c606b1e7f9492b6c5df7 Mon Sep 17 00:00:00 2001 From: Juan RP Date: Sun, 29 Nov 2009 03:17:35 +0100 Subject: [PATCH] Fix and improve how missing pkg dependencies are handled from repos. - Use an array of strings to store the pkgdeps. - While adding a missing pkgdep, check if it's already in the queue and new required version is greater, in that case replace with new one. --HG-- extra : convert_revision : xtraeme%40gmail.com-20091129021735-5dqfucofny8slks2 --- bin/xbps-bin/install.c | 15 ++-- lib/depends.c | 168 ++++++++++++++++++++++++++++++++--------- lib/plist.c | 2 - 3 files changed, 138 insertions(+), 47 deletions(-) diff --git a/bin/xbps-bin/install.c b/bin/xbps-bin/install.c index 0464bc3a..a83a2a87 100644 --- a/bin/xbps-bin/install.c +++ b/bin/xbps-bin/install.c @@ -56,20 +56,17 @@ show_missing_deps(prop_dictionary_t d, const char *pkgname) static int show_missing_dep_cb(prop_object_t obj, void *arg, bool *loop_done) { - const char *pkgname, *version; + const char *reqpkg; (void)arg; (void)loop_done; - prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname); - prop_dictionary_get_cstring_nocopy(obj, "version", &version); - if (pkgname && version) { - printf(" * Missing binary package for: %s%s\n", - pkgname, version); - return 0; - } + reqpkg = prop_string_cstring_nocopy(obj); + if (reqpkg == NULL) + return EINVAL; - return EINVAL; + printf(" * Missing binary package for: %s\n", reqpkg); + return 0; } static bool diff --git a/lib/depends.c b/lib/depends.c index 53b75033..9746e7ba 100644 --- a/lib/depends.c +++ b/lib/depends.c @@ -30,7 +30,8 @@ #include -static int add_missing_reqdep(prop_dictionary_t, const char *, const char *); +static int add_missing_reqdep(prop_dictionary_t, const char *); +static int remove_missing_reqdep(prop_dictionary_t, const char *); static int find_repo_deps(prop_dictionary_t, prop_dictionary_t, const char *, prop_array_t); @@ -102,43 +103,139 @@ store_dependency(prop_dictionary_t master, prop_dictionary_t depd, } static int -add_missing_reqdep(prop_dictionary_t master, const char *pkgname, - const char *version) +add_missing_reqdep(prop_dictionary_t master, const char *reqpkg) { prop_array_t missing_rdeps; - prop_dictionary_t mdepd, tmpd; + prop_string_t reqpkg_str; + prop_object_iterator_t iter = NULL; + prop_object_t obj; + size_t idx = 0; + bool add_pkgdep, pkgfound, update_pkgdep; - assert(array != NULL); - assert(reqdep != NULL); + assert(master != NULL); + assert(reqpkg != NULL); - tmpd = xbps_find_pkg_in_dict(master, "missing_deps", pkgname); - if (tmpd == NULL) { - if (errno && errno != ENOENT) - return errno; - } else if (tmpd) - return EEXIST; + add_pkgdep = update_pkgdep = pkgfound = false; - mdepd = prop_dictionary_create(); - if (mdepd == NULL) + reqpkg_str = prop_string_create_cstring_nocopy(reqpkg); + if (reqpkg_str == NULL) return errno; missing_rdeps = prop_dictionary_get(master, "missing_deps"); - if (!prop_dictionary_set_cstring(mdepd, "pkgname", pkgname)) { - prop_object_release(mdepd); - return errno; + iter = prop_array_iterator(missing_rdeps); + if (iter == NULL) + goto out; + + while ((obj = prop_object_iterator_next(iter)) != NULL) { + const char *curdep, *curver, *pkgver; + char *curpkgnamedep = NULL, *pkgnamedep = NULL; + + assert(prop_object_type(obj) == PROP_TYPE_STRING); + curdep = prop_string_cstring_nocopy(obj); + curver = xbps_get_pkgdep_version(curdep); + pkgver = xbps_get_pkgdep_version(reqpkg); + if (curver == NULL || pkgver == NULL) + goto out; + curpkgnamedep = xbps_get_pkgdep_name(curdep); + if (curpkgnamedep == NULL) + goto out; + pkgnamedep = xbps_get_pkgdep_name(reqpkg); + if (pkgnamedep == NULL) { + free(curpkgnamedep); + goto out; + } + if (strcmp(pkgnamedep, curpkgnamedep) == 0) { + pkgfound = true; + /* + * if new dependency version is greater than current + * one, store it. + */ + DPRINTF(("Missing pkgdep name matched, curver: %s " + "newver: %s\n", curver, pkgver)); + if (xbps_cmpver(curver, pkgver) <= 0) { + add_pkgdep = false; + free(curpkgnamedep); + free(pkgnamedep); + goto out; + } + update_pkgdep = true; + } + free(curpkgnamedep); + free(pkgnamedep); + if (pkgfound) + break; + + idx++; } - if (!prop_dictionary_set_cstring(mdepd, "version", version)) { - prop_object_release(mdepd); + add_pkgdep = true; +out: + if (iter) + prop_object_iterator_release(iter); + if (update_pkgdep) + prop_array_remove(missing_rdeps, idx); + if (add_pkgdep && !xbps_add_obj_to_array(missing_rdeps, reqpkg_str)) { + prop_object_release(reqpkg_str); return errno; } - if (!xbps_add_obj_to_array(missing_rdeps, mdepd)) { - prop_object_release(mdepd); - return EINVAL; - } return 0; } +static int +remove_missing_reqdep(prop_dictionary_t master, 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(master != NULL); + assert(reqpkg != NULL); + + missing_rdeps = prop_dictionary_get(master, "missing_deps"); + iter = prop_array_iterator(missing_rdeps); + if (iter == NULL) + return errno; + + while ((obj = prop_object_iterator_next(iter)) != NULL) { + const char *curdep; + char *curpkgnamedep, *reqpkgname; + + curdep = prop_string_cstring_nocopy(obj); + curpkgnamedep = xbps_get_pkgdep_name(curdep); + if (curpkgnamedep == NULL) { + rv = errno; + goto out; + } + reqpkgname = xbps_get_pkgdep_name(reqpkg); + if (reqpkgname == NULL) { + free(curpkgnamedep); + rv = errno; + goto out; + } + if (strcmp(reqpkgname, curpkgnamedep) == 0) + found = true; + + free(curpkgnamedep); + free(reqpkgname); + if (found) + break; + idx++; + } +out: + prop_object_iterator_release(iter); + if (found) { + prop_array_remove(missing_rdeps, idx); + return 0; + } + if (rv == 0) + rv = ENOENT; + + return rv; +} + int SYMEXPORT xbps_find_deps_in_pkg(prop_dictionary_t master, prop_dictionary_t pkg) { @@ -147,8 +244,8 @@ xbps_find_deps_in_pkg(prop_dictionary_t master, prop_dictionary_t pkg) const char *pkgname; int rv = 0; + assert(master != NULL); assert(pkg != NULL); - assert(iter != NULL); pkg_rdeps = prop_dictionary_get(pkg, "run_depends"); if (pkg_rdeps == NULL) @@ -174,7 +271,7 @@ xbps_find_deps_in_pkg(prop_dictionary_t master, prop_dictionary_t pkg) if ((rv = find_repo_deps(master, rdata->rd_repod, rdata->rd_uri, pkg_rdeps)) != 0) { DPRINTF(("Error '%s' while checking rundeps!\n", - strerror(errno))); + strerror(rv))); goto out; } } @@ -194,8 +291,8 @@ xbps_find_deps_in_pkg(prop_dictionary_t master, prop_dictionary_t pkg) SIMPLEQ_FOREACH(rdata, &repodata_queue, chain) { if ((rv = find_repo_deps(master, rdata->rd_repod, rdata->rd_uri, missing_rdeps)) != 0) { - DPRINTF(("Error '%s' while checking for" - "missing rundeps!\n", strerror(errno))); + DPRINTF(("Error '%s' while checking for " + "missing rundeps!\n", strerror(rv))); goto out; } } @@ -299,7 +396,7 @@ find_repo_deps(prop_dictionary_t master, prop_dictionary_t repo, break; } - rv = add_missing_reqdep(master, pkgname, reqvers); + rv = add_missing_reqdep(master, reqpkg); if (rv != 0 && rv != EEXIST) { DPRINTF(("add missing reqdep failed %s\n", reqpkg)); @@ -313,7 +410,7 @@ find_repo_deps(prop_dictionary_t master, prop_dictionary_t repo, continue; } else { DPRINTF(("Added missing dep %s (repo: %s).\n", - pkgname, repoloc)); + reqpkg, repoloc)); free(pkgname); continue; } @@ -336,6 +433,7 @@ find_repo_deps(prop_dictionary_t master, prop_dictionary_t repo, } else if (tmpd) { rv = xbps_get_pkg_state_installed(pkgname, &state); if (rv != 0) { + free(pkgname); prop_object_release(tmpd); break; } @@ -348,32 +446,30 @@ find_repo_deps(prop_dictionary_t master, prop_dictionary_t repo, prop_object_release(tmpd); } + free(pkgname); /* * Package is on repo, add it into the dictionary. */ if ((rv = store_dependency(master, curpkgd, repoloc)) != 0) { DPRINTF(("store_dependency failed %s\n", reqpkg)); - free(pkgname); break; } - DPRINTF(("Added reqdep %s (repo: %s)\n", pkgname, repoloc)); + DPRINTF(("Added reqdep %s (repo: %s)\n", reqpkg, repoloc)); /* * If package was added in the missing_deps array, we * can remove it now it has been found in current repository. */ - rv = xbps_remove_pkg_from_dict(master, "missing_deps", pkgname); + rv = remove_missing_reqdep(master, reqpkg); if (rv == ENOENT) { rv = 0; } else if (rv == 0) { - DPRINTF(("Removed missing dep %s.\n", pkgname)); + DPRINTF(("Removed missing dep %s.\n", reqpkg)); } else { DPRINTF(("Removing missing dep %s returned %s\n", - pkgname, strerror(rv))); - free(pkgname); + reqpkg, strerror(rv))); break; } - free(pkgname); /* * If package doesn't have rundeps, pass to the next one. diff --git a/lib/plist.c b/lib/plist.c index bb395a5c..955ba4b1 100644 --- a/lib/plist.c +++ b/lib/plist.c @@ -265,8 +265,6 @@ xbps_remove_string_from_array(prop_array_t array, const char *str) return errno; while ((obj = prop_object_iterator_next(iter)) != NULL) { - if (prop_object_type(obj) != PROP_TYPE_STRING) - continue; if (prop_string_equals_cstring(obj, str)) { found = true; break;