From 7eea0f8e8eea0cc56713563a81e3ad579e7396ec Mon Sep 17 00:00:00 2001 From: Juan RP Date: Tue, 22 Dec 2009 12:37:36 +0100 Subject: [PATCH] xbps-bin(8): implemented Launchpad blueprint "arbitrary-pkgname-args". See https://blueprints.launchpad.net/xbps/+spec/arbitrary-pkgname-args. The install, update and remove targets now accept a list of package names that will be processed. --HG-- extra : convert_revision : xtraeme%40gmail.com-20091222113736-0dawl4whvtdi5dj3 --- bin/xbps-bin/defs.h | 7 +- bin/xbps-bin/install.c | 206 +++++++++++++++++------------------- bin/xbps-bin/main.c | 24 +++-- bin/xbps-bin/remove.c | 84 ++++++++++----- bin/xbps-bin/xbps-bin.8.txt | 16 +-- lib/repository_finddeps.c | 5 +- lib/repository_findpkg.c | 49 ++------- 7 files changed, 195 insertions(+), 196 deletions(-) diff --git a/bin/xbps-bin/defs.h b/bin/xbps-bin/defs.h index 780e4fae..bbc4f896 100644 --- a/bin/xbps-bin/defs.h +++ b/bin/xbps-bin/defs.h @@ -26,9 +26,12 @@ #ifndef _XBPS_BIN_DEFS_H_ #define _XBPS_BIN_DEFS_H_ -int xbps_exec_transaction(const char *, bool, bool); +int xbps_install_new_pkg(const char *); +int xbps_update_pkg(const char *); +int xbps_autoupdate_pkgs(bool); int xbps_autoremove_pkgs(bool); -int xbps_remove_installed_pkg(const char *, bool); +int xbps_exec_transaction(bool); +int xbps_remove_installed_pkgs(int, char **, bool); int xbps_check_pkg_integrity(const char *); int xbps_check_pkg_integrity_all(void); int xbps_show_pkg_deps(const char *); diff --git a/bin/xbps-bin/install.c b/bin/xbps-bin/install.c index 253824f3..32b263ee 100644 --- a/bin/xbps-bin/install.c +++ b/bin/xbps-bin/install.c @@ -35,20 +35,18 @@ struct transaction { prop_dictionary_t dict; prop_object_iterator_t iter; - const char *originpkgname; bool force; }; static int exec_transaction(struct transaction *); -static void show_missing_deps(prop_dictionary_t, const char *); +static void show_missing_deps(prop_dictionary_t); static int show_missing_dep_cb(prop_object_t, void *, bool *); static void show_package_list(prop_object_iterator_t, const char *); static void -show_missing_deps(prop_dictionary_t d, const char *pkgname) +show_missing_deps(prop_dictionary_t d) { - printf("Unable to locate some required packages for %s:\n", - pkgname); + printf("Unable to locate some required packages:\n"); (void)xbps_callback_array_iter_in_dict(d, "missing_deps", show_missing_dep_cb, NULL); } @@ -297,84 +295,95 @@ show_transaction_sizes(prop_object_iterator_t iter) } int -xbps_exec_transaction(const char *pkgname, bool force, bool update) +xbps_autoupdate_pkgs(bool force) { - struct transaction *trans; - prop_dictionary_t pkgd; - prop_array_t array; int rv = 0; - assert(pkgname != NULL); - - if (update && (strcasecmp(pkgname, "all") == 0)) { - /* - * Update all currently installed packages, aka - * "xbps-bin autoupdate". - */ - printf("Finding new packages...\n"); - if ((rv = xbps_repository_update_allpkgs()) != 0) { - if (rv == ENOENT) { - printf("No packages currently registered.\n"); - return 0; - } else if (rv == ENOPKG) { - printf("All packages are up-to-date.\n"); - return 0; - } - goto out; - } - } else { - pkgd = xbps_find_pkg_installed_from_plist(pkgname); - if (update) { - /* - * Update a single package, aka - * "xbps-bin update pkgname" - */ - printf("Finding new '%s' package...\n", pkgname); - if (pkgd) { - rv = xbps_repository_update_pkg(pkgname, pkgd); - if (rv == EEXIST) { - printf("Package '%s' is up to date.\n", - pkgname); - prop_object_release(pkgd); - return rv; - } else if (rv == ENOENT) { - printf("Package '%s' not found in " - "repository pool.\n", pkgname); - prop_object_release(pkgd); - return rv; - } else if (rv != 0) { - prop_object_release(pkgd); - return rv; - } - prop_object_release(pkgd); - } else { - printf("Package '%s' not installed.\n", - pkgname); - return rv; - } - } else { - /* - * Install a single package, aka - * "xbps-bin install pkgname" - */ - if (pkgd) { - printf("Package '%s' is already installed.\n", - pkgname); - prop_object_release(pkgd); - return rv; - } - rv = xbps_repository_install_pkg(pkgname); - if (rv != 0 && rv == EAGAIN) { - printf("Unable to locate '%s' in " - "repository pool.\n", pkgname); - return rv; - } else if (rv != 0 && rv != ENOENT) { - printf("Unexpected error: %s", strerror(errno)); - return rv; - } + /* + * Update all currently installed packages, aka + * "xbps-bin autoupdate". + */ + printf("Finding new packages...\n"); + if ((rv = xbps_repository_update_allpkgs()) != 0) { + if (rv == ENOENT) { + printf("No packages currently registered.\n"); + return 0; + } else if (rv == ENOPKG) { + printf("All packages are up-to-date.\n"); + return 0; } + return rv; } + return xbps_exec_transaction(force); +} + +int +xbps_install_new_pkg(const char *pkgname) +{ + prop_dictionary_t pkgd; + int rv = 0; + + /* + * Find a package in a repository and prepare for installation. + */ + if ((pkgd = xbps_find_pkg_installed_from_plist(pkgname))) { + printf("Package '%s' is already installed.\n", pkgname); + prop_object_release(pkgd); + return rv; + } + rv = xbps_repository_install_pkg(pkgname); + if (rv != 0 && rv == EAGAIN) { + printf("Unable to locate '%s' in " + "repository pool.\n", pkgname); + return rv; + } else if (rv != 0 && rv != ENOENT) { + printf("Unexpected error: %s", strerror(errno)); + return rv; + } + + return rv; +} + +int +xbps_update_pkg(const char *pkgname) +{ + prop_dictionary_t pkgd; + int rv = 0; + + pkgd = xbps_find_pkg_installed_from_plist(pkgname); + printf("Finding new '%s' package...\n", pkgname); + if (pkgd) { + rv = xbps_repository_update_pkg(pkgname, pkgd); + if (rv == EEXIST) { + printf("Package '%s' is up to date.\n", pkgname); + prop_object_release(pkgd); + return 0; + } else if (rv == ENOENT) { + printf("Package '%s' not found in " + "repository pool.\n", pkgname); + prop_object_release(pkgd); + return rv; + } else if (rv != 0) { + prop_object_release(pkgd); + return rv; + } + prop_object_release(pkgd); + } else { + printf("Package '%s' not installed.\n", pkgname); + return rv; + } + + return rv; +} + +int +xbps_exec_transaction(bool force) +{ + struct transaction *trans; + prop_array_t array; + int rv = 0; + trans = calloc(1, sizeof(struct transaction)); if (trans == NULL) goto out; @@ -390,28 +399,20 @@ xbps_exec_transaction(const char *pkgname, bool force, bool update) */ array = prop_dictionary_get(trans->dict, "missing_deps"); if (prop_array_count(array) > 0) { - show_missing_deps(trans->dict, pkgname); + show_missing_deps(trans->dict); goto out2; } DPRINTF(("%s", prop_dictionary_externalize(trans->dict))); - if (update) { - /* - * Sort the package transaction dictionary. - */ - if ((rv = xbps_sort_pkg_deps(trans->dict)) != 0) { - printf("Error while sorting packages: %s\n", - strerror(rv)); - goto out2; - } - } else { - if (!prop_dictionary_get_cstring_nocopy(trans->dict, - "origin", &trans->originpkgname)) { - rv = errno; - goto out2; - } + /* + * Sort the package transaction dictionary. + */ + if ((rv = xbps_sort_pkg_deps(trans->dict)) != 0) { + printf("Error while sorting packages: %s\n", strerror(rv)); + goto out2; } + /* * It's time to run the transaction! */ @@ -527,6 +528,7 @@ exec_transaction(struct transaction *trans) if (!prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver)) return errno; + prop_dictionary_get_bool(obj, "automatic-install", &autoinst); prop_dictionary_get_bool(obj, "essential", &essential); if (!prop_dictionary_get_cstring_nocopy(obj, "filename", &filename)) @@ -536,18 +538,6 @@ exec_transaction(struct transaction *trans) return errno; replaces_iter = xbps_get_array_iter_from_dict(obj, "replaces"); - /* - * Set automatic-install bool if we are updating all packages, - * and a new package is going to be installed, and - * if we updating a package required new updating dependent - * packages. - */ - if (trans->originpkgname && - strcmp(trans->originpkgname, pkgname)) - autoinst = true; - else if (!trans->originpkgname && strcmp(tract, "install") == 0) - autoinst = true; - /* * If dependency is already unpacked skip this phase. */ @@ -584,12 +574,6 @@ exec_transaction(struct transaction *trans) prop_object_release(instpkgd); return errno; } - autoinst = false; - if (!prop_dictionary_get_bool(instpkgd, - "automatic-install", &autoinst)) { - prop_object_release(instpkgd); - return errno; - } prop_object_release(instpkgd); /* diff --git a/bin/xbps-bin/main.c b/bin/xbps-bin/main.c index 3f8aaf80..ccaa4b70 100644 --- a/bin/xbps-bin/main.c +++ b/bin/xbps-bin/main.c @@ -111,7 +111,7 @@ main(int argc, char **argv) { prop_dictionary_t dict; struct sigaction sa; - int c, flags = 0, rv = 0; + int i = 0, c, flags = 0, rv = 0; bool force, verbose; force = verbose = false; @@ -187,24 +187,32 @@ main(int argc, char **argv) } else if (strcasecmp(argv[0], "install") == 0) { /* Installs a binary package and required deps. */ - if (argc != 2) + if (argc < 2) usage(); - rv = xbps_exec_transaction(argv[1], force, false); + for (i = 1; i < argc; i++) + if ((rv = xbps_install_new_pkg(argv[i])) != 0) + goto out; + + rv = xbps_exec_transaction(force); } else if (strcasecmp(argv[0], "update") == 0) { /* Update an installed package. */ - if (argc != 2) + if (argc < 2) usage(); - rv = xbps_exec_transaction(argv[1], force, true); + for (i = 1; i < argc; i++) + if ((rv = xbps_update_pkg(argv[i])) != 0) + goto out; + + rv = xbps_exec_transaction(force); } else if (strcasecmp(argv[0], "remove") == 0) { /* Removes a binary package. */ - if (argc != 2) + if (argc < 2) usage(); - rv = xbps_remove_installed_pkg(argv[1], force); + rv = xbps_remove_installed_pkgs(argc, argv, force); } else if (strcasecmp(argv[0], "show") == 0) { /* Shows info about an installed binary package. */ @@ -245,7 +253,7 @@ main(int argc, char **argv) if (argc != 1) usage(); - rv = xbps_exec_transaction("all", force, true); + rv = xbps_autoupdate_pkgs(force); } else if (strcasecmp(argv[0], "autoremove") == 0) { /* diff --git a/bin/xbps-bin/remove.c b/bin/xbps-bin/remove.c index 03070031..9df9e3e1 100644 --- a/bin/xbps-bin/remove.c +++ b/bin/xbps-bin/remove.c @@ -88,7 +88,7 @@ xbps_autoremove_pkgs(bool force) prop_object_iterator_reset(iter); printf("\n\n"); - if (!force && !xbps_noyes("Do you want to remove them?")) { + if (!force && !xbps_noyes("Do you want to continue?")) { printf("Cancelled!\n"); goto out2; } @@ -117,47 +117,79 @@ out: } int -xbps_remove_installed_pkg(const char *pkgname, bool force) +xbps_remove_installed_pkgs(int argc, char **argv, bool force) { prop_array_t reqby; prop_dictionary_t dict; + size_t cols = 0; const char *version; - int rv = 0; - bool reqby_force = false; + int i, rv = 0; + bool found = false, first = false, reqby_force = false; /* * First check if package is required by other packages. */ - dict = xbps_find_pkg_installed_from_plist(pkgname); - if (dict == NULL) { - printf("Package %s is not installed.\n", pkgname); + for (i = 1; i < argc; i++) { + dict = xbps_find_pkg_installed_from_plist(argv[i]); + if (dict == NULL) { + printf("Package %s is not installed.\n", argv[i]); + continue; + } + if (!prop_dictionary_get_cstring_nocopy(dict, "version", + &version)) + return errno; + + found = true; + reqby = prop_dictionary_get(dict, "requiredby"); + if (reqby != NULL && prop_array_count(reqby) > 0) { + printf("WARNING: %s-%s IS REQUIRED BY OTHER " + "PACKAGES!\n", argv[i], version); + reqby_force = true; + } + } + if (!found) return 0; - } - if (!prop_dictionary_get_cstring_nocopy(dict, "version", &version)) - return errno; - reqby = prop_dictionary_get(dict, "requiredby"); - if (reqby != NULL && prop_array_count(reqby) > 0) { - printf("WARNING! %s-%s is required by the following " - "packages:\n\n", pkgname, version); - (void)xbps_callback_array_iter_in_dict(dict, - "requiredby", list_strings_in_array, NULL); - printf("\n\n"); - reqby_force = true; + /* + * Show the list of going-to-be removed packages. + */ + printf("The following packages will be removed:\n\n"); + for (i = 1; i < argc; i++) { + dict = xbps_find_pkg_installed_from_plist(argv[i]); + if (dict == NULL) + continue; + prop_dictionary_get_cstring_nocopy(dict, "version", &version); + cols += strlen(argv[i]) + strlen(version) + 4; + if (cols <= 80) { + if (first == false) { + printf(" "); + first = true; + } + } else { + printf("\n "); + cols = strlen(argv[i]) + strlen(version) + 4; + } + printf("%s-%s ", argv[i], version); } - - if (!force && !xbps_noyes("Do you want to remove %s?", pkgname)) { + printf("\n\n"); + if (!force && !xbps_noyes("Do you want to continue?")) { printf("Cancelling!\n"); return 0; } if (reqby_force) - printf("Forcing %s-%s for deletion!\n", pkgname, version); + printf("Forcing removal!\n"); - printf("Removing package %s-%s ...\n", pkgname, version); - if ((rv = xbps_remove_pkg(pkgname, version, false)) != 0) { - printf("Unable to remove %s-%s (%s).\n", - pkgname, version, strerror(errno)); - return rv; + for (i = 1; i < argc; i++) { + dict = xbps_find_pkg_installed_from_plist(argv[i]); + if (dict == NULL) + continue; + prop_dictionary_get_cstring_nocopy(dict, "version", &version); + printf("Removing package %s-%s ...\n", argv[i], version); + if ((rv = xbps_remove_pkg(argv[i], version, false)) != 0) { + printf("Unable to remove %s-%s (%s).\n", + argv[i], version, strerror(errno)); + return rv; + } } return 0; diff --git a/bin/xbps-bin/xbps-bin.8.txt b/bin/xbps-bin/xbps-bin.8.txt index f957e598..cfe70e1c 100644 --- a/bin/xbps-bin/xbps-bin.8.txt +++ b/bin/xbps-bin/xbps-bin.8.txt @@ -63,16 +63,16 @@ Please note that all targets are *case insensitive*. Updates all currently installed packages to the most newer version available in repository pool. -*check 'pkgname' | 'all'*:: +*check 'pkgname(s)' | 'all'*:: Checks for integrity errors in installed packages. The checks are to found missing run-time dependencies, missing and modified package files and metadata files. If the *all* keyword is used, 'all' packages currently installed will be checked, otherwise only *pkgname*. -*install 'pkgname'*:: +*install 'pkgname(s)'*:: Install binary package "*pkgname*" by searching it in the - repository pool. The package will be 'download' (if working with + repository pool. The package(s) will be 'download' (if working with a remote repository), 'unpacked' and 'configured'. The 'unpack stage will execute the *pre-install* action on its *INSTALL* script, and unpack its files. The 'configure' stage will run the *post-install* action set on its @@ -103,8 +103,8 @@ Please note that all targets are *case insensitive*. not configured packages. If *-f* option is used, the package will be reconfigured even if its state is already *installed*. -*remove 'pkgname'*:: - Removes the installed package 'pkgname'. Its files will be removed +*remove 'pkgname(s)'*:: + Removes the installed package 'pkgname(s)'. Its files will be removed and its state will be changed to *config-files* in the package database. Configuration files, its metadata directory/files and its information in the package database are preserved. To fully remove @@ -126,9 +126,9 @@ Please note that all targets are *case insensitive*. Shows the reverse dependencies for 'pkgname'. Reverse dependencies are packages that are currently depending in 'pkgname' directly. -*update 'pkgname'*:: - Updates 'pkgname' to the most newer version available in repository - pool. This can be used if only 'pkgname' needs to be updated, unlike +*update 'pkgname(s)'*:: + Updates 'pkgname(s)' to the most newer version available in repository + pool. This can be used if only 'pkgname(s)' needs to be updated, unlike the *autoupdate* target that will update all currently installed packages. diff --git a/lib/repository_finddeps.c b/lib/repository_finddeps.c index 0bfd08b0..7c1a666f 100644 --- a/lib/repository_finddeps.c +++ b/lib/repository_finddeps.c @@ -90,7 +90,10 @@ store_dependency(prop_dictionary_t master, prop_dictionary_t depd, prop_object_release(dict); return errno; } - + if (!prop_dictionary_set_bool(dict, "automatic-install", true)) { + prop_object_release(dict); + return errno; + } /* * Add the dictionary into the array. */ diff --git a/lib/repository_findpkg.c b/lib/repository_findpkg.c index d76c0a23..9bc92505 100644 --- a/lib/repository_findpkg.c +++ b/lib/repository_findpkg.c @@ -301,7 +301,7 @@ int SYMEXPORT xbps_repository_install_pkg(const char *pkgname) { prop_dictionary_t origin_pkgrd = NULL, pkgrd = NULL; - prop_array_t pkgs_array; + prop_array_t unsorted; struct repository_pool *rpool; int rv = 0; @@ -345,49 +345,18 @@ xbps_repository_install_pkg(const char *pkgname) } origin_pkgrd = prop_dictionary_copy(pkgrd); - if (!prop_dictionary_set_cstring(trans_dict, "origin", pkgname)) { - rv = errno; - goto out; - } /* - * Check if this package needs dependencies. + * Prepare required package dependencies. */ - if (xbps_pkg_has_rundeps(pkgrd)) { - /* - * Construct the dependency chain for this package. - */ - if ((rv = xbps_repository_find_pkg_deps(trans_dict, - pkgrd)) != 0) - goto out; - /* - * Sort the dependency chain for this package. - */ - if ((rv = xbps_sort_pkg_deps(trans_dict)) != 0) - goto out; - } else { - /* - * Package has no deps, so we have to create the - * "packages" array. - */ - pkgs_array = prop_array_create(); - if (pkgs_array == NULL) { - rv = errno; - goto out; - } - if (!prop_dictionary_set(trans_dict, "packages", - pkgs_array)) { - rv = errno; - goto out; - } - } + if ((rv = xbps_repository_find_pkg_deps(trans_dict, pkgrd)) != 0) + goto out; /* - * Add required package dictionary into the packages - * dictionary. + * Add required package dictionary into the unsorted deps dictionary, + * set package state as not yet installed. */ - pkgs_array = prop_dictionary_get(trans_dict, "packages"); - if (pkgs_array == NULL || - prop_object_type(pkgs_array) != PROP_TYPE_ARRAY) { + unsorted = prop_dictionary_get(trans_dict, "unsorted_deps"); + if (unsorted == NULL) { rv = EINVAL; goto out; } @@ -399,7 +368,7 @@ xbps_repository_install_pkg(const char *pkgname) rv = errno; goto out; } - if (!prop_array_add(pkgs_array, origin_pkgrd)) + if (!prop_array_add(unsorted, origin_pkgrd)) rv = errno; out: