xbps-install(8): implemented single pkg updates without -u, --update.

The -u, --update is now only necessary to perform full system updates.

Close #35 (https://github.com/voidlinux/xbps/issues/35)
This commit is contained in:
Juan RP 2014-05-27 11:33:45 +02:00
parent e1e5310428
commit 61a1d33995
4 changed files with 122 additions and 40 deletions

10
NEWS
View File

@ -1,5 +1,15 @@
xbps-0.37 (???): xbps-0.37 (???):
* xbps-install(8): it's possible now to update a single package (if it's already
installed) without using the -u, --update option. This implements
GH #35 (https://github.com/voidlinux/xbps/issues/35).
$ xbps-install [-f] -y foo
- if foo is installed, update it.
- if foo not installed, install it.
- if -f is set, reinstall or downgrade it.
* xbps-query(8): new option (-S, --show) which shows info of a package * xbps-query(8): new option (-S, --show) which shows info of a package
installed locally or in a repository with -R. This is the default mode installed locally or in a repository with -R. This is the default mode
if no other mode is set; to preserve compatibility with previous versions. if no other mode is set; to preserve compatibility with previous versions.

View File

@ -1,9 +1,9 @@
.Dd April 21, 2014 .Dd May 27, 2014
.Os Void Linux .Os Void Linux
.Dt xbps-install 8 .Dt xbps-install 8
.Sh NAME .Sh NAME
.Nm xbps-install .Nm xbps-install
.Nd XBPS utility to install and update packages .Nd XBPS utility to (re)install and update packages
.Sh SYNOPSYS .Sh SYNOPSYS
.Nm xbps-install .Nm xbps-install
.Op OPTIONS .Op OPTIONS
@ -11,12 +11,17 @@
.Sh DESCRIPTION .Sh DESCRIPTION
The The
.Nm .Nm
utility installs and updates packages in the target root directory. utility installs, reinstalls, downgrades and updates packages in the target root directory.
The argument The argument
.Ar PKG .Ar PKG
is a package expression, which is explained in the is a package expression, which is explained in the
.Em PACKAGE EXPRESSION .Em PACKAGE EXPRESSION
section. section. If package is installed, it will be updated to the version available in repositories
matching the
.Em PACKAGE EXPRESSION .
Otherwise it will be installed, or reinstalled/downgraded if
.Fl f , Fl -force
option is set.
.Sh PACKAGE EXPRESSION .Sh PACKAGE EXPRESSION
A package expression is a form to match a pattern; currently xbps A package expression is a form to match a pattern; currently xbps
supports 3 ways to specify them: supports 3 ways to specify them:
@ -61,8 +66,10 @@ Specifies a full path to the cache directory, where binary packages are stored.
.It Fl d, Fl -debug .It Fl d, Fl -debug
Enables extra debugging shown to stderr. Enables extra debugging shown to stderr.
.It Fl f, Fl -force .It Fl f, Fl -force
Forcefully install target package even if another version is already installed, Force downgrade installation (if package version in repos is less than installed version),
overwritting regular package files and symlinks (if they have been modified) but or reinstallation (if package version in repos is the same) to the target
.Ar PKG ,
overwriting regular package files and symlinks (if they have been modified) but
.Em preserving configuration files . .Em preserving configuration files .
If If
.Fl f .Fl f
@ -79,9 +86,8 @@ Specifies a full path for the target root directory.
.It Fl S, Fl -sync .It Fl S, Fl -sync
Synchronize remote repository index files. Synchronize remote repository index files.
.It Fl u, Fl -update .It Fl u, Fl -update
Update target package(s) rather than install. If Performs a full system upgrade: all installed packages will be updated to the greatest
.Op PKG versions that were found in repositories.
not set, all installed packages will be updated.
.It Fl v, Fl -verbose .It Fl v, Fl -verbose
Enables verbose messages. Enables verbose messages.
.It Fl y, Fl -yes .It Fl y, Fl -yes

View File

