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:
parent
e1e5310428
commit
61a1d33995
10
NEWS
10
NEWS
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user