xbps-bin: implemented (WIP) "autoupdate" target.
Some parts in the library related to findings pkgs in repositories has been improved vastly by caching the dictionary once. Duplicated code has been added in xbps-bin/install.c, but will be fixed soon. --HG-- extra : convert_revision : 2924012a8589a2a6ecaa3863b5091049006c0ef3
This commit is contained in:
parent
951a775432
commit
9f108b4cd2
|
@ -29,5 +29,6 @@
|
|||
void xbps_install_pkg(const char *, bool, bool);
|
||||
void xbps_autoremove_pkgs(void);
|
||||
void xbps_remove_pkg(const char *, bool);
|
||||
void xbps_autoupdate_pkgs(bool);
|
||||
|
||||
#endif /* !_XBPS_BIN_DEFS_H_ */
|
||||
|
|
|
@ -65,73 +65,48 @@ show_missing_dep_cb(prop_object_t obj, void *arg, bool *loop_done)
|
|||
return EINVAL;
|
||||
}
|
||||
|
||||
void
|
||||
xbps_install_pkg(const char *pkg, bool force, bool update)
|
||||
static void
|
||||
check_pkg_hashes(prop_dictionary_t props, prop_object_iterator_t iter)
|
||||
{
|
||||
prop_object_t obj;
|
||||
const char *repoloc, *filename;
|
||||
int rv = 0;
|
||||
|
||||
printf("Checking binary package file(s) integrity...\n");
|
||||
while ((obj = prop_object_iterator_next(iter)) != NULL) {
|
||||
prop_dictionary_get_cstring_nocopy(obj, "repository", &repoloc);
|
||||
prop_dictionary_get_cstring_nocopy(obj, "filename", &filename);
|
||||
rv = xbps_check_pkg_file_hash(obj, repoloc);
|
||||
if (rv != 0 && rv != ERANGE) {
|
||||
printf("error: checking hash for %s (%s)\n",
|
||||
filename, strerror(rv));
|
||||
prop_object_release(props);
|
||||
exit(EXIT_FAILURE);
|
||||
} else if (rv != 0 && rv == ERANGE) {
|
||||
printf("Hash doesn't match for %s!\n", filename);
|
||||
prop_object_release(props);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
prop_object_iterator_reset(iter);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
show_transaction_sizes(prop_dictionary_t props, prop_object_iterator_t iter,
|
||||
const char *descr)
|
||||
{
|
||||
prop_dictionary_t props, instpkg;
|
||||
prop_array_t array;
|
||||
prop_object_t obj;
|
||||
prop_object_iterator_t iter;
|
||||
uint64_t tsize = 0, dlsize = 0, instsize = 0;
|
||||
size_t cols = 0;
|
||||
const char *repoloc, *filename, *instver, *origin;
|
||||
const char *pkgname, *version;
|
||||
char size[64];
|
||||
int rv = 0;
|
||||
bool pkg_is_dep, doup = false, first = false;
|
||||
|
||||
assert(props != NULL);
|
||||
|
||||
/*
|
||||
* Find and sort all required package dictionaries.
|
||||
*/
|
||||
printf("Finding/sorting required binary packages...\n");
|
||||
|
||||
rv = xbps_prepare_pkg(pkg);
|
||||
if (rv != 0 && rv == EAGAIN) {
|
||||
printf("Unable to locate %s in repository pool.\n", pkg);
|
||||
exit(EXIT_FAILURE);
|
||||
} else if (rv != 0 && rv != ENOENT) {
|
||||
printf("Unexpected error: %s\n", strerror(rv));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
props = xbps_get_pkg_props(pkg);
|
||||
if (props == NULL) {
|
||||
printf("error: unexistent props dictionary!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bail out if there are unresolved deps.
|
||||
*/
|
||||
array = prop_dictionary_get(props, "missing_deps");
|
||||
if (prop_array_count(array) > 0) {
|
||||
show_missing_deps(props, pkg);
|
||||
prop_object_release(props);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
prop_dictionary_get_cstring_nocopy(props, "origin", &origin);
|
||||
bool first = false;
|
||||
|
||||
/*
|
||||
* Iterate over the list of packages that are going to be
|
||||
* installed and check the file hash.
|
||||
*/
|
||||
array = prop_dictionary_get(props, "packages");
|
||||
if (array == NULL || prop_array_count(array) == 0) {
|
||||
printf("error: empty packages array!\n");
|
||||
prop_object_release(props);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
iter = prop_array_iterator(array);
|
||||
if (iter == NULL) {
|
||||
printf("error: allocating array mem! (%s)\n", strerror(errno));
|
||||
prop_object_release(props);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
while ((obj = prop_object_iterator_next(iter)) != NULL) {
|
||||
prop_dictionary_get_uint64(obj, "filename-size", &tsize);
|
||||
dlsize += tsize;
|
||||
|
@ -145,7 +120,7 @@ xbps_install_pkg(const char *pkg, bool force, bool update)
|
|||
/*
|
||||
* Show the list of packages that will be installed.
|
||||
*/
|
||||
printf("\nThe following new packages will be installed:\n\n");
|
||||
printf("\nThe following new packages will be %s:\n\n", descr);
|
||||
|
||||
while ((obj = prop_object_iterator_next(iter)) != NULL) {
|
||||
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
|
||||
|
@ -182,7 +157,71 @@ xbps_install_pkg(const char *pkg, bool force, bool update)
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
printf("Total installed size: %s\n\n", size);
|
||||
}
|
||||
|
||||
void
|
||||
xbps_install_pkg(const char *pkg, bool force, bool update)
|
||||
{
|
||||
prop_dictionary_t props, instpkg;
|
||||
prop_array_t array;
|
||||
prop_object_t obj;
|
||||
prop_object_iterator_t iter;
|
||||
const char *instver, *origin, *pkgname, *version;
|
||||
int rv = 0;
|
||||
bool pkg_is_dep, doup = false;
|
||||
|
||||
/*
|
||||
* Find and sort all required package dictionaries.
|
||||
*/
|
||||
printf("Finding/sorting required binary packages...\n");
|
||||
|
||||
rv = xbps_prepare_pkg(pkg);
|
||||
if (rv != 0 && rv == EAGAIN) {
|
||||
printf("Unable to locate %s in repository pool.\n", pkg);
|
||||
exit(EXIT_FAILURE);
|
||||
} else if (rv != 0 && rv != ENOENT) {
|
||||
printf("Unexpected error: %s\n", strerror(rv));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
props = xbps_get_pkg_props();
|
||||
if (props == NULL) {
|
||||
printf("error: unexistent props dictionary!\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bail out if there are unresolved deps.
|
||||
*/
|
||||
array = prop_dictionary_get(props, "missing_deps");
|
||||
if (prop_array_count(array) > 0) {
|
||||
show_missing_deps(props, pkg);
|
||||
prop_object_release(props);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
prop_dictionary_get_cstring_nocopy(props, "origin", &origin);
|
||||
|
||||
array = prop_dictionary_get(props, "packages");
|
||||
if (array == NULL || prop_array_count(array) == 0) {
|
||||
printf("error: empty packages array!\n");
|
||||
prop_object_release(props);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
iter = prop_array_iterator(array);
|
||||
if (iter == NULL) {
|
||||
printf("error: allocating array mem! (%s)\n", strerror(errno));
|
||||
prop_object_release(props);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
/*
|
||||
* Show download/installed size for the transaction.
|
||||
*/
|
||||
show_transaction_sizes(props, iter, "installed");
|
||||
|
||||
/*
|
||||
* Ask interactively (if -f not set).
|
||||
*/
|
||||
if (force == false) {
|
||||
if (xbps_noyes("Do you want to continue?") == false) {
|
||||
printf("Aborting!\n");
|
||||
|
@ -191,24 +230,10 @@ xbps_install_pkg(const char *pkg, bool force, bool update)
|
|||
}
|
||||
}
|
||||
|
||||
printf("Checking binary package file(s) integrity...\n");
|
||||
while ((obj = prop_object_iterator_next(iter)) != NULL) {
|
||||
prop_dictionary_get_cstring_nocopy(obj, "repository", &repoloc);
|
||||
prop_dictionary_get_cstring_nocopy(obj, "filename", &filename);
|
||||
rv = xbps_check_pkg_file_hash(obj, repoloc);
|
||||
if (rv != 0 && rv != ERANGE) {
|
||||
printf("error: checking hash for %s (%s)\n",
|
||||
filename, strerror(rv));
|
||||
prop_object_release(props);
|
||||
exit(EXIT_FAILURE);
|
||||
} else if (rv != 0 && rv == ERANGE) {
|
||||
printf("Hash doesn't match for %s!\n", filename);
|
||||
prop_object_release(props);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
prop_object_iterator_reset(iter);
|
||||
printf("\n");
|
||||
/*
|
||||
* Check the SHA256 hash for all required packages.
|
||||
*/
|
||||
check_pkg_hashes(props, iter);
|
||||
|
||||
/*
|
||||
* Install all packages, the list is already sorted.
|
||||
|
@ -276,3 +301,144 @@ xbps_install_pkg(const char *pkg, bool force, bool update)
|
|||
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
void
|
||||
xbps_autoupdate_pkgs(bool force)
|
||||
{
|
||||
prop_dictionary_t dict, props, instpkg;
|
||||
prop_array_t array;
|
||||
prop_object_t obj;
|
||||
prop_object_iterator_t iter;
|
||||
const char *pkgname, *version, *instver;
|
||||
int rv = 0;
|
||||
|
||||
dict = xbps_get_regpkgdb_dict();
|
||||
if (dict == NULL) {
|
||||
printf("No packages currently installed (%s).\n",
|
||||
strerror(errno));
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
iter = xbps_get_array_iter_from_dict(dict, "packages");
|
||||
if (iter == NULL) {
|
||||
xbps_release_regpkgdb_dict();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (xbps_prepare_repolist_data() != 0) {
|
||||
prop_object_iterator_release(iter);
|
||||
xbps_release_regpkgdb_dict();
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
while ((obj = prop_object_iterator_next(iter)) != NULL) {
|
||||
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
|
||||
rv = xbps_find_new_pkg(pkgname, obj);
|
||||
if (rv != 0)
|
||||
break;
|
||||
}
|
||||
prop_object_iterator_release(iter);
|
||||
xbps_release_regpkgdb_dict();
|
||||
|
||||
/* Sort the list of packages */
|
||||
props = xbps_get_pkg_props();
|
||||
if (props == NULL) {
|
||||
if (errno == 0) {
|
||||
printf("All packages are up-to-date.\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
printf("Error while checking for new pkgs: %s\n",
|
||||
strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
if ((rv = xbps_sort_pkg_deps(props)) != 0) {
|
||||
printf("Error while sorting packages: %s\n",
|
||||
strerror(rv));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
/* Update all packages now */
|
||||
array = prop_dictionary_get(props, "packages");
|
||||
if (array == NULL || prop_array_count(array) == 0) {
|
||||
printf("error: empty packages array!\n");
|
||||
prop_object_release(props);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
iter = prop_array_iterator(array);
|
||||
if (iter == NULL) {
|
||||
printf("error: allocating array mem! (%s)\n", strerror(errno));
|
||||
prop_object_release(props);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Show download/installed size for the transaction.
|
||||
*/
|
||||
show_transaction_sizes(props, iter, "upgraded");
|
||||
|
||||
/*
|
||||
* Ask interactively (if -f not set).
|
||||
*/
|
||||
if (force == false) {
|
||||
if (xbps_noyes("Do you want to continue?") == false) {
|
||||
printf("Aborting!\n");
|
||||
prop_object_release(props);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the SHA256 hash for all required packages.
|
||||
*/
|
||||
check_pkg_hashes(props, iter);
|
||||
|
||||
while ((obj = prop_object_iterator_next(iter)) != NULL) {
|
||||
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
|
||||
prop_dictionary_get_cstring_nocopy(obj, "version", &version);
|
||||
|
||||
/*
|
||||
* Update a package, firstly removing current package.
|
||||
*/
|
||||
instpkg = xbps_find_pkg_installed_from_plist(pkgname);
|
||||
if (instpkg == NULL) {
|
||||
printf("error: unable to find %s installed "
|
||||
"dict!\n", pkgname);
|
||||
prop_object_release(props);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
prop_dictionary_get_cstring_nocopy(instpkg,
|
||||
"version", &instver);
|
||||
printf("Updating package %s-%s to %s...\n", pkgname,
|
||||
instver, version);
|
||||
prop_object_release(instpkg);
|
||||
rv = xbps_remove_binary_pkg(pkgname, true);
|
||||
if (rv != 0) {
|
||||
printf("error: removing %s-%s (%s)\n",
|
||||
pkgname, instver, strerror(rv));
|
||||
prop_object_release(props);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unpack binary package.
|
||||
*/
|
||||
if ((rv = xbps_unpack_binary_pkg(obj)) != 0) {
|
||||
printf("error: unpacking %s-%s (%s)\n", pkgname,
|
||||
version, strerror(rv));
|
||||
prop_object_release(props);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
/*
|
||||
* Register binary package.
|
||||
*/
|
||||
if ((rv = xbps_register_pkg(obj, true, false)) != 0) {
|
||||
printf("error: registering %s-%s! (%s)\n",
|
||||
pkgname, version, strerror(rv));
|
||||
prop_object_release(props);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
prop_object_iterator_release(iter);
|
||||
xbps_release_repolist_data();
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
|
|
@ -45,7 +45,8 @@ usage(void)
|
|||
{
|
||||
printf("Usage: xbps-bin [options] [target] [arguments]\n\n"
|
||||
" Available targets:\n"
|
||||
" autoremove, files, install, list, remove, show, update\n"
|
||||
" autoremove, autoupdate, files, install, list, remove\n"
|
||||
" show, update\n"
|
||||
" Targets with arguments:\n"
|
||||
" files\t<pkgname>\n"
|
||||
" install\t<pkgname>\n"
|
||||
|
@ -63,6 +64,7 @@ usage(void)
|
|||
"\n"
|
||||
" Examples:\n"
|
||||
" $ xbps-bin autoremove\n"
|
||||
" $ xbps-bin autoupdate\n"
|
||||
" $ xbps-bin -C files klibc\n"
|
||||
" $ xbps-bin install klibc\n"
|
||||
" $ xbps-bin -r /path/to/root install klibc\n"
|
||||
|
@ -204,6 +206,15 @@ main(int argc, char **argv)
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
} else if (strcasecmp(argv[0], "autoupdate") == 0) {
|
||||
/*
|
||||
* To update all packages currently installed.
|
||||
*/
|
||||
if (argc != 1)
|
||||
usage();
|
||||
|
||||
xbps_autoupdate_pkgs(force);
|
||||
|
||||
} else if (strcasecmp(argv[0], "autoremove") == 0) {
|
||||
/*
|
||||
* Removes orphan pkgs. These packages were installed
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include <sys/queue.h>
|
||||
#define NDEBUG
|
||||
#include <assert.h>
|
||||
|
||||
|
@ -86,8 +87,17 @@ int xbps_humanize_number(char *, size_t, int64_t, const char *,
|
|||
int, int);
|
||||
|
||||
/* From lib/findpkg.c */
|
||||
struct repository_data {
|
||||
SIMPLEQ_ENTRY(repository_data) chain;
|
||||
prop_dictionary_t rd_repod;
|
||||
};
|
||||
SIMPLEQ_HEAD(, repository_data) repodata_queue;
|
||||
|
||||
int xbps_prepare_pkg(const char *);
|
||||
prop_dictionary_t xbps_get_pkg_props(const char *);
|
||||
int xbps_find_new_pkg(const char *, prop_dictionary_t);
|
||||
int xbps_prepare_repolist_data(void);
|
||||
void xbps_release_repolist_data(void);
|
||||
prop_dictionary_t xbps_get_pkg_props(void);
|
||||
|
||||
/* From lib/register.c */
|
||||
int xbps_register_pkg(prop_dictionary_t, bool, bool);
|
||||
|
@ -100,8 +110,7 @@ int xbps_requiredby_pkg_remove(const char *);
|
|||
int xbps_unpack_binary_pkg(prop_dictionary_t);
|
||||
|
||||
/* From lib/depends.c */
|
||||
int xbps_find_deps_in_pkg(prop_dictionary_t, prop_dictionary_t,
|
||||
prop_object_iterator_t);
|
||||
int xbps_find_deps_in_pkg(prop_dictionary_t, prop_dictionary_t);
|
||||
|
||||
/* From lib/plist.c */
|
||||
bool xbps_add_obj_to_dict(prop_dictionary_t, prop_object_t,
|
||||
|
@ -121,6 +130,8 @@ prop_dictionary_t xbps_find_pkg_from_plist(const char *, const char *);
|
|||
prop_dictionary_t xbps_find_pkg_installed_from_plist(const char *);
|
||||
bool xbps_find_string_in_array(prop_array_t, const char *);
|
||||
|
||||
prop_dictionary_t xbps_get_regpkgdb_dict(void);
|
||||
void xbps_release_regpkgdb_dict(void);
|
||||
prop_object_iterator_t xbps_get_array_iter_from_dict(prop_dictionary_t,
|
||||
const char *);
|
||||
|
||||
|
|
|
@ -45,9 +45,7 @@ store_dependency(prop_dictionary_t master, prop_dictionary_t origind,
|
|||
{
|
||||
prop_dictionary_t dict;
|
||||
prop_array_t array;
|
||||
size_t dirdepscnt = 0, indirdepscnt = 0;
|
||||
const char *reqbyname, *repoloc, *originpkg;
|
||||
bool indirectdep = false;
|
||||
const char *reqbyname, *repoloc;
|
||||
|
||||
assert(origind != NULL);
|
||||
assert(depd != NULL);
|
||||
|
@ -59,25 +57,6 @@ store_dependency(prop_dictionary_t master, prop_dictionary_t origind,
|
|||
prop_dictionary_get_cstring_nocopy(origind, "pkgname", &reqbyname);
|
||||
prop_dictionary_get_cstring_nocopy(repod, "location-local", &repoloc);
|
||||
|
||||
/*
|
||||
* Required dependency is not installed. Check if it's
|
||||
* already registered in the chain, and update some objects
|
||||
* or add the object into array otherwise.
|
||||
*/
|
||||
prop_dictionary_get_cstring_nocopy(master, "origin", &originpkg);
|
||||
if (strcmp(originpkg, reqbyname)) {
|
||||
indirectdep = true;
|
||||
prop_dictionary_get_uint32(master, "indirectdeps_count",
|
||||
&indirdepscnt);
|
||||
prop_dictionary_set_uint32(master, "indirectdeps_count",
|
||||
++indirdepscnt);
|
||||
} else {
|
||||
prop_dictionary_get_uint32(master, "directdeps_count",
|
||||
&dirdepscnt);
|
||||
prop_dictionary_set_uint32(master, "directdeps_count",
|
||||
++dirdepscnt);
|
||||
}
|
||||
|
||||
dict = prop_dictionary_copy(depd);
|
||||
if (dict == NULL)
|
||||
return errno;
|
||||
|
@ -91,7 +70,6 @@ store_dependency(prop_dictionary_t master, prop_dictionary_t origind,
|
|||
* Add required objects into package dep's dictionary.
|
||||
*/
|
||||
prop_dictionary_set_cstring(dict, "repository", repoloc);
|
||||
prop_dictionary_set_bool(dict, "indirect_dep", indirectdep);
|
||||
/*
|
||||
* Remove some unneeded objects.
|
||||
*/
|
||||
|
@ -144,16 +122,12 @@ add_missing_reqdep(prop_dictionary_t master, const char *pkgname,
|
|||
}
|
||||
|
||||
int
|
||||
xbps_find_deps_in_pkg(prop_dictionary_t master, prop_dictionary_t pkg,
|
||||
prop_object_iterator_t iter)
|
||||
xbps_find_deps_in_pkg(prop_dictionary_t master, prop_dictionary_t pkg)
|
||||
{
|
||||
prop_array_t pkg_rdeps, missing_rdeps;
|
||||
prop_dictionary_t repod;
|
||||
prop_object_t obj;
|
||||
char *plist;
|
||||
struct repository_data *rdata;
|
||||
int rv = 0;
|
||||
|
||||
assert(pkg_props != NULL);
|
||||
assert(pkg != NULL);
|
||||
assert(iter != NULL);
|
||||
|
||||
|
@ -165,35 +139,20 @@ xbps_find_deps_in_pkg(prop_dictionary_t master, prop_dictionary_t pkg,
|
|||
* Iterate over the repository pool and find out if we have
|
||||
* all available binary packages.
|
||||
*/
|
||||
while ((obj = prop_object_iterator_next(iter)) != NULL) {
|
||||
plist =
|
||||
xbps_get_pkg_index_plist(prop_string_cstring_nocopy(obj));
|
||||
if (plist == NULL)
|
||||
return EINVAL;
|
||||
|
||||
repod = prop_dictionary_internalize_from_file(plist);
|
||||
if (repod == NULL) {
|
||||
free(plist);
|
||||
return errno;
|
||||
}
|
||||
free(plist);
|
||||
|
||||
SIMPLEQ_FOREACH(rdata, &repodata_queue, chain) {
|
||||
/*
|
||||
* This will find direct and indirect deps,
|
||||
* if any of them is not there it will be added
|
||||
* into the missing_deps array.
|
||||
*/
|
||||
rv = find_repo_deps(master, repod, pkg, pkg_rdeps);
|
||||
rv = find_repo_deps(master, rdata->rd_repod, pkg, pkg_rdeps);
|
||||
if (rv != 0) {
|
||||
if (rv == ENOENT) {
|
||||
rv = 0;
|
||||
prop_object_release(repod);
|
||||
continue;
|
||||
}
|
||||
prop_object_release(repod);
|
||||
break;
|
||||
}
|
||||
prop_object_release(repod);
|
||||
}
|
||||
|
||||
missing_rdeps = prop_dictionary_get(master, "missing_deps");
|
||||
|
@ -204,27 +163,10 @@ xbps_find_deps_in_pkg(prop_dictionary_t master, prop_dictionary_t pkg,
|
|||
* If there are missing deps, iterate one more time
|
||||
* just in case that indirect deps weren't found.
|
||||
*/
|
||||
prop_object_iterator_reset(iter);
|
||||
while ((obj = prop_object_iterator_next(iter)) != NULL) {
|
||||
plist =
|
||||
xbps_get_pkg_index_plist(prop_string_cstring_nocopy(obj));
|
||||
if (plist == NULL)
|
||||
return EINVAL;
|
||||
|
||||
repod = prop_dictionary_internalize_from_file(plist);
|
||||
if (repod == NULL) {
|
||||
free(plist);
|
||||
return errno;
|
||||
}
|
||||
free(plist);
|
||||
|
||||
rv = find_repo_missing_deps(master, repod, pkg);
|
||||
if (rv != 0 && rv != ENOENT) {
|
||||
prop_object_release(repod);
|
||||
SIMPLEQ_FOREACH(rdata, &repodata_queue, chain) {
|
||||
rv = find_repo_missing_deps(master, rdata->rd_repod, pkg);
|
||||
if (rv != 0 && rv != ENOENT)
|
||||
return rv;
|
||||
}
|
||||
|
||||
prop_object_release(repod);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
246
lib/findpkg.c
246
lib/findpkg.c
|
@ -34,18 +34,20 @@
|
|||
|
||||
#include <xbps_api.h>
|
||||
|
||||
static int create_pkg_props_dictionary(const char *);
|
||||
|
||||
static prop_dictionary_t pkg_props;
|
||||
|
||||
static int
|
||||
create_pkg_props_dictionary(const char *pkgname)
|
||||
create_pkg_props_dictionary(void)
|
||||
{
|
||||
prop_array_t unsorted, missing;
|
||||
int rv = 0;
|
||||
static bool pkg_props_avail;
|
||||
|
||||
assert(pkgname != NULL);
|
||||
|
||||
if (pkg_props_avail)
|
||||
return 0;
|
||||
|
||||
pkg_props = prop_dictionary_create();
|
||||
if (pkg_props == NULL)
|
||||
return ENOMEM;
|
||||
|
@ -71,7 +73,7 @@ create_pkg_props_dictionary(const char *pkgname)
|
|||
goto fail3;
|
||||
}
|
||||
|
||||
prop_dictionary_set_cstring_nocopy(pkg_props, "origin", pkgname);
|
||||
pkg_props_avail = true;
|
||||
|
||||
return rv;
|
||||
|
||||
|
@ -86,32 +88,37 @@ fail:
|
|||
}
|
||||
|
||||
prop_dictionary_t
|
||||
xbps_get_pkg_props(const char *pkgname)
|
||||
xbps_get_pkg_props(void)
|
||||
{
|
||||
prop_string_t origin;
|
||||
|
||||
if (pkg_props == NULL || prop_dictionary_count(pkg_props) == 0)
|
||||
return NULL;
|
||||
|
||||
origin = prop_dictionary_get(pkg_props, "origin");
|
||||
if (!prop_string_equals_cstring(origin, pkgname))
|
||||
return NULL;
|
||||
|
||||
return prop_dictionary_copy(pkg_props);
|
||||
}
|
||||
|
||||
int
|
||||
xbps_prepare_pkg(const char *pkgname)
|
||||
xbps_prepare_repolist_data(void)
|
||||
{
|
||||
prop_dictionary_t repod = NULL, repolistd, pkgrd = NULL;
|
||||
prop_array_t array, pkgs_array;
|
||||
prop_dictionary_t dict = NULL;
|
||||
prop_array_t array;
|
||||
prop_object_t obj;
|
||||
prop_object_iterator_t repolist_iter;
|
||||
const char *repoloc, *rootdir;
|
||||
prop_object_iterator_t iter;
|
||||
struct repository_data *rdata;
|
||||
const char *rootdir;
|
||||
char *plist;
|
||||
int rv = 0;
|
||||
static bool repodata_init;
|
||||
|
||||
assert(pkgname != NULL);
|
||||
if (repodata_init == false) {
|
||||
SIMPLEQ_INIT(&repodata_queue);
|
||||
repodata_init = true;
|
||||
}
|
||||
|
||||
rdata = malloc(sizeof(struct repository_data));
|
||||
if (rdata == NULL) {
|
||||
rv = errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rootdir = xbps_get_rootdir();
|
||||
if (rootdir == NULL)
|
||||
|
@ -119,79 +126,201 @@ xbps_prepare_pkg(const char *pkgname)
|
|||
|
||||
plist = xbps_xasprintf("%s/%s/%s", rootdir,
|
||||
XBPS_META_PATH, XBPS_REPOLIST);
|
||||
if (plist == NULL)
|
||||
return EINVAL;
|
||||
if (plist == NULL) {
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
repolistd = prop_dictionary_internalize_from_file(plist);
|
||||
if (repolistd == NULL) {
|
||||
dict = prop_dictionary_internalize_from_file(plist);
|
||||
if (dict == NULL) {
|
||||
free(plist);
|
||||
return EINVAL;
|
||||
rv = errno;
|
||||
goto out;
|
||||
}
|
||||
free(plist);
|
||||
|
||||
array = prop_dictionary_get(repolistd, "repository-list");
|
||||
array = prop_dictionary_get(dict, "repository-list");
|
||||
if (array == NULL) {
|
||||
prop_object_release(repolistd);
|
||||
return EINVAL;
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
repolist_iter = prop_array_iterator(array);
|
||||
if (repolist_iter == NULL) {
|
||||
prop_object_release(repolistd);
|
||||
return ENOMEM;
|
||||
iter = prop_array_iterator(array);
|
||||
if (iter == NULL) {
|
||||
rv = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
while ((obj = prop_object_iterator_next(repolist_iter)) != NULL) {
|
||||
while ((obj = prop_object_iterator_next(iter)) != NULL) {
|
||||
/*
|
||||
* Iterate over the repository pool and find out if we have
|
||||
* the binary package.
|
||||
* Iterate over the repository pool and add the dictionary
|
||||
* for current repository into the queue.
|
||||
*/
|
||||
plist =
|
||||
xbps_get_pkg_index_plist(prop_string_cstring_nocopy(obj));
|
||||
if (plist == NULL)
|
||||
return EINVAL;
|
||||
if (plist == NULL) {
|
||||
rv = EINVAL;
|
||||
goto out2;
|
||||
}
|
||||
|
||||
repod = prop_dictionary_internalize_from_file(plist);
|
||||
if (repod == NULL) {
|
||||
rdata->rd_repod = prop_dictionary_internalize_from_file(plist);
|
||||
if (rdata->rd_repod == NULL) {
|
||||
free(plist);
|
||||
return errno;
|
||||
rv = errno;
|
||||
goto out2;
|
||||
}
|
||||
free(plist);
|
||||
SIMPLEQ_INSERT_TAIL(&repodata_queue, rdata, chain);
|
||||
}
|
||||
|
||||
out2:
|
||||
prop_object_iterator_release(iter);
|
||||
out:
|
||||
prop_object_release(dict);
|
||||
if (rv != 0)
|
||||
xbps_release_repolist_data();
|
||||
|
||||
return rv;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
xbps_release_repolist_data(void)
|
||||
{
|
||||
struct repository_data *rdata;
|
||||
|
||||
while ((rdata = SIMPLEQ_FIRST(&repodata_queue)) != NULL) {
|
||||
SIMPLEQ_REMOVE(&repodata_queue, rdata, repository_data, chain);
|
||||
prop_object_release(rdata->rd_repod);
|
||||
free(rdata);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
xbps_find_new_pkg(const char *pkgname, prop_dictionary_t instpkg)
|
||||
{
|
||||
prop_dictionary_t pkgrd = NULL;
|
||||
prop_array_t unsorted;
|
||||
struct repository_data *rdata;
|
||||
const char *repoloc, *repover, *instver;
|
||||
int rv = 0;
|
||||
|
||||
assert(pkgname != NULL);
|
||||
assert(instpkg != NULL);
|
||||
|
||||
SIMPLEQ_FOREACH(rdata, &repodata_queue, chain) {
|
||||
/*
|
||||
* Get the package dictionary from current repository.
|
||||
* If it's not there, pass to the next repository.
|
||||
*/
|
||||
pkgrd = xbps_find_pkg_in_dict(repod, "packages", pkgname);
|
||||
if (pkgrd == NULL) {
|
||||
prop_object_release(repod);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
prop_object_iterator_reset(repolist_iter);
|
||||
pkgrd = xbps_find_pkg_in_dict(rdata->rd_repod,
|
||||
"packages", pkgname);
|
||||
if (pkgrd != NULL) {
|
||||
/*
|
||||
* Check if installed version is >= than the
|
||||
* one available in current repository.
|
||||
*/
|
||||
prop_dictionary_get_cstring_nocopy(instpkg,
|
||||
"version", &instver);
|
||||
prop_dictionary_get_cstring_nocopy(pkgrd,
|
||||
"version", &repover);
|
||||
if (xbps_cmpver_versions(instver, repover) >= 0)
|
||||
goto out;
|
||||
|
||||
if (pkgrd == NULL) {
|
||||
rv = EAGAIN;
|
||||
goto out2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pkgrd == NULL)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Create master pkg dictionary.
|
||||
*/
|
||||
if ((rv = create_pkg_props_dictionary(pkgname)) != 0)
|
||||
if ((rv = create_pkg_props_dictionary()) != 0)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Set repository in pkg dictionary.
|
||||
*/
|
||||
if (!prop_dictionary_get_cstring_nocopy(repod,
|
||||
if (!prop_dictionary_get_cstring_nocopy(rdata->rd_repod,
|
||||
"location-local", &repoloc)) {
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
prop_dictionary_set_cstring(pkgrd, "repository", repoloc);
|
||||
|
||||
/*
|
||||
* Construct the dependency chain for this package.
|
||||
*/
|
||||
if ((rv = xbps_find_deps_in_pkg(pkg_props, pkgrd)) != 0)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Add required package dictionary into the packages
|
||||
* dictionary.
|
||||
*/
|
||||
unsorted = prop_dictionary_get(pkg_props, "unsorted_deps");
|
||||
if (unsorted == NULL) {
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!prop_array_add(unsorted, pkgrd))
|
||||
rv = errno;
|
||||
|
||||
out:
|
||||
if (rv != 0)
|
||||
xbps_release_repolist_data();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
xbps_prepare_pkg(const char *pkgname)
|
||||
{
|
||||
prop_dictionary_t pkgrd = NULL;
|
||||
prop_array_t pkgs_array;
|
||||
struct repository_data *rdata;
|
||||
const char *repoloc;
|
||||
int rv = 0;
|
||||
|
||||
assert(pkgname != NULL);
|
||||
|
||||
if ((rv = xbps_prepare_repolist_data()) != 0)
|
||||
return rv;
|
||||
|
||||
SIMPLEQ_FOREACH(rdata, &repodata_queue, chain) {
|
||||
/*
|
||||
* Get the package dictionary from current repository.
|
||||
* If it's not there, pass to the next repository.
|
||||
*/
|
||||
pkgrd = xbps_find_pkg_in_dict(rdata->rd_repod,
|
||||
"packages", pkgname);
|
||||
if (pkgrd != NULL)
|
||||
break;
|
||||
}
|
||||
if (pkgrd == NULL) {
|
||||
rv = EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create master pkg dictionary.
|
||||
*/
|
||||
if ((rv = create_pkg_props_dictionary()) != 0)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Set repository in pkg dictionary.
|
||||
*/
|
||||
if (!prop_dictionary_get_cstring_nocopy(rdata->rd_repod,
|
||||
"location-local", &repoloc)) {
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
prop_dictionary_set_cstring(pkgrd, "repository", repoloc);
|
||||
prop_dictionary_set_cstring(pkgrd, "origin", pkgname);
|
||||
|
||||
/*
|
||||
* Check if this package needs dependencies.
|
||||
*/
|
||||
|
@ -199,8 +328,7 @@ xbps_prepare_pkg(const char *pkgname)
|
|||
/*
|
||||
* Construct the dependency chain for this package.
|
||||
*/
|
||||
if ((rv = xbps_find_deps_in_pkg(pkg_props, pkgrd,
|
||||
repolist_iter)) != 0)
|
||||
if ((rv = xbps_find_deps_in_pkg(pkg_props, pkgrd)) != 0)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
|
@ -218,7 +346,8 @@ xbps_prepare_pkg(const char *pkgname)
|
|||
rv = errno;
|
||||
goto out;
|
||||
}
|
||||
if (!prop_dictionary_set(pkg_props, "packages", pkgs_array)) {
|
||||
if (!prop_dictionary_set(pkg_props, "packages",
|
||||
pkgs_array)) {
|
||||
rv = errno;
|
||||
goto out;
|
||||
}
|
||||
|
@ -235,18 +364,11 @@ xbps_prepare_pkg(const char *pkgname)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (!prop_array_add(pkgs_array, pkgrd)) {
|
||||
if (!prop_array_add(pkgs_array, pkgrd))
|
||||
rv = errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
prop_dictionary_remove(pkg_props, "unsorted_deps");
|
||||
|
||||
out:
|
||||
prop_object_release(repod);
|
||||
out2:
|
||||
prop_object_iterator_release(repolist_iter);
|
||||
prop_object_release(repolistd);
|
||||
xbps_release_repolist_data();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
|
47
lib/plist.c
47
lib/plist.c
|
@ -33,6 +33,8 @@
|
|||
|
||||
#include <xbps_api.h>
|
||||
|
||||
static prop_dictionary_t regpkgdb_dict;
|
||||
|
||||
bool
|
||||
xbps_add_obj_to_dict(prop_dictionary_t dict, prop_object_t obj,
|
||||
const char *key)
|
||||
|
@ -160,18 +162,14 @@ xbps_find_pkg_from_plist(const char *plist, const char *pkgname)
|
|||
prop_dictionary_t
|
||||
xbps_find_pkg_installed_from_plist(const char *pkgname)
|
||||
{
|
||||
prop_dictionary_t pkgd;
|
||||
const char *rootdir;
|
||||
char *plist;
|
||||
prop_dictionary_t instd, pkgd;
|
||||
|
||||
rootdir = xbps_get_rootdir();
|
||||
plist = xbps_xasprintf("%s/%s/%s", rootdir,
|
||||
XBPS_META_PATH, XBPS_REGPKGDB);
|
||||
if (plist == NULL)
|
||||
instd = xbps_get_regpkgdb_dict();
|
||||
if (instd == NULL)
|
||||
return NULL;
|
||||
|
||||
pkgd = xbps_find_pkg_from_plist(plist, pkgname);
|
||||
free(plist);
|
||||
pkgd = xbps_find_pkg_in_dict(instd, "packages", pkgname);
|
||||
xbps_release_regpkgdb_dict();
|
||||
|
||||
return pkgd;
|
||||
}
|
||||
|
@ -202,6 +200,37 @@ xbps_find_pkg_in_dict(prop_dictionary_t dict, const char *key,
|
|||
return obj;
|
||||
}
|
||||
|
||||
prop_dictionary_t
|
||||
xbps_get_regpkgdb_dict(void)
|
||||
{
|
||||
const char *rootdir;
|
||||
char *plist;
|
||||
|
||||
if (regpkgdb_dict == NULL) {
|
||||
rootdir = xbps_get_rootdir();
|
||||
plist = xbps_xasprintf("%s/%s/%s", rootdir,
|
||||
XBPS_META_PATH, XBPS_REGPKGDB);
|
||||
if (plist == NULL)
|
||||
return NULL;
|
||||
|
||||
regpkgdb_dict = prop_dictionary_internalize_from_file(plist);
|
||||
if (regpkgdb_dict == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return prop_dictionary_copy(regpkgdb_dict);
|
||||
}
|
||||
|
||||
void
|
||||
xbps_release_regpkgdb_dict(void)
|
||||
{
|
||||
if (regpkgdb_dict == NULL)
|
||||
return;
|
||||
|
||||
prop_object_release(regpkgdb_dict);
|
||||
regpkgdb_dict = NULL;
|
||||
}
|
||||
|
||||
bool
|
||||
xbps_find_string_in_array(prop_array_t array, const char *val)
|
||||
{
|
||||
|
|
|
@ -64,7 +64,7 @@ xbps_sort_pkg_deps(prop_dictionary_t chaindeps)
|
|||
prop_object_t obj, obj2;
|
||||
prop_object_iterator_t iter, iter2;
|
||||
struct sorted_dependency *sdep;
|
||||
size_t indirdepscnt = 0, dirdepscnt = 0, rundepscnt = 0, cnt = 0;
|
||||
size_t ndeps = 0, rundepscnt = 0, cnt = 0;
|
||||
const char *pkgname;
|
||||
char *curpkgnamedep;
|
||||
int rv = 0;
|
||||
|
@ -84,10 +84,7 @@ xbps_sort_pkg_deps(prop_dictionary_t chaindeps)
|
|||
return 0;
|
||||
}
|
||||
|
||||
prop_dictionary_get_uint32(chaindeps, "indirectdeps_count",
|
||||
&indirdepscnt);
|
||||
prop_dictionary_get_uint32(chaindeps, "directdeps_count",
|
||||
&dirdepscnt);
|
||||
ndeps = prop_array_count(unsorted);
|
||||
unsorted = prop_dictionary_get(chaindeps, "unsorted_deps");
|
||||
|
||||
iter = prop_array_iterator(unsorted);
|
||||
|
@ -159,7 +156,7 @@ again:
|
|||
}
|
||||
|
||||
/* Iterate until all deps are processed. */
|
||||
if (cnt < dirdepscnt + indirdepscnt) {
|
||||
if (cnt < ndeps) {
|
||||
prop_object_iterator_reset(iter);
|
||||
goto again;
|
||||
}
|
||||
|
@ -179,14 +176,16 @@ again:
|
|||
* Sanity check that the array contains the same number of
|
||||
* objects than the total number of required dependencies.
|
||||
*/
|
||||
cnt = dirdepscnt + indirdepscnt;
|
||||
if (cnt != prop_array_count(sorted)) {
|
||||
if (ndeps != prop_array_count(sorted)) {
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!prop_dictionary_set(chaindeps, "packages", sorted))
|
||||
rv = EINVAL;
|
||||
|
||||
prop_dictionary_remove(chaindeps, "unsorted_deps");
|
||||
|
||||
out:
|
||||
/*
|
||||
* Release resources used by temporary sorting.
|
||||
|
|
|
@ -125,7 +125,7 @@ xbps_check_is_installed_pkg(const char *pkg)
|
|||
dict = xbps_find_pkg_installed_from_plist(pkgname);
|
||||
if (dict == NULL) {
|
||||
free(pkgname);
|
||||
return -1; /* not installed */
|
||||
return -2; /* not installed */
|
||||
}
|
||||
|
||||
/* Get version from installed package */
|
||||
|
|
Loading…
Reference in New Issue