@ -1,5 +1,5 @@
/*- /*-
* Copyright (c) 2009-2013 Juan Romero Pardines. * Copyright (c) 2009-2014 Juan Romero Pardines.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -54,17 +54,18 @@
*/ */
enum { enum {
TRANS_INSTALL = 1, TRANS_INSTALL = 1,
TRANS_UPDATE TRANS_UPDATE,
TRANS_REINSTALL
}; };
static int static int
trans_find_pkg(struct xbps_handle *xhp, const char *pkg, int action) trans_find_pkg(struct xbps_handle *xhp, const char *pkg, bool reinstall)
{ {
xbps_dictionary_t pkg_pkgdb = NULL, pkg_repod; xbps_dictionary_t pkg_pkgdb = NULL, pkg_repod = NULL;
xbps_array_t unsorted; xbps_array_t unsorted;
const char *repoloc, *repopkgver, *instpkgver, *reason; const char *repoloc, *repopkgver, *instpkgver, *reason;
char *pkgname; char *pkgname;
int rv = 0; int action = 0, rv = 0;
pkg_state_t state = 0; pkg_state_t state = 0;
bool autoinst = false; bool autoinst = false;
@ -77,7 +78,9 @@ trans_find_pkg(struct xbps_handle *xhp, const char *pkg, int action)
/* /*
* Find out if the pkg has been found in repository pool. * Find out if the pkg has been found in repository pool.
*/ */
if (action == TRANS_INSTALL) { if (pkg_pkgdb == NULL) {
/* pkg not installed, perform installation */
action = TRANS_INSTALL;
reason = "install"; reason = "install";
if (((pkg_repod = xbps_rpool_get_pkg(xhp, pkg)) == NULL) && if (((pkg_repod = xbps_rpool_get_pkg(xhp, pkg)) == NULL) &&
((pkg_repod = xbps_rpool_get_virtualpkg(xhp, pkg)) == NULL)) { ((pkg_repod = xbps_rpool_get_virtualpkg(xhp, pkg)) == NULL)) {
@ -85,21 +88,27 @@ trans_find_pkg(struct xbps_handle *xhp, const char *pkg, int action)
return ENOENT; return ENOENT;
} }
} else { } else {
if (pkg_pkgdb == NULL) /* pkg installed, update or reinstall */
return ENODEV; if (!reinstall) {
action = TRANS_UPDATE;
reason = "update"; reason = "update";
} else {
action = TRANS_REINSTALL;
reason = "install";
}
if ((pkg_repod = xbps_rpool_get_pkg(xhp, pkg)) == NULL) { if ((pkg_repod = xbps_rpool_get_pkg(xhp, pkg)) == NULL) {
/* not found */ /* not found */
return ENOENT; return ENOENT;
} }
} }
xbps_dictionary_get_cstring_nocopy(pkg_repod, "pkgver", &repopkgver); xbps_dictionary_get_cstring_nocopy(pkg_repod, "pkgver", &repopkgver);
xbps_dictionary_get_cstring_nocopy(pkg_repod, "repository", &repoloc); xbps_dictionary_get_cstring_nocopy(pkg_repod, "repository", &repoloc);
if (action == TRANS_UPDATE) { if (action == TRANS_UPDATE) {
/* /*
* Compare installed version vs best pkg available in repos. * Compare installed version vs best pkg available in repos
* for pkg updates.
*/ */
xbps_dictionary_get_cstring_nocopy(pkg_pkgdb, xbps_dictionary_get_cstring_nocopy(pkg_pkgdb,
"pkgver", &instpkgver); "pkgver", &instpkgver);
@ -109,16 +118,26 @@ trans_find_pkg(struct xbps_handle *xhp, const char *pkg, int action)
repopkgver, instpkgver, repoloc); repopkgver, instpkgver, repoloc);
return EEXIST; return EEXIST;
} }
} else if (action == TRANS_REINSTALL) {
/*
* For reinstallation check if installed version is less than
* or equal to the pkg in repos, if true, continue with reinstallation;
* otherwise perform an update.
*/
xbps_dictionary_get_cstring_nocopy(pkg_pkgdb, "pkgver", &instpkgver);
if (xbps_cmpver(repopkgver, instpkgver) == 1) {
action = TRANS_UPDATE;
reason = "update";
}
} }
if (pkg_pkgdb) { if (pkg_pkgdb) {
/* /*
* If pkg is already installed, respect its automatic-install * If pkg is already installed, respect its automatic-install
* property. * property.
*/ */
xbps_dictionary_get_bool(pkg_pkgdb, "automatic-install", xbps_dictionary_get_bool(pkg_pkgdb, "automatic-install", &autoinst);
&autoinst); xbps_dictionary_set_bool(pkg_repod, "automatic-install", autoinst);
xbps_dictionary_set_bool(pkg_repod, "automatic-install",
autoinst);
} }
/* /*
* Prepare transaction dictionary. * Prepare transaction dictionary.
@ -216,7 +235,7 @@ xbps_transaction_update_packages(struct xbps_handle *xhp)
} }
pkgname = xbps_pkg_name(pkgver); pkgname = xbps_pkg_name(pkgver);
assert(pkgname); assert(pkgname);
rv = trans_find_pkg(xhp, pkgname, TRANS_UPDATE); rv = trans_find_pkg(xhp, pkgname, false);
if (rv == 0) if (rv == 0)
newpkg_found = true; newpkg_found = true;
else if (rv == ENOENT || rv == EEXIST || rv == ENODEV) { else if (rv == ENOENT || rv == EEXIST || rv == ENODEV) {
@ -236,27 +255,14 @@ xbps_transaction_update_packages(struct xbps_handle *xhp)
int int
xbps_transaction_update_pkg(struct xbps_handle *xhp, const char *pkg) xbps_transaction_update_pkg(struct xbps_handle *xhp, const char *pkg)
{ {
return trans_find_pkg(xhp, pkg, TRANS_UPDATE); return trans_find_pkg(xhp, pkg, false);
} }
int int
xbps_transaction_install_pkg(struct xbps_handle *xhp, const char *pkg, xbps_transaction_install_pkg(struct xbps_handle *xhp, const char *pkg,
bool reinstall) bool reinstall)
{ {
xbps_dictionary_t pkgd = NULL; return trans_find_pkg(xhp, pkg, reinstall);
pkg_state_t state;
if ((pkgd = xbps_pkgdb_get_pkg(xhp, pkg)) ||
(pkgd = xbps_pkgdb_get_virtualpkg(xhp, pkg))) {
if (xbps_pkg_state_dictionary(pkgd, &state) != 0)
return EINVAL;
if ((state == XBPS_PKG_STATE_INSTALLED) && !reinstall) {
/* error out if pkg installed and no reinstall */
return EEXIST;
}
}
return trans_find_pkg(xhp, pkg, TRANS_INSTALL);
} }
int int

View File

@ -66,7 +66,67 @@ install_with_vpkg_deps_body() {
atf_check_equal $? 0 atf_check_equal $? 0
} }
atf_test_case update_if_installed
update_if_installed_head() {
atf_set "descr" "Tests for pkg installations: update if installed (issue #35)"
}
update_if_installed_body() {
mkdir some_repo
mkdir -p pkg_A/usr/bin
cd some_repo
xbps-create -A noarch -n A-1.0_1 -s "A pkg" ../pkg_A
atf_check_equal $? 0
xbps-rindex -a *.xbps
atf_check_equal $? 0
cd ..
xbps-install -C empty.conf -r root --repository=$PWD/some_repo -y A
atf_check_equal $? 0
cd some_repo
xbps-create -A noarch -n A-1.1_1 -s "A pkg" ../pkg_A
atf_check_equal $? 0
xbps-rindex -a *.xbps
atf_check_equal $? 0
cd ..
xbps-install -C empty.conf -r root --repository=$PWD/some_repo -y A
atf_check_equal $? 0
pkgver=$(xbps-query -r root -ppkgver A)
atf_check_equal $pkgver A-1.1_1
}
atf_test_case install_if_not_installed_on_update
install_if_not_installed_on_update_head() {
atf_set "descr" "Tests for pkg installations: install if not installed on update (issue #35)"
}
install_if_not_installed_on_update_body() {
mkdir some_repo
mkdir -p pkg_A/usr/bin
cd some_repo
xbps-create -A noarch -n A-1.0_1 -s "A pkg" ../pkg_A
atf_check_equal $? 0
xbps-rindex -a *.xbps
atf_check_equal $? 0
cd ..
xbps-install -C empty.conf -r root --repository=$PWD/some_repo -yu A
atf_check_equal $? 0
pkgver=$(xbps-query -r root -ppkgver A)
atf_check_equal $pkgver A-1.0_1
}
atf_init_test_cases() { atf_init_test_cases() {
atf_add_test_case install_with_deps atf_add_test_case install_with_deps
atf_add_test_case install_with_vpkg_deps atf_add_test_case install_with_vpkg_deps
atf_add_test_case install_if_not_installed_on_update
atf_add_test_case update_if_installed
} }