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
This commit is contained in:
Juan RP
2009-12-22 12:37:36 +01:00
parent 009c2131fc
commit 7eea0f8e8e
7 changed files with 195 additions and 196 deletions

View File

@@ -26,9 +26,12 @@
#ifndef _XBPS_BIN_DEFS_H_ #ifndef _XBPS_BIN_DEFS_H_
#define _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_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(const char *);
int xbps_check_pkg_integrity_all(void); int xbps_check_pkg_integrity_all(void);
int xbps_show_pkg_deps(const char *); int xbps_show_pkg_deps(const char *);

View File

@@ -35,20 +35,18 @@
struct transaction { struct transaction {
prop_dictionary_t dict; prop_dictionary_t dict;
prop_object_iterator_t iter; prop_object_iterator_t iter;
const char *originpkgname;
bool force; bool force;
}; };
static int exec_transaction(struct transaction *); 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 int show_missing_dep_cb(prop_object_t, void *, bool *);
static void show_package_list(prop_object_iterator_t, const char *); static void show_package_list(prop_object_iterator_t, const char *);
static void 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", printf("Unable to locate some required packages:\n");
pkgname);
(void)xbps_callback_array_iter_in_dict(d, "missing_deps", (void)xbps_callback_array_iter_in_dict(d, "missing_deps",
show_missing_dep_cb, NULL); show_missing_dep_cb, NULL);
} }
@@ -297,84 +295,95 @@ show_transaction_sizes(prop_object_iterator_t iter)
} }
int 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; int rv = 0;
assert(pkgname != NULL); /*
* Update all currently installed packages, aka
if (update && (strcasecmp(pkgname, "all") == 0)) { * "xbps-bin autoupdate".
/* */
* Update all currently installed packages, aka printf("Finding new packages...\n");
* "xbps-bin autoupdate". if ((rv = xbps_repository_update_allpkgs()) != 0) {
*/ if (rv == ENOENT) {
printf("Finding new packages...\n"); printf("No packages currently registered.\n");
if ((rv = xbps_repository_update_allpkgs()) != 0) { return 0;
if (rv == ENOENT) { } else if (rv == ENOPKG) {
printf("No packages currently registered.\n"); printf("All packages are up-to-date.\n");
return 0; 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;
}
} }
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)); trans = calloc(1, sizeof(struct transaction));
if (trans == NULL) if (trans == NULL)
goto out; goto out;
@@ -390,28 +399,20 @@ xbps_exec_transaction(const char *pkgname, bool force, bool update)
*/ */
array = prop_dictionary_get(trans->dict, "missing_deps"); array = prop_dictionary_get(trans->dict, "missing_deps");
if (prop_array_count(array) > 0) { if (prop_array_count(array) > 0) {
show_missing_deps(trans->dict, pkgname); show_missing_deps(trans->dict);
goto out2; goto out2;
} }
DPRINTF(("%s", prop_dictionary_externalize(trans->dict))); DPRINTF(("%s", prop_dictionary_externalize(trans->dict)));
if (update) { /*
/* * Sort the package transaction dictionary.
* Sort the package transaction dictionary. */
*/ if ((rv = xbps_sort_pkg_deps(trans->dict)) != 0) {
if ((rv = xbps_sort_pkg_deps(trans->dict)) != 0) { printf("Error while sorting packages: %s\n", strerror(rv));
printf("Error while sorting packages: %s\n", goto out2;
strerror(rv));
goto out2;
}
} else {
if (!prop_dictionary_get_cstring_nocopy(trans->dict,
"origin", &trans->originpkgname)) {
rv = errno;
goto out2;
}
} }
/* /*
* It's time to run the transaction! * It's time to run the transaction!
*/ */
@@ -527,6 +528,7 @@ exec_transaction(struct transaction *trans)
if (!prop_dictionary_get_cstring_nocopy(obj, if (!prop_dictionary_get_cstring_nocopy(obj,
"pkgver", &pkgver)) "pkgver", &pkgver))
return errno; return errno;
prop_dictionary_get_bool(obj, "automatic-install", &autoinst);
prop_dictionary_get_bool(obj, "essential", &essential); prop_dictionary_get_bool(obj, "essential", &essential);
if (!prop_dictionary_get_cstring_nocopy(obj, if (!prop_dictionary_get_cstring_nocopy(obj,
"filename", &filename)) "filename", &filename))
@@ -536,18 +538,6 @@ exec_transaction(struct transaction *trans)
return errno; return errno;
replaces_iter = xbps_get_array_iter_from_dict(obj, "replaces"); 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. * If dependency is already unpacked skip this phase.
*/ */
@@ -584,12 +574,6 @@ exec_transaction(struct transaction *trans)
prop_object_release(instpkgd); prop_object_release(instpkgd);
return errno; return errno;
} }
autoinst = false;
if (!prop_dictionary_get_bool(instpkgd,
"automatic-install", &autoinst)) {
prop_object_release(instpkgd);
return errno;
}
prop_object_release(instpkgd); prop_object_release(instpkgd);
/* /*

View File

@@ -111,7 +111,7 @@ main(int argc, char **argv)
{ {
prop_dictionary_t dict; prop_dictionary_t dict;
struct sigaction sa; struct sigaction sa;
int c, flags = 0, rv = 0; int i = 0, c, flags = 0, rv = 0;
bool force, verbose; bool force, verbose;
force = verbose = false; force = verbose = false;
@@ -187,24 +187,32 @@ main(int argc, char **argv)
} else if (strcasecmp(argv[0], "install") == 0) { } else if (strcasecmp(argv[0], "install") == 0) {
/* Installs a binary package and required deps. */ /* Installs a binary package and required deps. */
if (argc != 2) if (argc < 2)
usage(); 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) { } else if (strcasecmp(argv[0], "update") == 0) {
/* Update an installed package. */ /* Update an installed package. */
if (argc != 2) if (argc < 2)
usage(); 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) { } else if (strcasecmp(argv[0], "remove") == 0) {
/* Removes a binary package. */ /* Removes a binary package. */
if (argc != 2) if (argc < 2)
usage(); usage();
rv = xbps_remove_installed_pkg(argv[1], force); rv = xbps_remove_installed_pkgs(argc, argv, force);
} else if (strcasecmp(argv[0], "show") == 0) { } else if (strcasecmp(argv[0], "show") == 0) {
/* Shows info about an installed binary package. */ /* Shows info about an installed binary package. */
@@ -245,7 +253,7 @@ main(int argc, char **argv)
if (argc != 1) if (argc != 1)
usage(); usage();
rv = xbps_exec_transaction("all", force, true); rv = xbps_autoupdate_pkgs(force);
} else if (strcasecmp(argv[0], "autoremove") == 0) { } else if (strcasecmp(argv[0], "autoremove") == 0) {
/* /*

View File

@@ -88,7 +88,7 @@ xbps_autoremove_pkgs(bool force)
prop_object_iterator_reset(iter); prop_object_iterator_reset(iter);
printf("\n\n"); 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"); printf("Cancelled!\n");
goto out2; goto out2;
} }
@@ -117,47 +117,79 @@ out:
} }
int 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_array_t reqby;
prop_dictionary_t dict; prop_dictionary_t dict;
size_t cols = 0;
const char *version; const char *version;
int rv = 0; int i, rv = 0;
bool reqby_force = false; bool found = false, first = false, reqby_force = false;
/* /*
* First check if package is required by other packages. * First check if package is required by other packages.
*/ */
dict = xbps_find_pkg_installed_from_plist(pkgname); for (i = 1; i < argc; i++) {
if (dict == NULL) { dict = xbps_find_pkg_installed_from_plist(argv[i]);
printf("Package %s is not installed.\n", pkgname); 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; 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) { * Show the list of going-to-be removed packages.
printf("WARNING! %s-%s is required by the following " */
"packages:\n\n", pkgname, version); printf("The following packages will be removed:\n\n");
(void)xbps_callback_array_iter_in_dict(dict, for (i = 1; i < argc; i++) {
"requiredby", list_strings_in_array, NULL); dict = xbps_find_pkg_installed_from_plist(argv[i]);
printf("\n\n"); if (dict == NULL)
reqby_force = true; 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);
} }
printf("\n\n");
if (!force && !xbps_noyes("Do you want to remove %s?", pkgname)) { if (!force && !xbps_noyes("Do you want to continue?")) {
printf("Cancelling!\n"); printf("Cancelling!\n");
return 0; return 0;
} }
if (reqby_force) if (reqby_force)
printf("Forcing %s-%s for deletion!\n", pkgname, version); printf("Forcing removal!\n");
printf("Removing package %s-%s ...\n", pkgname, version); for (i = 1; i < argc; i++) {
if ((rv = xbps_remove_pkg(pkgname, version, false)) != 0) { dict = xbps_find_pkg_installed_from_plist(argv[i]);
printf("Unable to remove %s-%s (%s).\n", if (dict == NULL)
pkgname, version, strerror(errno)); continue;
return rv; 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; return 0;

View File

@@ -63,16 +63,16 @@ Please note that all targets are *case insensitive*.
Updates all currently installed packages to the most newer version Updates all currently installed packages to the most newer version
available in repository pool. available in repository pool.
*check 'pkgname' | 'all'*:: *check 'pkgname(s)' | 'all'*::
Checks for integrity errors in installed packages. The checks Checks for integrity errors in installed packages. The checks
are to found missing run-time dependencies, missing and modified are to found missing run-time dependencies, missing and modified
package files and metadata files. If the *all* keyword is used, package files and metadata files. If the *all* keyword is used,
'all' packages currently installed will be checked, otherwise only 'all' packages currently installed will be checked, otherwise only
*pkgname*. *pkgname*.
*install 'pkgname'*:: *install 'pkgname(s)'*::
Install binary package "*pkgname*" by searching it in the 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 a remote repository), 'unpacked' and 'configured'. The 'unpack stage will
execute the *pre-install* action on its *INSTALL* script, and unpack its files. 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 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 not configured packages. If *-f* option is used, the package will be
reconfigured even if its state is already *installed*. reconfigured even if its state is already *installed*.
*remove 'pkgname'*:: *remove 'pkgname(s)'*::
Removes the installed package 'pkgname'. Its files will be removed Removes the installed package 'pkgname(s)'. Its files will be removed
and its state will be changed to *config-files* in the package and its state will be changed to *config-files* in the package
database. Configuration files, its metadata directory/files and database. Configuration files, its metadata directory/files and
its information in the package database are preserved. To fully remove 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 Shows the reverse dependencies for 'pkgname'. Reverse dependencies
are packages that are currently depending in 'pkgname' directly. are packages that are currently depending in 'pkgname' directly.
*update 'pkgname'*:: *update 'pkgname(s)'*::
Updates 'pkgname' to the most newer version available in repository Updates 'pkgname(s)' to the most newer version available in repository
pool. This can be used if only 'pkgname' needs to be updated, unlike pool. This can be used if only 'pkgname(s)' needs to be updated, unlike
the *autoupdate* target that will update all currently installed the *autoupdate* target that will update all currently installed
packages. packages.

View File

@@ -90,7 +90,10 @@ store_dependency(prop_dictionary_t master, prop_dictionary_t depd,
prop_object_release(dict); prop_object_release(dict);
return errno; return errno;
} }
if (!prop_dictionary_set_bool(dict, "automatic-install", true)) {
prop_object_release(dict);
return errno;
}
/* /*
* Add the dictionary into the array. * Add the dictionary into the array.
*/ */

View File

@@ -301,7 +301,7 @@ int SYMEXPORT
xbps_repository_install_pkg(const char *pkgname) xbps_repository_install_pkg(const char *pkgname)
{ {
prop_dictionary_t origin_pkgrd = NULL, pkgrd = NULL; prop_dictionary_t origin_pkgrd = NULL, pkgrd = NULL;
prop_array_t pkgs_array; prop_array_t unsorted;
struct repository_pool *rpool; struct repository_pool *rpool;
int rv = 0; int rv = 0;
@@ -345,49 +345,18 @@ xbps_repository_install_pkg(const char *pkgname)
} }
origin_pkgrd = prop_dictionary_copy(pkgrd); 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)) { if ((rv = xbps_repository_find_pkg_deps(trans_dict, pkgrd)) != 0)
/* goto out;
* 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;
}
}
/* /*
* Add required package dictionary into the packages * Add required package dictionary into the unsorted deps dictionary,
* dictionary. * set package state as not yet installed.
*/ */
pkgs_array = prop_dictionary_get(trans_dict, "packages"); unsorted = prop_dictionary_get(trans_dict, "unsorted_deps");
if (pkgs_array == NULL || if (unsorted == NULL) {
prop_object_type(pkgs_array) != PROP_TYPE_ARRAY) {
rv = EINVAL; rv = EINVAL;
goto out; goto out;
} }
@@ -399,7 +368,7 @@ xbps_repository_install_pkg(const char *pkgname)
rv = errno; rv = errno;
goto out; goto out;
} }
if (!prop_array_add(pkgs_array, origin_pkgrd)) if (!prop_array_add(unsorted, origin_pkgrd))
rv = errno; rv = errno;
out: out: