Merged purge code in remove, configurable transaction regpkgdb flushing.
See the NEWS file for info.
This commit is contained in:
parent
d7a32a7eca
commit
3b7491d29b
23
NEWS
23
NEWS
@ -1,4 +1,25 @@
|
||||
xbps-0.11.1 (???):
|
||||
xbps-0.12.0 (???):
|
||||
|
||||
* Renamed some options in xbps.conf to not have dashes, such as:
|
||||
fetch-timeout-connection -> FetchTimeoutConnection
|
||||
fetch-cache-connections-host -> FetchCacheConnections
|
||||
fetch-cache-connections-per-host -> FetchCacheConnectionsPerHost
|
||||
|
||||
* Implemented memory caching for regpkgdb and configurarable transaction
|
||||
flushing. Can be changed in xbps.conf with "TransactionFrequencyFlusing".
|
||||
By default set to 5. That means that every 5 packages processed in
|
||||
a transaction there will be a regpkgdb plist flush to disk.
|
||||
|
||||
Setting it to 0 enables automatic mode which will only flush in
|
||||
two required points. Setting it to 1 makes the behaviour used in XBPS<=0.11,
|
||||
which flushed it on every package.
|
||||
|
||||
That feature provides a 25% (and in some cases even more!) of performance
|
||||
when executing a transaction.
|
||||
|
||||
* Merged purge code into remove. It wasn't necessary to have this splitted,
|
||||
so it now has been merged into xbps_remove_pkg(). That also means that
|
||||
'-p' flag in xbps-bin(8) and xbps-repo(8) doesn't exist anymore.
|
||||
|
||||
* xbps-repo(8): the 'find-files' target accepts multiple patterns, such as:
|
||||
$ xbps-repo find-files /bin/cat '/bin/f*' ...
|
||||
|
@ -35,44 +35,6 @@
|
||||
#include <xbps_api.h>
|
||||
#include "defs.h"
|
||||
|
||||
static int
|
||||
write_pkgd_to_regpkgdb(prop_dictionary_t pkgd,
|
||||
prop_array_t regpkgs,
|
||||
const char *pkgn)
|
||||
{
|
||||
struct xbps_handle *xhp = xbps_handle_get();
|
||||
char *path;
|
||||
int rv;
|
||||
|
||||
rv = xbps_array_replace_dict_by_name(regpkgs, pkgd, pkgn);
|
||||
if (rv != 0) {
|
||||
xbps_error_printf("%s: failed to replace pkgd: %s\n",
|
||||
pkgn, strerror(rv));
|
||||
return -1;
|
||||
}
|
||||
if (!prop_dictionary_set(xhp->regpkgdb_dictionary,
|
||||
"packages", regpkgs)) {
|
||||
xbps_error_printf("%s: failed to set new regpkgdb "
|
||||
"packages array: %s", pkgn, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
path = xbps_xasprintf("%s/%s/%s", xhp->rootdir,
|
||||
XBPS_META_PATH, XBPS_REGPKGDB);
|
||||
if (path == NULL)
|
||||
return -1;
|
||||
|
||||
if (!prop_dictionary_externalize_to_zfile(
|
||||
xhp->regpkgdb_dictionary, path)) {
|
||||
xbps_error_printf("%s: failed to write regpkgdb plist:"
|
||||
" %s\n", pkgn, strerror(errno));
|
||||
free(path);
|
||||
return -1;
|
||||
}
|
||||
free(path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks package integrity of an installed package.
|
||||
* The following task is accomplished in this file:
|
||||
@ -94,6 +56,8 @@ check_pkg_requiredby(prop_dictionary_t pkgd_regpkgdb,
|
||||
struct xbps_handle *xhp = xbps_handle_get();
|
||||
const char *curpkgn, *pkgname, *pkgver;
|
||||
size_t i;
|
||||
int rv;
|
||||
bool pkg_fixed = false;
|
||||
|
||||
(void)pkg_propsd;
|
||||
(void)pkg_filesd;
|
||||
@ -101,7 +65,7 @@ check_pkg_requiredby(prop_dictionary_t pkgd_regpkgdb,
|
||||
prop_dictionary_get_cstring_nocopy(pkgd_regpkgdb, "pkgname", &pkgname);
|
||||
prop_dictionary_get_cstring_nocopy(pkgd_regpkgdb, "pkgver", &pkgver);
|
||||
|
||||
regpkgs = prop_dictionary_get(xhp->regpkgdb_dictionary, "packages");
|
||||
regpkgs = prop_dictionary_get(xhp->regpkgdb, "packages");
|
||||
|
||||
for (i = 0; i < prop_array_count(regpkgs); i++) {
|
||||
obj = prop_array_get(regpkgs, i);
|
||||
@ -181,13 +145,30 @@ check_pkg_requiredby(prop_dictionary_t pkgd_regpkgdb,
|
||||
*/
|
||||
prop_array_add(reqby, curpkgver);
|
||||
prop_dictionary_set(pkgd_regpkgdb, "requiredby", reqby);
|
||||
if (write_pkgd_to_regpkgdb(pkgd_regpkgdb, regpkgs, pkgname) != 0)
|
||||
rv = xbps_array_replace_dict_by_name(regpkgs, obj, curpkgn);
|
||||
if (rv != 0) {
|
||||
xbps_error_printf("%s: failed to replace pkgd: %s\n",
|
||||
curpkgn, strerror(rv));
|
||||
return -1;
|
||||
|
||||
}
|
||||
if (!prop_dictionary_set(xhp->regpkgdb, "packages", regpkgs)) {
|
||||
xbps_error_printf("%s: failed to set new regpkgdb "
|
||||
"packages array: %s", curpkgn, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
pkg_fixed = true;
|
||||
printf("%s: added requiredby entry for %s.\n",
|
||||
pkgver, prop_string_cstring_nocopy(curpkgver));
|
||||
prop_object_release(curpkg_propsd);
|
||||
}
|
||||
if (pkg_fixed == false)
|
||||
return rv;
|
||||
|
||||
return 0;
|
||||
if ((rv = xbps_regpkgdb_update(xhp, true)) != 0) {
|
||||
xbps_error_printf("failed to write regpkgdb plist: "
|
||||
" %s\n", strerror(rv));
|
||||
return rv;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -47,9 +47,9 @@ struct list_pkgver_cb {
|
||||
/* from transaction.c */
|
||||
int install_new_pkg(const char *, bool);
|
||||
int update_pkg(const char *);
|
||||
int remove_pkg(const char *, bool, bool);
|
||||
int remove_pkg(const char *, bool);
|
||||
int autoupdate_pkgs(bool, bool);
|
||||
int autoremove_pkgs(bool, bool);
|
||||
int autoremove_pkgs(bool);
|
||||
int exec_transaction(bool, bool);
|
||||
|
||||
/* from remove.c */
|
||||
|
@ -68,17 +68,17 @@ main(int argc, char **argv)
|
||||
struct sigaction sa;
|
||||
const char *rootdir, *cachedir, *conffile, *option;
|
||||
int i, c, flags, rv;
|
||||
bool yes, purge, debug, reqby_force, force_rm_with_deps, recursive_rm;
|
||||
bool yes, debug, reqby_force, force_rm_with_deps, recursive_rm;
|
||||
bool install_auto, install_manual, show_download_pkglist_url;
|
||||
bool reinstall;
|
||||
|
||||
rootdir = cachedir = conffile = option = NULL;
|
||||
flags = rv = 0;
|
||||
reqby_force = yes = purge = force_rm_with_deps = false;
|
||||
reqby_force = yes = force_rm_with_deps = false;
|
||||
recursive_rm = debug = reinstall = false;
|
||||
install_auto = install_manual = show_download_pkglist_url = false;
|
||||
|
||||
while ((c = getopt(argc, argv, "AC:c:dDFfMo:pRr:Vvy")) != -1) {
|
||||
while ((c = getopt(argc, argv, "AC:c:dDFfMo:Rr:Vvy")) != -1) {
|
||||
switch (c) {
|
||||
case 'A':
|
||||
install_auto = true;
|
||||
@ -109,9 +109,6 @@ main(int argc, char **argv)
|
||||
case 'o':
|
||||
option = optarg;
|
||||
break;
|
||||
case 'p':
|
||||
purge = true;
|
||||
break;
|
||||
case 'R':
|
||||
recursive_rm = true;
|
||||
break;
|
||||
@ -147,15 +144,6 @@ main(int argc, char **argv)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Register a signal handler to clean up resources used by libxbps.
|
||||
*/
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = cleanup;
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
sigaction(SIGTERM, &sa, NULL);
|
||||
sigaction(SIGQUIT, &sa, NULL);
|
||||
|
||||
/*
|
||||
* Initialize libxbps.
|
||||
*/
|
||||
@ -185,6 +173,14 @@ main(int argc, char **argv)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Register a signal handler to clean up resources used by libxbps.
|
||||
*/
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = cleanup;
|
||||
sigaction(SIGINT, &sa, NULL);
|
||||
sigaction(SIGTERM, &sa, NULL);
|
||||
|
||||
if (strcasecmp(argv[0], "list") == 0) {
|
||||
/* Lists packages currently registered in database. */
|
||||
if (argc < 1 || argc > 2)
|
||||
@ -199,12 +195,12 @@ main(int argc, char **argv)
|
||||
lpc.state = XBPS_PKG_STATE_HALF_UNPACKED;
|
||||
else if (strcmp(argv[1], "unpacked") == 0)
|
||||
lpc.state = XBPS_PKG_STATE_UNPACKED;
|
||||
else if (strcmp(argv[1], "config-files") == 0)
|
||||
lpc.state = XBPS_PKG_STATE_CONFIG_FILES;
|
||||
else if (strcmp(argv[1], "half-removed") == 0)
|
||||
lpc.state = XBPS_PKG_STATE_HALF_REMOVED;
|
||||
else {
|
||||
fprintf(stderr,
|
||||
"E: invalid state `%s'. Accepted values: "
|
||||
"config-files, unpacked, "
|
||||
"half-removed, unpacked, half-unpacked, "
|
||||
"installed [default]\n", argv[1]);
|
||||
rv = -1;
|
||||
goto out;
|
||||
@ -249,7 +245,7 @@ main(int argc, char **argv)
|
||||
usage(xhp);
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
rv = remove_pkg(argv[i], purge, recursive_rm);
|
||||
rv = remove_pkg(argv[i], recursive_rm);
|
||||
if (rv == 0)
|
||||
continue;
|
||||
else if (rv != EEXIST)
|
||||
@ -323,19 +319,7 @@ main(int argc, char **argv)
|
||||
if (argc != 1)
|
||||
usage(xhp);
|
||||
|
||||
rv = autoremove_pkgs(yes, purge);
|
||||
|
||||
} else if (strcasecmp(argv[0], "purge") == 0) {
|
||||
/*
|
||||
* Purge a package completely.
|
||||
*/
|
||||
if (argc != 2)
|
||||
usage(xhp);
|
||||
|
||||
if (strcasecmp(argv[1], "all") == 0)
|
||||
rv = xbps_purge_packages();
|
||||
else
|
||||
rv = xbps_purge_pkg(argv[1], true);
|
||||
rv = autoremove_pkgs(yes);
|
||||
|
||||
} else if (strcasecmp(argv[0], "reconfigure") == 0) {
|
||||
/*
|
||||
|
@ -66,9 +66,6 @@ state_cb(const struct xbps_state_cb_data *xscd, void *cbdata)
|
||||
case XBPS_STATE_REMOVE:
|
||||
printf("Removing `%s-%s' ...\n", xscd->pkgname, xscd->version);
|
||||
break;
|
||||
case XBPS_STATE_PURGE:
|
||||
printf("Purging `%s-%s' ...\n", xscd->pkgname, xscd->version);
|
||||
break;
|
||||
case XBPS_STATE_CONFIGURE:
|
||||
printf("Configuring `%s-%s' ...\n", xscd->pkgname,
|
||||
xscd->version);
|
||||
@ -125,21 +122,12 @@ state_cb(const struct xbps_state_cb_data *xscd, void *cbdata)
|
||||
"(rootdir: %s).", xscd->pkgname, xscd->version,
|
||||
xhp->rootdir);
|
||||
break;
|
||||
case XBPS_STATE_PURGE_DONE:
|
||||
printf("Purged `%s-%s' successfully.\n",
|
||||
xscd->pkgname, xscd->version);
|
||||
if (xhp->syslog_enabled)
|
||||
syslog(LOG_NOTICE, "Purged `%s-%s' successfully "
|
||||
"(rootdir: %s).", xscd->pkgname, xscd->version,
|
||||
xhp->rootdir);
|
||||
break;
|
||||
/* errors */
|
||||
case XBPS_STATE_UNPACK_FAIL:
|
||||
case XBPS_STATE_UPDATE_FAIL:
|
||||
case XBPS_STATE_CONFIGURE_FAIL:
|
||||
case XBPS_STATE_REGISTER_FAIL:
|
||||
case XBPS_STATE_UNREGISTER_FAIL:
|
||||
case XBPS_STATE_PURGE_FAIL:
|
||||
case XBPS_STATE_REMOVE_FAIL:
|
||||
case XBPS_STATE_VERIFY_FAIL:
|
||||
case XBPS_STATE_DOWNLOAD_FAIL:
|
||||
|
@ -222,11 +222,11 @@ autoupdate_pkgs(bool yes, bool show_download_pkglist_url)
|
||||
}
|
||||
|
||||
int
|
||||
autoremove_pkgs(bool yes, bool purge)
|
||||
autoremove_pkgs(bool yes)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
if ((rv = xbps_transaction_autoremove_pkgs(purge)) != 0) {
|
||||
if ((rv = xbps_transaction_autoremove_pkgs()) != 0) {
|
||||
if (rv == ENOENT) {
|
||||
printf("No package orphans were found.\n");
|
||||
return 0;
|
||||
@ -328,7 +328,7 @@ update_pkg(const char *pkgname)
|
||||
}
|
||||
|
||||
int
|
||||
remove_pkg(const char *pkgname, bool purge, bool recursive)
|
||||
remove_pkg(const char *pkgname, bool recursive)
|
||||
{
|
||||
prop_dictionary_t pkgd;
|
||||
prop_array_t reqby;
|
||||
@ -336,7 +336,7 @@ remove_pkg(const char *pkgname, bool purge, bool recursive)
|
||||
size_t x;
|
||||
int rv;
|
||||
|
||||
rv = xbps_transaction_remove_pkg(pkgname, purge, recursive);
|
||||
rv = xbps_transaction_remove_pkg(pkgname, recursive);
|
||||
if (rv == EEXIST) {
|
||||
/* pkg has revdeps */
|
||||
pkgd = xbps_find_pkg_dict_installed(pkgname, false);
|
||||
|
@ -1,4 +1,4 @@
|
||||
.Dd December 22, 2011
|
||||
.Dd December 23, 2011
|
||||
.Os Void GNU/Linux
|
||||
.Dt xbps-bin 8
|
||||
.Sh NAME
|
||||
@ -60,7 +60,6 @@ depending on it, i.e package is a dependency of any other installed package.
|
||||
.It Fl f
|
||||
Used currently in the
|
||||
.Em install ,
|
||||
.Em purge ,
|
||||
.Em reconfigure
|
||||
and
|
||||
.Em remove
|
||||
@ -69,10 +68,8 @@ targets. If set, package(s) will be reconfigured regardless of its state in
|
||||
target, or to
|
||||
.Em force
|
||||
removal of package files even if its hash does not match in the
|
||||
.Em purge
|
||||
and
|
||||
.Em remove
|
||||
targets. If set, package(s) will be reinstalled even if its state is
|
||||
target. If set, package(s) will be reinstalled even if its state is
|
||||
.Em installed
|
||||
when used with the
|
||||
.Em install
|
||||
@ -95,13 +92,6 @@ Used currently in the
|
||||
target. Prints the value of specified key(s) from
|
||||
package's properties dictionary. Multiple keys can be specified delimited by
|
||||
the comma character.
|
||||
.It Fl p
|
||||
Used currently in the
|
||||
.Em remove
|
||||
and
|
||||
.Em autoremove
|
||||
targets. If enabled, after removing
|
||||
a package it is also purged.
|
||||
.It Fl R
|
||||
Used currently in the
|
||||
.Em remove
|
||||
@ -175,28 +165,14 @@ to list only packages with the specified
|
||||
By default only packages fully installed will be listed if
|
||||
.Em state
|
||||
has not been specified. Accepted states are:
|
||||
.Em config-files ,
|
||||
.Em half-removed ,
|
||||
.Em half-unpacked ,
|
||||
.Em unpacked ,
|
||||
.Em installed
|
||||
and
|
||||
.Em installed .
|
||||
.Em unpacked .
|
||||
.It Sy list-manual
|
||||
Lists packages that were installed manually by the user, i.e not as dependencies
|
||||
of any other package.
|
||||
.It Sy purge Ar pkgname | Ar all
|
||||
Purge an installed package:
|
||||
.Em pkgname
|
||||
or
|
||||
.Em all
|
||||
packages. The purge stage runs the post-remove action set in the REMOVE script
|
||||
in its metadata directory
|
||||
.Pa (/var/db/xbps/metadata/pkgname)
|
||||
and will remove configuration (if they were not modified by the user) and
|
||||
metadata files. The package will be fully removed from the system once it
|
||||
has been purged. If
|
||||
.Ql -f
|
||||
option is used, configuration files that have been
|
||||
.Em modified WILL BE REMOVED. BEWARE WITH THIS!
|
||||
.It Sy reconfigure Ar pkgname | Ar all
|
||||
Reconfigure an unpacked package. Packages in this state are not fully installed,
|
||||
because they were not configured for whatever reason. The configure stage will
|
||||
@ -209,16 +185,7 @@ option is used, the package will be reconfigured even if its state is already in
|
||||
.It Sy remove Ar pkgname(s)
|
||||
Removes the installed package
|
||||
.Em pkgname(s) .
|
||||
Its files will be removed and its state will be changed to
|
||||
.Em config-files
|
||||
in the package database. Configuration files, its metadata directory/files and its
|
||||
information in the package database are preserved. To fully remove a package in
|
||||
.Em config-files
|
||||
state, it must be purged with the
|
||||
.Em purge
|
||||
command or alternatively use the
|
||||
.Ql -p
|
||||
flag. If
|
||||
Files not matching the original SHA256 hash will be preserved. If
|
||||
.Ql -f
|
||||
option is used, package files will be
|
||||
.Em removed even if its SHA256 hash don't match .
|
||||
@ -257,10 +224,9 @@ target that will update all currently installed packages.
|
||||
A package can be in a different state while it is being
|
||||
.Em installed ,
|
||||
.Em removed ,
|
||||
.Em unpacked ,
|
||||
.Em configured
|
||||
.Em unpacked
|
||||
or
|
||||
.Em purged .
|
||||
.Em configured .
|
||||
The following states are available:
|
||||
.Bl -tag -width ident
|
||||
.It Sy installed
|
||||
@ -271,11 +237,13 @@ The package was being unpacked but didn't finish properly for unknown reasons.
|
||||
The package has been unpacked in destination root directory, but it is not fully
|
||||
installed because it was not yet configured. Please note that some packages will
|
||||
do not work if they are only unpacked.
|
||||
.It Sy config-files
|
||||
The package has been removed but configuration files and its metadata directory
|
||||
are still available (and it is still registered in the package database).
|
||||
You can purge safely packages that are in this state, modified configuration
|
||||
files will be preserved.
|
||||
.It Sy half-remove
|
||||
The package removal did not finish for unknown reasons (power outage, process killed, etc).
|
||||
The
|
||||
.Em purge
|
||||
action in its metadata REMOVE script has not been yet executed. The package
|
||||
metadata directory is still available and it is registered in package database.
|
||||
Packages in this state can be still removed.
|
||||
.Sh FILES
|
||||
.Bl -tag -width /var/db/xbps/metadata/<pkgname>/props.plist -compact
|
||||
.It Pa /etc/xbps/xbps.conf
|
||||
|
@ -94,6 +94,7 @@ die(const char *fmt, ...)
|
||||
vfprintf(stderr, fmt, ap);
|
||||
fprintf(stderr, " (%s)\n", strerror(save_errno));
|
||||
va_end(ap);
|
||||
xbps_end(xbps_handle_get());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
@ -215,6 +215,9 @@ main(int argc, char **argv)
|
||||
in_chroot ? "[chroot] " : "" , argv[1], argv[2],
|
||||
strerror(rv), MSG_RESET);
|
||||
} else {
|
||||
if ((rv = xbps_regpkgdb_update(xhp, true)) != 0)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
printf("%s%s=> %s-%s registered successfully.%s\n",
|
||||
MSG_NORMAL, in_chroot ? "[chroot] " : "",
|
||||
argv[1], argv[2], MSG_RESET);
|
||||
|
@ -17,11 +17,13 @@ digraph regpkgdb_dictionary {
|
||||
pkgdict -> pkgver [label="string"];
|
||||
pkgdict -> state [label="string"];
|
||||
state -> state_inst [label="value"];
|
||||
state -> state_cffiles [label="value"];
|
||||
state -> state_hfuned [label="value"];
|
||||
state -> state_unpack [label="value"];
|
||||
state -> state_hfrmed [label="value"];
|
||||
state_inst [style=filled,fillcolor="yellowgreen",label="installed"];
|
||||
state_cffiles [style=filled,fillcolor="yellowgreen",label="config-files"];
|
||||
state_hfuned [style=filled,fillcolor="yellowgreen",label="half-unpacked"];
|
||||
state_unpack [style=filled,fillcolor="yellowgreen",label="unpacked"];
|
||||
state_hfrmed [style=filled,fillcolor="yellowgreen",label="half-removed"];
|
||||
pkgdict -> automatic [label="bool"];
|
||||
automatic [label="automatic-install"];
|
||||
pkgdict -> short_desc [label="string"]
|
||||
|
BIN
etc/.xbps.conf.swp
Normal file
BIN
etc/.xbps.conf.swp
Normal file
Binary file not shown.
@ -2,24 +2,30 @@
|
||||
# ============================
|
||||
#
|
||||
# Root directory.
|
||||
#rootdir = /
|
||||
#RootDir = /
|
||||
#
|
||||
# Cache directory to store downloaded binary packages.
|
||||
# If string begins with '/' it will be treated as full path,
|
||||
# otherwise it will be treated as relative to the root-directory.
|
||||
#cachedir = var/cache/xbps
|
||||
#CacheDir = var/cache/xbps
|
||||
#
|
||||
# Default global limit of cached connections when fetching files.
|
||||
#fetch-cache-connections = 10
|
||||
#FetchCacheConnection = 10
|
||||
#
|
||||
# Default per-host limit of cached connections when fetching files.
|
||||
#fetch-cache-connections-per-host = 3
|
||||
#FetchCacheConnectionPerHost = 3
|
||||
#
|
||||
# Default timeout limit for connections, in seconds.
|
||||
#fetch-timeout-connection = 30
|
||||
#FetchTimeoutConnection = 30
|
||||
#
|
||||
# Enable syslog messages, set the value to false or 0 to disable.
|
||||
#syslog = true
|
||||
#Syslog = true
|
||||
|
||||
# Number of packages to be processed in a transaction to trigger
|
||||
# a flush to the master package database. Set it to 0 to make it
|
||||
# only flush at required points.
|
||||
#
|
||||
#TransactionFrequencyFlush = 25
|
||||
|
||||
# Repositories.
|
||||
#
|
||||
|
@ -56,7 +56,7 @@
|
||||
*/
|
||||
#define XBPS_PKGINDEX_VERSION "1.3"
|
||||
|
||||
#define XBPS_API_VERSION "20111223"
|
||||
#define XBPS_API_VERSION "20111224"
|
||||
#define XBPS_VERSION "0.12"
|
||||
|
||||
/**
|
||||
@ -159,6 +159,13 @@
|
||||
*/
|
||||
#define XBPS_FETCH_TIMEOUT 30
|
||||
|
||||
/**
|
||||
* @def XBPS_TRANS_FLUSH
|
||||
* Default number of packages to be processed in a transaction to
|
||||
* trigger a flush to the master package database XBPS_REGPKGDB.
|
||||
*/
|
||||
#define XBPS_TRANS_FLUSH 5
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
void xbps_dbg_printf(const char *, ...);
|
||||
@ -187,8 +194,6 @@ void xbps_warn_printf(const char *, ...);
|
||||
* XBPS_STATE_REMOVE_DONE: a package has been removed successfully.
|
||||
* XBPS_STATE_REMOVE_FILE: a package file is being removed.
|
||||
* XBPS_STATE_REMOVE_OBSOLETE: an obsolete package file is being removed.
|
||||
* XBPS_STATE_PURGE: a package is being purged.
|
||||
* XBPS_STATE_PURGE_DONE: a package has been purged successfully.
|
||||
* XBPS_STATE_REPLACE: a package is being replaced.
|
||||
* XBPS_STATE_INSTALL: a package is being installed.
|
||||
* XBPS_STATE_INSTALL_DONE: a package has been installed successfully.
|
||||
@ -209,7 +214,6 @@ void xbps_warn_printf(const char *, ...);
|
||||
* its hash has failed.
|
||||
* XBPS_STATE_REMOVE_FILE_OBSOLETE_FAIL: an obsolete package file
|
||||
* removal has failed.
|
||||
* XBPS_STATE_PURGE_FAIL: package purge has failed.
|
||||
* XBPS_STATE_CONFIGURE_FAIL: package configure has failed.
|
||||
* XBPS_STATE_CONFIG_FILE_FAIL: package configuration file operation
|
||||
* has failed.
|
||||
@ -419,12 +423,12 @@ struct xbps_handle {
|
||||
*/
|
||||
cfg_t *cfg;
|
||||
/**
|
||||
* @private regpkgdb_dictionary.
|
||||
* @private regpkgdb.
|
||||
*
|
||||
* Internalized proplib dictionary with the registed package database
|
||||
* stored in XBPS_META_PATH/XBPS_REGPKGDB.
|
||||
*/
|
||||
prop_dictionary_t regpkgdb_dictionary;
|
||||
prop_dictionary_t regpkgdb;
|
||||
/**
|
||||
* @private
|
||||
*
|
||||
@ -498,13 +502,20 @@ struct xbps_handle {
|
||||
*/
|
||||
const char *conffile;
|
||||
/**
|
||||
* @private fetch_timeout
|
||||
* @var fetch_timeout
|
||||
*
|
||||
* Unsigned integer to specify libfetch's timeout limit.
|
||||
* If not set, it defaults to 30 (in seconds). This is set internally
|
||||
* by the API from a setting in configuration file.
|
||||
*/
|
||||
uint16_t fetch_timeout;
|
||||
/**
|
||||
* @var transaction_frequency_flush
|
||||
*
|
||||
* Number of packages to be processed in a transaction to
|
||||
* trigger a flush to the master databases.
|
||||
*/
|
||||
uint16_t transaction_frequency_flush;
|
||||
/**
|
||||
* @var flags
|
||||
*
|
||||
@ -554,8 +565,8 @@ struct xbps_handle {
|
||||
* - Set default cache connections for libfetch.
|
||||
* - Parse configuration file.
|
||||
*
|
||||
* @param[in] xhp Pointer to an xbps_handle structure, as returned by
|
||||
* \a xbps_handle_alloc().
|
||||
* @param[in] xhp The xbps_handle structure previously allocated
|
||||
* by \a xbps_handle_alloc().
|
||||
* @note It's assumed that \a xhp is a valid pointer.
|
||||
*
|
||||
* @return 0 on success, an errno value otherwise.
|
||||
@ -797,6 +808,32 @@ int xbps_regpkgdb_foreach_reverse_pkg_cb(
|
||||
int (*fn)(prop_object_t, void *, bool *),
|
||||
void *arg);
|
||||
|
||||
/**
|
||||
* Returns a package dictionary from regpkgdb plist, matching pkgname or
|
||||
* pkgver specified in \a pkg.
|
||||
*
|
||||
* @param[in] pkg Package name or name-version tuple to match.
|
||||
* @param[in] bypattern If false \a pkg must be a pkgname, otherwise a pkgver.
|
||||
*
|
||||
* @return The matching proplib package dictionary from regpkgdb copied
|
||||
* with \a prop_dictionary_copy() so it must be released when not required
|
||||
* anymore with prop_object_release().
|
||||
*/
|
||||
prop_dictionary_t xbps_regpkgdb_get_pkgd(const char *pkg, bool bypattern);
|
||||
|
||||
/**
|
||||
* Updates the regpkgdb plist with new contents from disk to the cached copy
|
||||
* in memory.
|
||||
*
|
||||
* @param[in] xhp Pointer to our xbps_handle struct, as returned by
|
||||
* \a xbps_handle_get() or xbps_handle_alloc().
|
||||
* @param[in] flush If true the regpkgdb plist contents in memory will
|
||||
* be flushed atomically to disk.
|
||||
*
|
||||
* @return 0 on success, otherwise an errno value.
|
||||
*/
|
||||
int xbps_regpkgdb_update(struct xbps_handle *xhp, bool flush);
|
||||
|
||||
/**
|
||||
* Finds the proplib's dictionary associated with a package, by looking
|
||||
* it via its name in a proplib dictionary.
|
||||
@ -1097,30 +1134,6 @@ int xbps_array_replace_dict_by_name(prop_array_t array,
|
||||
|
||||
/*@}*/
|
||||
|
||||
/** @addtogroup purge */
|
||||
/*@{*/
|
||||
|
||||
/**
|
||||
* Purge an installed package.
|
||||
*
|
||||
* @param[in] pkgname Package name to match.
|
||||
* @param[in] check_state Set it to true to check that package
|
||||
* is in XBPS_PKG_STATE_CONFIG_FILES state.
|
||||
*
|
||||
* @return 0 on success, otherwise an errno value.
|
||||
*/
|
||||
int xbps_purge_pkg(const char *pkgname, bool check_state);
|
||||
|
||||
/**
|
||||
* Purge all installed packages. Packages that aren't in
|
||||
* XBPS_PKG_STATE_CONFIG_FILES state will be ignored.
|
||||
*
|
||||
* @return 0 on success, otherwise an errno value.
|
||||
*/
|
||||
int xbps_purge_packages(void);
|
||||
|
||||
/*@}*/
|
||||
|
||||
/** @addtogroup pkg_register */
|
||||
/*@{*/
|
||||
|
||||
@ -1220,7 +1233,6 @@ int xbps_transaction_update_packages(void);
|
||||
* be added into the transaction dictionary.
|
||||
*
|
||||
* @param[in] pkgname Package name to be removed.
|
||||
* @param[in] purge If true package will also be purged.
|
||||
* @param[in] recursive If true, all packages that are currently depending
|
||||
* on the package to be removed, and if they are orphans, will be added.
|
||||
*
|
||||
@ -1229,19 +1241,16 @@ int xbps_transaction_update_packages(void);
|
||||
* process.
|
||||
*/
|
||||
int xbps_transaction_remove_pkg(const char *pkgname,
|
||||
bool purge,
|
||||
bool recursive);
|
||||
|
||||
/**
|
||||
* Finds all package orphans currently installed and adds them into
|
||||
* the transaction dictionary.
|
||||
*
|
||||
* @param[in] purge If true packages will also be purged.
|
||||
*
|
||||
* @return 0 on succcess, ENOENT if no package orphans were found, ENXIO
|
||||
* or EINVAL if a problem ocurred in the process.
|
||||
*/
|
||||
int xbps_transaction_autoremove_pkgs(bool purge);
|
||||
int xbps_transaction_autoremove_pkgs(void);
|
||||
|
||||
/**
|
||||
* Returns the transaction dictionary, as shown above in the image.
|
||||
@ -1452,8 +1461,9 @@ int xbps_repository_sync_pkg_index(const char *uri);
|
||||
*
|
||||
* <b>XBPS_PKG_STATE_BROKEN</b>: not yet used.
|
||||
*
|
||||
* <b>XBPS_PKG_STATE_CONFIG_FILES</b>: Package has been removed but not
|
||||
* yet purged.
|
||||
* <b>XBPS_PKG_STATE_HALF_REMOVED</b>: Package has been removed but not
|
||||
* completely: the purge action in REMOVE script wasn't executed, pkg
|
||||
* metadata directory still exists and is registered in package database.
|
||||
*
|
||||
* <b>XBPS_PKG_STATE_NOT_INSTALLED</b>: Package going to be installed in
|
||||
* a transaction dictionary but that has not been yet unpacked.
|
||||
@ -1462,7 +1472,7 @@ typedef enum pkg_state {
|
||||
XBPS_PKG_STATE_UNPACKED = 1,
|
||||
XBPS_PKG_STATE_INSTALLED,
|
||||
XBPS_PKG_STATE_BROKEN,
|
||||
XBPS_PKG_STATE_CONFIG_FILES,
|
||||
XBPS_PKG_STATE_HALF_REMOVED,
|
||||
XBPS_PKG_STATE_NOT_INSTALLED,
|
||||
XBPS_PKG_STATE_HALF_UNPACKED
|
||||
} pkg_state_t;
|
||||
|
@ -128,7 +128,7 @@ int HIDDEN xbps_repository_find_pkg_deps(prop_dictionary_t,
|
||||
* @private
|
||||
* From lib/package_requiredby.c
|
||||
*/
|
||||
int HIDDEN xbps_requiredby_pkg_add(prop_array_t, prop_dictionary_t);
|
||||
int HIDDEN xbps_requiredby_pkg_add(struct xbps_handle *, prop_dictionary_t);
|
||||
int HIDDEN xbps_requiredby_pkg_remove(const char *);
|
||||
|
||||
/**
|
||||
|
@ -44,7 +44,7 @@ EXTOBJS += external/match.o external/mkpath.o
|
||||
OBJS = package_configure.o package_config_files.o package_orphans.o
|
||||
OBJS += package_remove.o package_remove_obsoletes.o package_state.o
|
||||
OBJS += package_unpack.o package_requiredby.o package_register.o
|
||||
OBJS += package_purge.o transaction_commit.o transaction_package_replace.o
|
||||
OBJS += transaction_commit.o transaction_package_replace.o
|
||||
OBJS += transaction_dictionary.o transaction_sortdeps.o transaction_ops.o
|
||||
OBJS += download.o initend.o
|
||||
OBJS += plist.o plist_archive_entry.o plist_find.o plist_match.o
|
||||
|
@ -88,12 +88,14 @@ xbps_init(struct xbps_handle *xh)
|
||||
CFG_STR(__UNCONST("rootdir"), __UNCONST("/"), CFGF_NONE),
|
||||
CFG_STR(__UNCONST("cachedir"),
|
||||
__UNCONST(XBPS_CACHE_PATH), CFGF_NONE),
|
||||
CFG_INT(__UNCONST("fetch-cache-connections"),
|
||||
CFG_INT(__UNCONST("FetchCacheConnections"),
|
||||
XBPS_FETCH_CACHECONN, CFGF_NONE),
|
||||
CFG_INT(__UNCONST("fetch-cache-connections-per-host"),
|
||||
CFG_INT(__UNCONST("FetchCacheConnectionsPerHost"),
|
||||
XBPS_FETCH_CACHECONN_HOST, CFGF_NONE),
|
||||
CFG_INT(__UNCONST("fetch-timeout-connection"),
|
||||
CFG_INT(__UNCONST("FetchTimeoutConnection"),
|
||||
XBPS_FETCH_TIMEOUT, CFGF_NONE),
|
||||
CFG_INT(__UNCONST("TransactionFrequencyFlush"),
|
||||
XBPS_TRANS_FLUSH, CFGF_NONE),
|
||||
CFG_BOOL(__UNCONST("syslog"), true, CFGF_NONE),
|
||||
CFG_STR_LIST(__UNCONST("repositories"), NULL, CFGF_MULTI),
|
||||
CFG_SEC(__UNCONST("virtual-package"),
|
||||
@ -161,22 +163,27 @@ xbps_init(struct xbps_handle *xh)
|
||||
if (xhp->cfg == NULL) {
|
||||
xhp->syslog_enabled = true;
|
||||
xhp->fetch_timeout = XBPS_FETCH_TIMEOUT;
|
||||
xhp->transaction_frequency_flush = XBPS_TRANS_FLUSH;
|
||||
cc = XBPS_FETCH_CACHECONN;
|
||||
cch = XBPS_FETCH_CACHECONN_HOST;
|
||||
} else {
|
||||
xhp->syslog_enabled = cfg_getbool(xhp->cfg, "syslog");
|
||||
xhp->fetch_timeout = cfg_getint(xhp->cfg, "fetch-timeout-connection");
|
||||
cc = cfg_getint(xhp->cfg, "fetch-cache-connections");
|
||||
cch = cfg_getint(xhp->cfg, "fetch-cache-connections-per-host");
|
||||
xhp->fetch_timeout = cfg_getint(xhp->cfg, "FetchTimeoutConnection");
|
||||
cc = cfg_getint(xhp->cfg, "FetchCacheConnections");
|
||||
cch = cfg_getint(xhp->cfg, "FetchCacheConnectionsPerHost");
|
||||
xhp->transaction_frequency_flush =
|
||||
cfg_getint(xhp->cfg, "TransactionFrequencyFlush");
|
||||
}
|
||||
xbps_fetch_set_cache_connection(cc, cch);
|
||||
|
||||
xbps_dbg_printf("rootdir=%s\n", xhp->rootdir);
|
||||
xbps_dbg_printf("cachedir=%s\n", xhp->cachedir);
|
||||
xbps_dbg_printf("fetch-timeout=%u\n", xhp->fetch_timeout);
|
||||
xbps_dbg_printf("fetch-cacheconn=%u\n", cc);
|
||||
xbps_dbg_printf("fetch-cacheconn-host=%u\n", cch);
|
||||
xbps_dbg_printf("syslog=%u\n", xhp->syslog_enabled);
|
||||
xbps_dbg_printf("Rootdir=%s\n", xhp->rootdir);
|
||||
xbps_dbg_printf("Cachedir=%s\n", xhp->cachedir);
|
||||
xbps_dbg_printf("FetchTimeout=%u\n", xhp->fetch_timeout);
|
||||
xbps_dbg_printf("FetchCacheconn=%u\n", cc);
|
||||
xbps_dbg_printf("FetchCacheconnHost=%u\n", cch);
|
||||
xbps_dbg_printf("Syslog=%u\n", xhp->syslog_enabled);
|
||||
xbps_dbg_printf("TransactionFrequencyFlush=%u\n",
|
||||
xhp->transaction_frequency_flush);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -86,8 +86,7 @@ xbps_configure_pkg(const char *pkgname,
|
||||
rv = xbps_pkg_state_installed(pkgname, &state);
|
||||
if (rv == ENOENT) {
|
||||
/*
|
||||
* package not installed or has been removed
|
||||
* (must be purged) so ignore it.
|
||||
* package not installed or has been removed.
|
||||
*/
|
||||
return 0;
|
||||
} else if (rv != 0) {
|
||||
|
@ -90,9 +90,10 @@ find_orphan_pkg(prop_object_t obj, void *arg, bool *loop_done)
|
||||
if ((rv = xbps_pkg_state_dictionary(obj, &state)) != 0)
|
||||
return rv;
|
||||
/*
|
||||
* Skip packages that aren't fully installed.
|
||||
* Skip packages that aren't fully installed or half removed.
|
||||
*/
|
||||
if (state != XBPS_PKG_STATE_INSTALLED)
|
||||
if (state != XBPS_PKG_STATE_INSTALLED &&
|
||||
state != XBPS_PKG_STATE_HALF_REMOVED)
|
||||
return 0;
|
||||
|
||||
reqby = prop_dictionary_get(obj, "requiredby");
|
||||
|
@ -1,233 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2009-2011 Juan Romero Pardines.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include "xbps_api_impl.h"
|
||||
|
||||
/**
|
||||
* @file lib/package_purge.c
|
||||
* @brief Package purging routines
|
||||
* @defgroup purge Package purging functions
|
||||
*
|
||||
* These functions will purge an specified package or all packages.
|
||||
* Only packages in XBPS_PKG_STATE_CONFIG_FILES state will be processed
|
||||
* (unless overriden). Package purging steps:
|
||||
*
|
||||
* - Unmodified configuration files will be removed.
|
||||
* - The purge action in the REMOVE script will be executed (if found).
|
||||
* - Metadata files will be removed and package will be unregistered
|
||||
* with xbps_unregister_pkg().
|
||||
*/
|
||||
|
||||
static int
|
||||
remove_pkg_metadata(const char *pkgname,
|
||||
const char *version,
|
||||
const char *pkgver,
|
||||
const char *rootdir)
|
||||
{
|
||||
struct dirent *dp;
|
||||
DIR *dirp;
|
||||
char *metadir, *path;
|
||||
int rv = 0;
|
||||
|
||||
assert(pkgname != NULL);
|
||||
assert(rootdir != NULL);
|
||||
|
||||
metadir = xbps_xasprintf("%s/%s/metadata/%s", rootdir,
|
||||
XBPS_META_PATH, pkgname);
|
||||
if (metadir == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
dirp = opendir(metadir);
|
||||
if (dirp == NULL) {
|
||||
free(metadir);
|
||||
return errno;
|
||||
}
|
||||
|
||||
while ((dp = readdir(dirp)) != NULL) {
|
||||
if ((strcmp(dp->d_name, ".") == 0) ||
|
||||
(strcmp(dp->d_name, "..") == 0))
|
||||
continue;
|
||||
|
||||
path = xbps_xasprintf("%s/%s", metadir, dp->d_name);
|
||||
if (path == NULL) {
|
||||
(void)closedir(dirp);
|
||||
free(metadir);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
if (unlink(path) == -1) {
|
||||
xbps_set_cb_state(XBPS_STATE_PURGE_FAIL,
|
||||
errno, pkgname, version,
|
||||
"%s: [purge] failed to remove metafile `%s': %s",
|
||||
pkgver, path, strerror(errno));
|
||||
}
|
||||
free(path);
|
||||
}
|
||||
(void)closedir(dirp);
|
||||
rv = rmdir(metadir);
|
||||
free(metadir);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int
|
||||
purge_pkgs_cb(prop_object_t obj, void *arg, bool *done)
|
||||
{
|
||||
const char *pkgname;
|
||||
|
||||
(void)arg;
|
||||
(void)done;
|
||||
|
||||
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
|
||||
return xbps_purge_pkg(pkgname, true);
|
||||
}
|
||||
int
|
||||
xbps_purge_packages(void)
|
||||
{
|
||||
return xbps_regpkgdb_foreach_pkg_cb(purge_pkgs_cb, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
xbps_purge_pkg(const char *pkgname, bool check_state)
|
||||
{
|
||||
struct xbps_handle *xhp;
|
||||
prop_dictionary_t dict, pkgd;
|
||||
const char *version, *pkgver;
|
||||
char *buf;
|
||||
int rv = 0;
|
||||
pkg_state_t state;
|
||||
|
||||
assert(pkgname != NULL);
|
||||
xhp = xbps_handle_get();
|
||||
|
||||
/*
|
||||
* Firstly let's get the pkg dictionary from regpkgdb.
|
||||
*/
|
||||
pkgd = xbps_find_pkg_in_dict_by_name(xhp->regpkgdb_dictionary,
|
||||
"packages", pkgname);
|
||||
if (pkgd == NULL) {
|
||||
xbps_dbg_printf("[purge] %s: missing pkg dictionary (%s)\n",
|
||||
pkgname, strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver);
|
||||
prop_dictionary_get_cstring_nocopy(pkgd, "version", &version);
|
||||
xbps_set_cb_state(XBPS_STATE_PURGE, 0, pkgname, version, NULL);
|
||||
|
||||
if (check_state) {
|
||||
/*
|
||||
* Skip packages that aren't in "config-files" state.
|
||||
*/
|
||||
if ((rv = xbps_pkg_state_dictionary(pkgd, &state)) != 0)
|
||||
return rv;
|
||||
if (state != XBPS_PKG_STATE_CONFIG_FILES) {
|
||||
xbps_dbg_printf("[purge] %s not in config-files "
|
||||
"state.\n", pkgname);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Remove unmodified configuration files.
|
||||
*/
|
||||
dict = xbps_dictionary_from_metadata_plist(pkgname, XBPS_PKGFILES);
|
||||
if (dict == NULL) {
|
||||
xbps_set_cb_state(XBPS_STATE_PURGE_FAIL,
|
||||
errno, pkgname, version,
|
||||
"%s: [purge] failed to read metafile `%s': %s",
|
||||
pkgver, XBPS_PKGFILES, strerror(errno));
|
||||
if (errno != ENOENT)
|
||||
return errno;
|
||||
} else {
|
||||
if (prop_dictionary_get(dict, "conf_files")) {
|
||||
rv = xbps_remove_pkg_files(dict, "conf_files", pkgver);
|
||||
if (rv != 0) {
|
||||
prop_object_release(dict);
|
||||
xbps_set_cb_state(XBPS_STATE_PURGE_FAIL,
|
||||
rv, pkgname, version,
|
||||
"%s: [purge] failed to remove "
|
||||
"configuration files: %s",
|
||||
pkgver, strerror(rv));
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
prop_object_release(dict);
|
||||
}
|
||||
/*
|
||||
* Execute the purge action in REMOVE script (if found).
|
||||
*/
|
||||
if (chdir(xhp->rootdir) == -1) {
|
||||
rv = errno;
|
||||
xbps_set_cb_state(XBPS_STATE_PURGE_FAIL,
|
||||
rv, pkgname, version,
|
||||
"%s: [purge] failed to chdir to rootdir `%s': %s",
|
||||
pkgver, xhp->rootdir, strerror(rv));
|
||||
return rv;
|
||||
}
|
||||
buf = xbps_xasprintf("%s/metadata/%s/REMOVE", XBPS_META_PATH, pkgname);
|
||||
if (buf == NULL) {
|
||||
rv = ENOMEM;
|
||||
return rv;
|
||||
}
|
||||
if (access(buf, X_OK) == 0) {
|
||||
rv = xbps_file_exec(buf, "purge", pkgname, version,
|
||||
"no", xhp->conffile, NULL);
|
||||
if (rv != 0) {
|
||||
free(buf);
|
||||
if (errno && errno != ENOENT) {
|
||||
xbps_set_cb_state(XBPS_STATE_PURGE_FAIL,
|
||||
errno, pkgname, version,
|
||||
"%s: [purge] REMOVE script failed to "
|
||||
"execute purge ACTION: %s",
|
||||
pkgver, strerror(errno));
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(buf);
|
||||
/*
|
||||
* Remove metadata dir and unregister package.
|
||||
*/
|
||||
if ((rv = remove_pkg_metadata(pkgname, version, pkgver,
|
||||
xhp->rootdir)) != 0) {
|
||||
xbps_set_cb_state(XBPS_STATE_PURGE_FAIL,
|
||||
rv, pkgname, version,
|
||||
"%s: [purge] failed to remove metadata files: %s",
|
||||
pkgver, strerror(rv));
|
||||
if (rv != ENOENT)
|
||||
return rv;
|
||||
}
|
||||
if ((rv = xbps_unregister_pkg(pkgname, version)) != 0)
|
||||
return rv;
|
||||
|
||||
xbps_set_cb_state(XBPS_STATE_PURGE_DONE, 0, pkgname, version, NULL);
|
||||
|
||||
return rv;
|
||||
}
|
@ -43,20 +43,15 @@ int
|
||||
xbps_register_pkg(prop_dictionary_t pkgrd)
|
||||
{
|
||||
struct xbps_handle *xhp;
|
||||
prop_dictionary_t dict, pkgd;
|
||||
prop_array_t array, provides = NULL, reqby;
|
||||
prop_dictionary_t pkgd;
|
||||
prop_array_t provides, reqby, array;
|
||||
const char *pkgname, *version, *desc, *pkgver;
|
||||
char *plist;
|
||||
int rv = 0;
|
||||
bool autoinst = false;
|
||||
|
||||
assert(prop_object_type(pkgrd) == PROP_TYPE_DICTIONARY);
|
||||
|
||||
xhp = xbps_handle_get();
|
||||
plist = xbps_xasprintf("%s/%s/%s", xhp->rootdir,
|
||||
XBPS_META_PATH, XBPS_REGPKGDB);
|
||||
if (plist == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
prop_dictionary_get_cstring_nocopy(pkgrd, "pkgname", &pkgname);
|
||||
prop_dictionary_get_cstring_nocopy(pkgrd, "version", &version);
|
||||
@ -72,80 +67,72 @@ xbps_register_pkg(prop_dictionary_t pkgrd)
|
||||
assert(version != NULL);
|
||||
assert(desc != NULL);
|
||||
assert(pkgver != NULL);
|
||||
assert(xhp->regpkgdb != NULL);
|
||||
|
||||
if ((dict = prop_dictionary_internalize_from_zfile(plist)) != NULL) {
|
||||
pkgd = xbps_find_pkg_in_dict_by_name(dict,
|
||||
"packages", pkgname);
|
||||
if (pkgd == NULL) {
|
||||
rv = errno;
|
||||
goto out;
|
||||
}
|
||||
if (!prop_dictionary_set_cstring_nocopy(pkgd,
|
||||
"version", version)) {
|
||||
prop_object_release(pkgd);
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (!prop_dictionary_set_cstring_nocopy(pkgd,
|
||||
"pkgver", pkgver)) {
|
||||
prop_object_release(pkgd);
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (!prop_dictionary_set_cstring_nocopy(pkgd,
|
||||
"short_desc", desc)) {
|
||||
prop_object_release(pkgd);
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (reqby && !prop_dictionary_set(pkgd, "requiredby", reqby)) {
|
||||
prop_object_release(pkgd);
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
prop_dictionary_get_bool(pkgd, "automatic-install", &autoinst);
|
||||
if (xhp->install_reason_auto)
|
||||
autoinst = true;
|
||||
else if (xhp->install_reason_manual)
|
||||
autoinst = false;
|
||||
|
||||
if (!prop_dictionary_set_bool(pkgd,
|
||||
"automatic-install", autoinst)) {
|
||||
prop_object_release(pkgd);
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (provides) {
|
||||
if (!prop_dictionary_set(pkgd, "provides", provides)) {
|
||||
prop_object_release(pkgd);
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Add the requiredby objects for dependent packages.
|
||||
*/
|
||||
if (pkgrd && xbps_pkg_has_rundeps(pkgrd)) {
|
||||
array = prop_dictionary_get(dict, "packages");
|
||||
if (array == NULL) {
|
||||
prop_object_release(pkgd);
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if ((rv = xbps_requiredby_pkg_add(array, pkgrd)) != 0)
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* Write plist file to storage.
|
||||
*/
|
||||
if (!prop_dictionary_externalize_to_zfile(dict, plist)) {
|
||||
rv = errno;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
free(plist);
|
||||
return ENOENT;
|
||||
pkgd = xbps_regpkgdb_get_pkgd(pkgname, false);
|
||||
if (pkgd == NULL) {
|
||||
rv = ENOENT;
|
||||
goto out;
|
||||
}
|
||||
if (!prop_dictionary_set_cstring_nocopy(pkgd,
|
||||
"version", version)) {
|
||||
prop_object_release(pkgd);
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (!prop_dictionary_set_cstring_nocopy(pkgd,
|
||||
"pkgver", pkgver)) {
|
||||
prop_object_release(pkgd);
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (!prop_dictionary_set_cstring_nocopy(pkgd,
|
||||
"short_desc", desc)) {
|
||||
prop_object_release(pkgd);
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (reqby && !prop_dictionary_set(pkgd, "requiredby", reqby)) {
|
||||
prop_object_release(pkgd);
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
prop_dictionary_get_bool(pkgd, "automatic-install", &autoinst);
|
||||
if (xhp->install_reason_auto)
|
||||
autoinst = true;
|
||||
else if (xhp->install_reason_manual)
|
||||
autoinst = false;
|
||||
|
||||
if (!prop_dictionary_set_bool(pkgd,
|
||||
"automatic-install", autoinst)) {
|
||||
prop_object_release(pkgd);
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (provides) {
|
||||
if (!prop_dictionary_set(pkgd, "provides", provides)) {
|
||||
prop_object_release(pkgd);
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
array = prop_dictionary_get(xhp->regpkgdb, "packages");
|
||||
rv = xbps_array_replace_dict_by_name(array, pkgd, pkgname);
|
||||
if (rv != 0) {
|
||||
prop_object_release(pkgd);
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* Add the requiredby objects for dependent packages.
|
||||
*/
|
||||
if (pkgrd && xbps_pkg_has_rundeps(pkgrd)) {
|
||||
if ((rv = xbps_requiredby_pkg_add(xhp, pkgrd)) != 0) {
|
||||
prop_object_release(pkgd);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
prop_object_release(pkgd);
|
||||
|
||||
out:
|
||||
if (rv != 0) {
|
||||
xbps_set_cb_state(XBPS_STATE_REGISTER_FAIL,
|
||||
@ -153,8 +140,6 @@ out:
|
||||
"%s: failed to register package: %s",
|
||||
pkgver, strerror(rv));
|
||||
}
|
||||
prop_object_release(dict);
|
||||
free(plist);
|
||||
|
||||
return rv;
|
||||
}
|
||||
@ -163,31 +148,24 @@ int
|
||||
xbps_unregister_pkg(const char *pkgname, const char *version)
|
||||
{
|
||||
struct xbps_handle *xhp;
|
||||
char *plist;
|
||||
int rv = 0;
|
||||
int rv;
|
||||
|
||||
assert(pkgname != NULL);
|
||||
|
||||
xhp = xbps_handle_get();
|
||||
if ((rv = xbps_regpkgdb_dictionary_init(xhp)) != 0)
|
||||
return rv;
|
||||
|
||||
xbps_set_cb_state(XBPS_STATE_UNREGISTER, 0, pkgname, version, NULL);
|
||||
|
||||
xhp = xbps_handle_get();
|
||||
plist = xbps_xasprintf("%s/%s/%s", xhp->rootdir,
|
||||
XBPS_META_PATH, XBPS_REGPKGDB);
|
||||
if (plist == NULL) {
|
||||
rv = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (!xbps_remove_pkg_dict_from_plist_by_name(pkgname, plist)) {
|
||||
rv = errno;
|
||||
goto out;
|
||||
}
|
||||
out:
|
||||
if (rv != 0) {
|
||||
if (!xbps_remove_pkg_from_dict_by_name(xhp->regpkgdb,
|
||||
"packages", pkgname)) {
|
||||
xbps_set_cb_state(XBPS_STATE_UNREGISTER_FAIL,
|
||||
rv, pkgname, version,
|
||||
errno, pkgname, version,
|
||||
"%s: failed to unregister package: %s",
|
||||
pkgname, strerror(rv));
|
||||
pkgname, strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
free(plist);
|
||||
return rv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -42,14 +42,18 @@
|
||||
* files. Package removal steps:
|
||||
* -# Its <b>pre-remove</b> target specified in the REMOVE script
|
||||
* will be executed.
|
||||
* -# Its files, dirs and links will be removed. Modified files (not
|
||||
* matching its sha256 hash) are preserved, unless
|
||||
* -# Its links, files, conf_files and dirs will be removed.
|
||||
* Modified files (not matchings its sha256 hash) are preserved, unless
|
||||
* XBPS_FLAG_FORCE_REMOVE_FILES flag is set via xbps_init::flags member.
|
||||
* -# Its <b>post-remove</b> target specified in the REMOVE script
|
||||
* will be executed.
|
||||
* -# Its requiredby objects will be removed from the installed packages
|
||||
* database.
|
||||
* -# Its state will be changed to XBPS_PKG_STATE_CONFIG_FILES.
|
||||
* -# Its state will be changed to XBPS_PKG_STATE_HALF_UNPACKED.
|
||||
* -# Its <b>purge-remove</b> target specified in the REMOVE script
|
||||
* will be executed.
|
||||
* -# Its package metadata directory will be removed.
|
||||
* -# Package will be unregistered from package database.
|
||||
*
|
||||
* @note
|
||||
* -# If a package is going to be updated, only steps <b>1</b> and <b>4</b>
|
||||
@ -69,6 +73,58 @@
|
||||
* Text inside of white boxes are the key associated with the object, its
|
||||
* data type is specified on its edge, i.e string, array, integer, dictionary.
|
||||
*/
|
||||
static int
|
||||
remove_pkg_metadata(const char *pkgname,
|
||||
const char *version,
|
||||
const char *pkgver,
|
||||
const char *rootdir)
|
||||
{
|
||||
struct dirent *dp;
|
||||
DIR *dirp;
|
||||
char *metadir, *path;
|
||||
int rv = 0;
|
||||
|
||||
assert(pkgname != NULL);
|
||||
assert(rootdir != NULL);
|
||||
|
||||
metadir = xbps_xasprintf("%s/%s/metadata/%s", rootdir,
|
||||
XBPS_META_PATH, pkgname);
|
||||
if (metadir == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
dirp = opendir(metadir);
|
||||
if (dirp == NULL) {
|
||||
free(metadir);
|
||||
return errno;
|
||||
}
|
||||
|
||||
while ((dp = readdir(dirp)) != NULL) {
|
||||
if ((strcmp(dp->d_name, ".") == 0) ||
|
||||
(strcmp(dp->d_name, "..") == 0))
|
||||
continue;
|
||||
|
||||
path = xbps_xasprintf("%s/%s", metadir, dp->d_name);
|
||||
if (path == NULL) {
|
||||
(void)closedir(dirp);
|
||||
free(metadir);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
if (unlink(path) == -1) {
|
||||
xbps_set_cb_state(XBPS_STATE_PURGE_FAIL,
|
||||
errno, pkgname, version,
|
||||
"%s: [purge] failed to remove metafile `%s': %s",
|
||||
pkgver, path, strerror(errno));
|
||||
}
|
||||
free(path);
|
||||
}
|
||||
(void)closedir(dirp);
|
||||
rv = rmdir(metadir);
|
||||
free(metadir);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
xbps_remove_pkg_files(prop_dictionary_t dict,
|
||||
const char *key,
|
||||
@ -87,9 +143,8 @@ xbps_remove_pkg_files(prop_dictionary_t dict,
|
||||
xhp = xbps_handle_get();
|
||||
|
||||
array = prop_dictionary_get(dict, key);
|
||||
if (array == NULL)
|
||||
return EINVAL;
|
||||
else if (prop_array_count(array) == 0)
|
||||
if ((prop_object_type(array) != PROP_TYPE_ARRAY) ||
|
||||
prop_array_count(array) == 0)
|
||||
return 0;
|
||||
|
||||
iter = xbps_array_iter_from_dict(dict, key);
|
||||
@ -174,6 +229,7 @@ xbps_remove_pkg_files(prop_dictionary_t dict,
|
||||
errno, pkgname, version,
|
||||
"%s: failed to remove %s `%s': %s", pkgver,
|
||||
curobj, file, strerror(errno));
|
||||
errno = 0;
|
||||
} else {
|
||||
/* success */
|
||||
xbps_set_cb_state(XBPS_STATE_REMOVE_FILE,
|
||||
@ -193,47 +249,47 @@ int
|
||||
xbps_remove_pkg(const char *pkgname, const char *version, bool update)
|
||||
{
|
||||
struct xbps_handle *xhp;
|
||||
prop_dictionary_t dict;
|
||||
char *buf, *pkgver;
|
||||
prop_dictionary_t pkgd = NULL;
|
||||
char *buf = NULL, *pkgver = NULL;
|
||||
int rv = 0;
|
||||
bool rmfile_exists = false;
|
||||
pkg_state_t state = 0;
|
||||
|
||||
assert(pkgname != NULL);
|
||||
assert(version != NULL);
|
||||
|
||||
xhp = xbps_handle_get();
|
||||
/*
|
||||
* Check if pkg is installed before anything else.
|
||||
*/
|
||||
if (!xbps_check_is_installed_pkg_by_name(pkgname))
|
||||
return ENOENT;
|
||||
|
||||
pkgver = xbps_xasprintf("%s-%s", pkgname, version);
|
||||
if (pkgver == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
if (!update)
|
||||
xbps_set_cb_state(XBPS_STATE_REMOVE, 0, pkgname, version, NULL);
|
||||
|
||||
buf = xbps_xasprintf("%s/metadata/%s/REMOVE",
|
||||
XBPS_META_PATH, pkgname);
|
||||
if (buf == NULL) {
|
||||
rv = ENOMEM;
|
||||
free(pkgver);
|
||||
return rv;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pkgver = xbps_xasprintf("%s-%s", pkgname, version);
|
||||
if (pkgver == NULL) {
|
||||
rv = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((rv = xbps_pkg_state_installed(pkgname, &state)) != 0)
|
||||
goto out;
|
||||
|
||||
if (!update)
|
||||
xbps_set_cb_state(XBPS_STATE_REMOVE, 0, pkgname, version, NULL);
|
||||
|
||||
if (chdir(xhp->rootdir) == -1) {
|
||||
rv = errno;
|
||||
xbps_set_cb_state(XBPS_STATE_REMOVE_FAIL,
|
||||
rv, pkgname, version,
|
||||
"%s: [remove] failed to chdir to rootdir `%s': %s",
|
||||
pkgver, xhp->rootdir, strerror(rv));
|
||||
free(buf);
|
||||
free(pkgver);
|
||||
return rv;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* If package was "half-removed", remove it fully. */
|
||||
if (state == XBPS_PKG_STATE_HALF_REMOVED)
|
||||
goto purge;
|
||||
/*
|
||||
* Run the pre remove action.
|
||||
*/
|
||||
@ -246,18 +302,15 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
|
||||
"%s: [remove] REMOVE script failed to "
|
||||
"execute pre ACTION: %s",
|
||||
pkgver, strerror(errno));
|
||||
free(pkgver);
|
||||
free(buf);
|
||||
return errno;
|
||||
rv = errno;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
if (errno != ENOENT) {
|
||||
free(pkgver);
|
||||
free(buf);
|
||||
return errno;
|
||||
rv = errno;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If updating a package, we just need to execute the current
|
||||
* pre-remove action target, unregister its requiredby entries and
|
||||
@ -269,38 +322,26 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
|
||||
return xbps_requiredby_pkg_remove(pkgname);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove links, files and dirs.
|
||||
*/
|
||||
dict = xbps_dictionary_from_metadata_plist(pkgname, XBPS_PKGFILES);
|
||||
if (dict == NULL) {
|
||||
free(pkgver);
|
||||
free(buf);
|
||||
return errno;
|
||||
pkgd = xbps_dictionary_from_metadata_plist(pkgname, XBPS_PKGFILES);
|
||||
if (pkgd == NULL) {
|
||||
rv = errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Remove links */
|
||||
if ((rv = xbps_remove_pkg_files(dict, "links", pkgver)) != 0) {
|
||||
prop_object_release(dict);
|
||||
free(buf);
|
||||
free(pkgver);
|
||||
return rv;
|
||||
}
|
||||
if ((rv = xbps_remove_pkg_files(pkgd, "links", pkgver)) != 0)
|
||||
goto out;
|
||||
|
||||
/* Remove regular files */
|
||||
if ((rv = xbps_remove_pkg_files(dict, "files", pkgver)) != 0) {
|
||||
prop_object_release(dict);
|
||||
free(buf);
|
||||
free(pkgver);
|
||||
return rv;
|
||||
}
|
||||
if ((rv = xbps_remove_pkg_files(pkgd, "files", pkgver)) != 0)
|
||||
goto out;
|
||||
|
||||
/* Remove configuration files */
|
||||
if ((rv = xbps_remove_pkg_files(pkgd, "conf_files", pkgver)) != 0)
|
||||
goto out;
|
||||
|
||||
/* Remove dirs */
|
||||
if ((rv = xbps_remove_pkg_files(dict, "dirs", pkgver)) != 0) {
|
||||
prop_object_release(dict);
|
||||
free(buf);
|
||||
free(pkgver);
|
||||
return rv;
|
||||
}
|
||||
prop_object_release(dict);
|
||||
if ((rv = xbps_remove_pkg_files(pkgd, "dirs", pkgver)) != 0)
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* Execute the post REMOVE action if file exists and we aren't
|
||||
@ -313,12 +354,9 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
|
||||
errno, pkgname, version,
|
||||
"%s: [remove] REMOVE script failed to execute "
|
||||
"post ACTION: %s", pkgver, strerror(errno));
|
||||
free(buf);
|
||||
free(pkgver);
|
||||
return errno;
|
||||
rv = errno;
|
||||
goto out;
|
||||
}
|
||||
free(buf);
|
||||
|
||||
/*
|
||||
* Update the requiredby array of all required dependencies.
|
||||
*/
|
||||
@ -327,25 +365,64 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update)
|
||||
rv, pkgname, version,
|
||||
"%s: [remove] failed to remove requiredby entries: %s",
|
||||
pkgver, strerror(rv));
|
||||
free(pkgver);
|
||||
return rv;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set package state to "config-files".
|
||||
* Set package state to "half-removed".
|
||||
*/
|
||||
rv = xbps_set_pkg_state_installed(pkgname, version, pkgver,
|
||||
XBPS_PKG_STATE_CONFIG_FILES);
|
||||
XBPS_PKG_STATE_HALF_REMOVED);
|
||||
if (rv != 0) {
|
||||
xbps_set_cb_state(XBPS_STATE_REMOVE_FAIL,
|
||||
rv, pkgname, version,
|
||||
"%s: [remove] failed to set state to config-files: %s",
|
||||
"%s: [remove] failed to set state to half-removed: %s",
|
||||
pkgver, strerror(rv));
|
||||
} else {
|
||||
xbps_set_cb_state(XBPS_STATE_REMOVE_DONE,
|
||||
0, pkgname, version, NULL);
|
||||
goto out;
|
||||
}
|
||||
free(pkgver);
|
||||
|
||||
purge:
|
||||
/*
|
||||
* Execute the purge REMOVE action if file exists.
|
||||
*/
|
||||
if (access(buf, X_OK) == 0) {
|
||||
if (xbps_file_exec(buf, "purge", pkgname, version, "no",
|
||||
xhp->conffile, NULL) != 0) {
|
||||
rv = errno;
|
||||
xbps_set_cb_state(XBPS_STATE_REMOVE_FAIL,
|
||||
errno, pkgname, version,
|
||||
"%s: REMOVE script failed to execute "
|
||||
"purge ACTION: %s", pkgver, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Remove package metadata directory.
|
||||
*/
|
||||
rv = remove_pkg_metadata(pkgname, version, pkgver, xhp->rootdir);
|
||||
if (rv != 0) {
|
||||
xbps_set_cb_state(XBPS_STATE_REMOVE_FAIL,
|
||||
rv, pkgname, version,
|
||||
"%s: failed to remove metadata files: %s",
|
||||
pkgver, strerror(rv));
|
||||
if (rv != ENOENT)
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* Unregister package from regpkgdb.
|
||||
*/
|
||||
if ((rv = xbps_unregister_pkg(pkgname, version)) != 0)
|
||||
goto out;
|
||||
|
||||
xbps_set_cb_state(XBPS_STATE_REMOVE_DONE,
|
||||
0, pkgname, version, NULL);
|
||||
|
||||
out:
|
||||
if (buf != NULL)
|
||||
free(buf);
|
||||
if (pkgver != NULL)
|
||||
free(pkgver);
|
||||
if (pkgd != NULL)
|
||||
prop_object_release(pkgd);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -91,9 +91,10 @@ remove_pkg_from_reqby(prop_object_t obj, void *arg, bool *loop_done)
|
||||
if (reqby == NULL || prop_array_count(reqby) == 0)
|
||||
return 0;
|
||||
|
||||
if (xbps_match_pkgname_in_array(reqby, pkgname))
|
||||
if (xbps_match_pkgname_in_array(reqby, pkgname)) {
|
||||
if (!xbps_remove_pkgname_from_array(reqby, pkgname))
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -101,46 +102,12 @@ remove_pkg_from_reqby(prop_object_t obj, void *arg, bool *loop_done)
|
||||
int HIDDEN
|
||||
xbps_requiredby_pkg_remove(const char *pkgname)
|
||||
{
|
||||
struct xbps_handle *xhp;
|
||||
prop_dictionary_t dict;
|
||||
char *plist;
|
||||
int rv = 0;
|
||||
|
||||
assert(pkgname != NULL);
|
||||
|
||||
xhp = xbps_handle_get();
|
||||
plist = xbps_xasprintf("%s/%s/%s", xhp->rootdir,
|
||||
XBPS_META_PATH, XBPS_REGPKGDB);
|
||||
if (plist == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
if ((dict = prop_dictionary_internalize_from_zfile(plist)) == NULL) {
|
||||
free(plist);
|
||||
xbps_dbg_printf("[reqby-rm] cannot internalize "
|
||||
"regpkgdb plist for '%s': %s\n", pkgname, strerror(errno));
|
||||
return errno;
|
||||
}
|
||||
|
||||
rv = xbps_callback_array_iter_in_dict(dict, "packages",
|
||||
remove_pkg_from_reqby, __UNCONST(pkgname));
|
||||
if (rv != 0)
|
||||
goto out;
|
||||
|
||||
if (!prop_dictionary_externalize_to_zfile(dict, plist)) {
|
||||
xbps_dbg_printf("[reqby-rm] cannot externalize plist for "
|
||||
"'%s': %s\n", pkgname, strerror(errno));
|
||||
rv = errno;
|
||||
}
|
||||
|
||||
out:
|
||||
prop_object_release(dict);
|
||||
free(plist);
|
||||
|
||||
return rv;
|
||||
return xbps_regpkgdb_foreach_pkg_cb(remove_pkg_from_reqby, __UNCONST(pkgname));
|
||||
}
|
||||
|
||||
int HIDDEN
|
||||
xbps_requiredby_pkg_add(prop_array_t pkgs_array, prop_dictionary_t pkgd)
|
||||
xbps_requiredby_pkg_add(struct xbps_handle *xhp, prop_dictionary_t pkgd)
|
||||
{
|
||||
prop_array_t pkg_rdeps;
|
||||
prop_object_t obj, pkgd_regpkgdb;
|
||||
@ -148,7 +115,6 @@ xbps_requiredby_pkg_add(prop_array_t pkgs_array, prop_dictionary_t pkgd)
|
||||
const char *pkgver, *str;
|
||||
int rv = 0;
|
||||
|
||||
assert(prop_object_type(pkgs_array) == PROP_TYPE_ARRAY);
|
||||
assert(prop_object_type(pkgd) == PROP_TYPE_DICTIONARY);
|
||||
|
||||
prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver);
|
||||
@ -166,8 +132,8 @@ xbps_requiredby_pkg_add(prop_array_t pkgs_array, prop_dictionary_t pkgd)
|
||||
rv = EINVAL;
|
||||
break;
|
||||
}
|
||||
pkgd_regpkgdb =
|
||||
xbps_find_virtualpkg_in_array_by_pattern(pkgs_array, str);
|
||||
pkgd_regpkgdb = xbps_find_virtualpkg_in_dict_by_pattern(
|
||||
xhp->regpkgdb, "packages", str);
|
||||
if (pkgd_regpkgdb == NULL)
|
||||
return EINVAL;
|
||||
|
||||
|
@ -40,7 +40,7 @@ static const struct state states[] = {
|
||||
{ "unpacked", XBPS_PKG_STATE_UNPACKED },
|
||||
{ "installed", XBPS_PKG_STATE_INSTALLED },
|
||||
{ "broken", XBPS_PKG_STATE_BROKEN },
|
||||
{ "config-files", XBPS_PKG_STATE_CONFIG_FILES },
|
||||
{ "half-removed", XBPS_PKG_STATE_HALF_REMOVED },
|
||||
{ "not-installed", XBPS_PKG_STATE_NOT_INSTALLED },
|
||||
{ "half-unpacked", XBPS_PKG_STATE_HALF_UNPACKED },
|
||||
{ NULL, 0 }
|
||||
@ -68,7 +68,7 @@ set_new_state(prop_dictionary_t dict, pkg_state_t state)
|
||||
break;
|
||||
|
||||
if (stp->string == NULL)
|
||||
return -1;
|
||||
return EINVAL;
|
||||
|
||||
if (!prop_dictionary_set_cstring_nocopy(dict, "state", stp->string))
|
||||
return EINVAL;
|
||||
@ -110,7 +110,7 @@ xbps_pkg_state_installed(const char *pkgname, pkg_state_t *state)
|
||||
assert(pkgname != NULL);
|
||||
assert(state != NULL);
|
||||
|
||||
pkgd = xbps_find_pkg_dict_installed(pkgname, false);
|
||||
pkgd = xbps_regpkgdb_get_pkgd(pkgname, false);
|
||||
if (pkgd == NULL)
|
||||
return ENOENT;
|
||||
|
||||
@ -170,127 +170,80 @@ xbps_set_pkg_state_installed(const char *pkgname,
|
||||
pkg_state_t state)
|
||||
{
|
||||
struct xbps_handle *xhp;
|
||||
prop_dictionary_t dict = NULL, pkgd;
|
||||
prop_dictionary_t pkgd;
|
||||
prop_array_t array;
|
||||
char *metadir, *plist;
|
||||
int rv = 0;
|
||||
bool newpkg = false;
|
||||
int rv;
|
||||
|
||||
assert(pkgname != NULL);
|
||||
xhp = xbps_handle_get();
|
||||
|
||||
metadir = xbps_xasprintf("%s/%s", xhp->rootdir, XBPS_META_PATH);
|
||||
if (metadir == NULL)
|
||||
return ENOMEM;
|
||||
plist = xbps_xasprintf("%s/%s", metadir, XBPS_REGPKGDB);
|
||||
if (plist == NULL) {
|
||||
free(metadir);
|
||||
return ENOMEM;
|
||||
}
|
||||
if ((dict = prop_dictionary_internalize_from_zfile(plist)) == NULL) {
|
||||
dict = prop_dictionary_create();
|
||||
if (dict == NULL) {
|
||||
rv = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (xhp->regpkgdb == NULL) {
|
||||
xhp->regpkgdb = prop_dictionary_create();
|
||||
if (xhp->regpkgdb == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
array = prop_array_create();
|
||||
if (array == NULL) {
|
||||
rv = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
if (array == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
pkgd = prop_dictionary_create();
|
||||
if (pkgd == NULL) {
|
||||
rv = ENOMEM;
|
||||
prop_object_release(array);
|
||||
goto out;
|
||||
return ENOMEM;
|
||||
}
|
||||
if ((rv = set_pkg_objs(pkgd, pkgname, version, pkgver)) != 0) {
|
||||
prop_object_release(array);
|
||||
prop_object_release(pkgd);
|
||||
goto out;
|
||||
return rv;
|
||||
}
|
||||
if ((rv = set_new_state(pkgd, state)) != 0) {
|
||||
prop_object_release(array);
|
||||
prop_object_release(pkgd);
|
||||
goto out;
|
||||
return rv;
|
||||
}
|
||||
if (!xbps_add_obj_to_array(array, pkgd)) {
|
||||
rv = EINVAL;
|
||||
prop_object_release(array);
|
||||
prop_object_release(pkgd);
|
||||
goto out;
|
||||
return EINVAL;
|
||||
}
|
||||
if (!xbps_add_obj_to_dict(dict, array, "packages")) {
|
||||
rv = EINVAL;
|
||||
if (!xbps_add_obj_to_dict(xhp->regpkgdb, array, "packages")) {
|
||||
prop_object_release(array);
|
||||
goto out;
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
} else {
|
||||
pkgd = xbps_find_pkg_in_dict_by_name(dict,
|
||||
"packages", pkgname);
|
||||
pkgd = xbps_regpkgdb_get_pkgd(pkgname, false);
|
||||
if (pkgd == NULL) {
|
||||
if (errno && errno != ENOENT) {
|
||||
rv = errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
newpkg = true;
|
||||
pkgd = prop_dictionary_create();
|
||||
if ((rv = set_pkg_objs(pkgd, pkgname,
|
||||
version, pkgver)) != 0) {
|
||||
prop_object_release(pkgd);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
array = prop_dictionary_get(dict, "packages");
|
||||
if (array == NULL) {
|
||||
array = prop_array_create();
|
||||
if (!prop_dictionary_set(dict, "packages", array)) {
|
||||
rv = EINVAL;
|
||||
if (newpkg)
|
||||
prop_object_release(pkgd);
|
||||
goto out;
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
if ((rv = set_new_state(pkgd, state)) != 0) {
|
||||
if (newpkg)
|
||||
prop_object_release(pkgd);
|
||||
goto out;
|
||||
return rv;
|
||||
}
|
||||
if (newpkg && !xbps_add_obj_to_array(array, pkgd)) {
|
||||
rv = EINVAL;
|
||||
prop_object_release(pkgd);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create metadir if doesn't exist */
|
||||
if (access(metadir, X_OK) == -1) {
|
||||
if (errno == ENOENT) {
|
||||
if (xbps_mkpath(metadir, 0755) != 0) {
|
||||
xbps_dbg_printf("[pkgstate] failed to create "
|
||||
"metadir %s: %s\n", metadir,
|
||||
strerror(errno));
|
||||
rv = errno;
|
||||
goto out;
|
||||
array = prop_dictionary_get(xhp->regpkgdb, "packages");
|
||||
if (newpkg) {
|
||||
if (!xbps_add_obj_to_array(array, pkgd)) {
|
||||
prop_object_release(pkgd);
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Externalize regpkgdb plist file */
|
||||
if (!prop_dictionary_externalize_to_zfile(dict, plist)) {
|
||||
rv = errno;
|
||||
xbps_dbg_printf("[pkgstate] cannot write plist '%s': %s\n",
|
||||
plist, strerror(errno));
|
||||
}
|
||||
} else {
|
||||
if ((rv = xbps_array_replace_dict_by_name(array,
|
||||
pkgd, pkgname)) != 0)
|
||||
return rv;
|
||||
|
||||
out:
|
||||
if (prop_object_type(dict) == PROP_TYPE_DICTIONARY)
|
||||
prop_object_release(dict);
|
||||
if (metadir)
|
||||
free(metadir);
|
||||
if (plist)
|
||||
free(plist);
|
||||
prop_object_release(pkgd);
|
||||
}
|
||||
if (!prop_dictionary_set(xhp->regpkgdb, "packages", array))
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -192,7 +192,16 @@ unpack_archive(prop_dictionary_t pkg_repod, struct archive *ar)
|
||||
xucd->entry_extract_count = 0;
|
||||
xucd->entry_total_count = 0;
|
||||
}
|
||||
|
||||
if (access(xhp->rootdir, R_OK) == -1) {
|
||||
if (errno != ENOENT) {
|
||||
rv = errno;
|
||||
goto out;
|
||||
}
|
||||
if (xbps_mkpath(xhp->rootdir, 0750) == -1) {
|
||||
rv = errno;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (chdir(xhp->rootdir) == -1) {
|
||||
xbps_set_cb_state(XBPS_STATE_UNPACK_FAIL,
|
||||
errno, pkgname, version,
|
||||
|
@ -231,7 +231,7 @@ xbps_dictionary_from_metadata_plist(const char *pkgname,
|
||||
|
||||
if (access(plistf, R_OK) == -1) {
|
||||
pkgd = xbps_find_virtualpkg_dict_installed(pkgname, false);
|
||||
if (pkgd) {
|
||||
if (prop_object_type(pkgd) == PROP_TYPE_DICTIONARY) {
|
||||
free(plistf);
|
||||
prop_dictionary_get_cstring_nocopy(pkgd,
|
||||
"pkgname", &savedpkgname);
|
||||
|
@ -336,15 +336,15 @@ find_pkgd_installed(const char *str, bool bypattern, bool virtual)
|
||||
|
||||
/* try normal pkg */
|
||||
if (virtual == false) {
|
||||
pkgd = find_pkg_in_dict(xhp->regpkgdb_dictionary,
|
||||
pkgd = find_pkg_in_dict(xhp->regpkgdb,
|
||||
"packages", str, bypattern, false);
|
||||
} else {
|
||||
/* virtual pkg set by user in conf */
|
||||
pkgd = find_virtualpkg_user_in_dict(xhp->regpkgdb_dictionary,
|
||||
pkgd = find_virtualpkg_user_in_dict(xhp->regpkgdb,
|
||||
"packages", str, bypattern);
|
||||
if (pkgd == NULL) {
|
||||
/* any virtual pkg in dictionary matching pattern */
|
||||
pkgd = find_pkg_in_dict(xhp->regpkgdb_dictionary,
|
||||
pkgd = find_pkg_in_dict(xhp->regpkgdb,
|
||||
"packages", str, bypattern, true);
|
||||
}
|
||||
}
|
||||
|
@ -42,16 +42,20 @@
|
||||
static bool
|
||||
remove_string_from_array(prop_array_t array, const char *str, int mode)
|
||||
{
|
||||
prop_object_iterator_t iter;
|
||||
prop_object_t obj;
|
||||
const char *curname, *pkgdep;
|
||||
char *curpkgname;
|
||||
size_t i, idx = 0;
|
||||
size_t idx = 0;
|
||||
bool found = false;
|
||||
|
||||
assert(prop_object_type(array) == PROP_TYPE_ARRAY);
|
||||
|
||||
for (i = 0; i < prop_array_count(array); i++) {
|
||||
obj = prop_array_get(array, i);
|
||||
iter = prop_array_iterator(array);
|
||||
if (iter == NULL)
|
||||
return false;
|
||||
|
||||
while ((obj = prop_object_iterator_next(iter))) {
|
||||
if (mode == 0) {
|
||||
/* exact match, obj is a string */
|
||||
if (prop_string_equals_cstring(obj, str)) {
|
||||
@ -81,8 +85,12 @@ remove_string_from_array(prop_array_t array, const char *str, int mode)
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
if (!found)
|
||||
prop_object_iterator_release(iter);
|
||||
|
||||
if (!found) {
|
||||
errno = ENOENT;
|
||||
return false;
|
||||
}
|
||||
|
||||
prop_array_remove(array, idx);
|
||||
return true;
|
||||
@ -121,7 +129,10 @@ xbps_remove_pkg_from_dict_by_name(prop_dictionary_t dict,
|
||||
if (array == NULL)
|
||||
return false;
|
||||
|
||||
return xbps_remove_pkg_from_array_by_name(array, pkgname);
|
||||
if (!xbps_remove_pkg_from_array_by_name(array, pkgname))
|
||||
return false;
|
||||
|
||||
return prop_dictionary_set(dict, key, array);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -56,45 +56,94 @@
|
||||
* dictionary.
|
||||
*/
|
||||
|
||||
static bool regpkgdb_initialized;
|
||||
|
||||
int HIDDEN
|
||||
xbps_regpkgdb_dictionary_init(struct xbps_handle *xhp)
|
||||
{
|
||||
char *plist;
|
||||
int rv;
|
||||
|
||||
if (regpkgdb_initialized)
|
||||
assert(xhp != NULL);
|
||||
|
||||
if (xhp->regpkgdb != NULL)
|
||||
return 0;
|
||||
|
||||
rv = xbps_regpkgdb_update(xhp, false);
|
||||
if (rv != 0) {
|
||||
if (rv != ENOENT)
|
||||
xbps_dbg_printf("[regpkgdb] cannot internalize "
|
||||
"regpkgdb dictionary: %s\n", strerror(rv));
|
||||
|
||||
return rv;
|
||||
}
|
||||
xbps_dbg_printf("[regpkgdb] initialized ok.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
xbps_regpkgdb_update(struct xbps_handle *xhp, bool flush)
|
||||
{
|
||||
char *plist, *metadir;
|
||||
int rv = 0;
|
||||
|
||||
plist = xbps_xasprintf("%s/%s/%s", xhp->rootdir,
|
||||
XBPS_META_PATH, XBPS_REGPKGDB);
|
||||
if (plist == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
xhp->regpkgdb_dictionary =
|
||||
prop_dictionary_internalize_from_zfile(plist);
|
||||
if (xhp->regpkgdb_dictionary == NULL) {
|
||||
free(plist);
|
||||
if (errno != ENOENT)
|
||||
xbps_dbg_printf("[regpkgdb] cannot internalize "
|
||||
"regpkgdb dictionary: %s\n", strerror(errno));
|
||||
return errno;
|
||||
if (xhp->regpkgdb != NULL && flush) {
|
||||
metadir = xbps_xasprintf("%s/%s", xhp->rootdir,
|
||||
XBPS_META_PATH);
|
||||
if (metadir == NULL) {
|
||||
free(plist);
|
||||
return ENOMEM;
|
||||
}
|
||||
/* Create metadir if doesn't exist */
|
||||
if (access(metadir, X_OK) == -1) {
|
||||
if (errno == ENOENT) {
|
||||
if (xbps_mkpath(metadir, 0755) != 0) {
|
||||
xbps_dbg_printf("[regpkgdb] failed to "
|
||||
"create metadir %s: %s\n", metadir,
|
||||
strerror(errno));
|
||||
rv = errno;
|
||||
free(metadir);
|
||||
free(plist);
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
free(plist);
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
free(metadir);
|
||||
/* flush dictionary to storage */
|
||||
if (!prop_dictionary_externalize_to_zfile(xhp->regpkgdb,
|
||||
plist)) {
|
||||
free(plist);
|
||||
return errno;
|
||||
}
|
||||
prop_object_release(xhp->regpkgdb);
|
||||
xhp->regpkgdb = NULL;
|
||||
}
|
||||
free(plist);
|
||||
regpkgdb_initialized = true;
|
||||
xbps_dbg_printf("[regpkgdb] initialized ok.\n");
|
||||
/* update copy in memory */
|
||||
xhp->regpkgdb = prop_dictionary_internalize_from_zfile(plist);
|
||||
if (xhp->regpkgdb == NULL)
|
||||
rv = errno;
|
||||
|
||||
return 0;
|
||||
free(plist);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void HIDDEN
|
||||
xbps_regpkgdb_dictionary_release(struct xbps_handle *xhp)
|
||||
{
|
||||
if (!regpkgdb_initialized)
|
||||
assert(xhp != NULL);
|
||||
|
||||
if (xhp->regpkgdb == NULL)
|
||||
return;
|
||||
|
||||
prop_object_release(xhp->regpkgdb_dictionary);
|
||||
regpkgdb_initialized = false;
|
||||
prop_object_release(xhp->regpkgdb);
|
||||
xhp->regpkgdb = NULL;
|
||||
xbps_dbg_printf("[regpkgdb] released ok.\n");
|
||||
}
|
||||
|
||||
@ -103,36 +152,19 @@ foreach_pkg_cb(int (*fn)(prop_object_t, void *, bool *),
|
||||
void *arg,
|
||||
bool reverse)
|
||||
{
|
||||
prop_array_t array;
|
||||
prop_object_t obj;
|
||||
struct xbps_handle *xhp = xbps_handle_get();
|
||||
size_t i, cnt;
|
||||
int rv;
|
||||
bool done = false;
|
||||
|
||||
/* initialize regpkgdb */
|
||||
if ((rv = xbps_regpkgdb_dictionary_init(xhp)) != 0)
|
||||
return rv;
|
||||
|
||||
array = prop_dictionary_get(xhp->regpkgdb_dictionary, "packages");
|
||||
if (prop_object_type(array) != PROP_TYPE_ARRAY)
|
||||
return EINVAL;
|
||||
|
||||
cnt = prop_array_count(array);
|
||||
if (reverse) {
|
||||
while (cnt--) {
|
||||
obj = prop_array_get(array, cnt);
|
||||
rv = (*fn)(obj, arg, &done);
|
||||
if (rv != 0 || done)
|
||||
break;
|
||||
}
|
||||
rv = xbps_callback_array_iter_reverse_in_dict(
|
||||
xhp->regpkgdb, "packages", fn, arg);
|
||||
} else {
|
||||
for (i = 0; i < cnt; i++) {
|
||||
obj = prop_array_get(array, i);
|
||||
rv = (*fn)(obj, arg, &done);
|
||||
if (rv != 0 || done)
|
||||
break;
|
||||
}
|
||||
rv = xbps_callback_array_iter_in_dict(
|
||||
xhp->regpkgdb, "packages", fn, arg);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@ -150,3 +182,22 @@ xbps_regpkgdb_foreach_pkg_cb(int (*fn)(prop_object_t, void *, bool *),
|
||||
{
|
||||
return foreach_pkg_cb(fn, arg, false);
|
||||
}
|
||||
|
||||
prop_dictionary_t
|
||||
xbps_regpkgdb_get_pkgd(const char *pkg, bool bypattern)
|
||||
{
|
||||
struct xbps_handle *xhp = xbps_handle_get();
|
||||
prop_dictionary_t pkgd = NULL;
|
||||
|
||||
if (xbps_regpkgdb_dictionary_init(xhp) != 0)
|
||||
return NULL;
|
||||
|
||||
if (bypattern)
|
||||
pkgd = xbps_find_pkg_in_dict_by_pattern(xhp->regpkgdb,
|
||||
"packages", pkg);
|
||||
else
|
||||
pkgd = xbps_find_pkg_in_dict_by_name(xhp->regpkgdb,
|
||||
"packages", pkg);
|
||||
|
||||
return prop_dictionary_copy(pkgd);
|
||||
}
|
||||
|
@ -164,13 +164,14 @@ xbps_transaction_commit(prop_dictionary_t transd)
|
||||
struct xbps_handle *xhp;
|
||||
prop_object_t obj;
|
||||
prop_object_iterator_t iter;
|
||||
size_t i;
|
||||
const char *pkgname, *version, *pkgver, *tract;
|
||||
int rv = 0;
|
||||
bool update, install, purge;
|
||||
bool update, install;
|
||||
|
||||
assert(prop_object_type(transd) == PROP_TYPE_DICTIONARY);
|
||||
|
||||
update = install = purge = false;
|
||||
update = install = false;
|
||||
xhp = xbps_handle_get();
|
||||
iter = xbps_array_iter_from_dict(transd, "packages");
|
||||
if (iter == NULL)
|
||||
@ -193,7 +194,16 @@ xbps_transaction_commit(prop_dictionary_t transd)
|
||||
*/
|
||||
xbps_set_cb_state(XBPS_STATE_TRANS_RUN, 0, NULL, NULL, NULL);
|
||||
|
||||
i = 0;
|
||||
while ((obj = prop_object_iterator_next(iter)) != NULL) {
|
||||
if ((xhp->transaction_frequency_flush > 0) &&
|
||||
(++i >= xhp->transaction_frequency_flush)) {
|
||||
rv = xbps_regpkgdb_update(xhp, true);
|
||||
if (rv != 0 && rv != ENOENT)
|
||||
goto out;
|
||||
|
||||
i = 0;
|
||||
}
|
||||
update = false;
|
||||
prop_dictionary_get_cstring_nocopy(obj, "transaction", &tract);
|
||||
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
|
||||
@ -201,22 +211,15 @@ xbps_transaction_commit(prop_dictionary_t transd)
|
||||
prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
|
||||
|
||||
if (strcmp(tract, "remove") == 0) {
|
||||
purge = update = false;
|
||||
update = false;
|
||||
/*
|
||||
* Remove and optionally also purge package.
|
||||
* Remove package.
|
||||
*/
|
||||
prop_dictionary_get_bool(obj, "remove-and-update",
|
||||
&update);
|
||||
prop_dictionary_get_bool(obj, "remove-and-purge",
|
||||
&purge);
|
||||
rv = xbps_remove_pkg(pkgname, version, update);
|
||||
if (rv != 0)
|
||||
goto out;
|
||||
if (update || !purge)
|
||||
continue;
|
||||
|
||||
if ((rv = xbps_purge_pkg(pkgname, false)) != 0)
|
||||
goto out;
|
||||
} else if (strcmp(tract, "configure") == 0) {
|
||||
/*
|
||||
* Reconfigure pending package.
|
||||
@ -269,6 +272,10 @@ xbps_transaction_commit(prop_dictionary_t transd)
|
||||
}
|
||||
prop_object_iterator_reset(iter);
|
||||
|
||||
/* force a flush now packages were removed/unpacked */
|
||||
if ((rv = xbps_regpkgdb_update(xhp, true)) != 0)
|
||||
goto out;
|
||||
|
||||
/* if there are no packages to install or update we are done */
|
||||
if (!update && !install)
|
||||
goto out;
|
||||
@ -277,11 +284,21 @@ xbps_transaction_commit(prop_dictionary_t transd)
|
||||
*/
|
||||
xbps_set_cb_state(XBPS_STATE_TRANS_CONFIGURE, 0, NULL, NULL, NULL);
|
||||
|
||||
i = 0;
|
||||
while ((obj = prop_object_iterator_next(iter)) != NULL) {
|
||||
if (xhp->transaction_frequency_flush > 0 &&
|
||||
++i >= xhp->transaction_frequency_flush) {
|
||||
if ((rv = xbps_regpkgdb_update(xhp, true)) != 0)
|
||||
goto out;
|
||||
|
||||
i = 0;
|
||||
}
|
||||
|
||||
prop_dictionary_get_cstring_nocopy(obj, "transaction", &tract);
|
||||
if ((strcmp(tract, "remove") == 0) ||
|
||||
(strcmp(tract, "configure") == 0))
|
||||
continue;
|
||||
|
||||
prop_dictionary_get_cstring_nocopy(obj, "pkgname", &pkgname);
|
||||
prop_dictionary_get_cstring_nocopy(obj, "version", &version);
|
||||
update = false;
|
||||
@ -304,6 +321,8 @@ xbps_transaction_commit(prop_dictionary_t transd)
|
||||
}
|
||||
}
|
||||
|
||||
/* Force a flush now that packages are configured */
|
||||
rv = xbps_regpkgdb_update(xhp, true);
|
||||
out:
|
||||
prop_object_iterator_release(iter);
|
||||
|
||||
|
@ -178,6 +178,8 @@ compute_transaction_stats(void)
|
||||
pkg_metad =
|
||||
xbps_dictionary_from_metadata_plist(pkgname,
|
||||
XBPS_PKGPROPS);
|
||||
if (pkg_metad == NULL)
|
||||
continue;
|
||||
prop_dictionary_get_uint64(pkg_metad,
|
||||
"installed_size", &tsize);
|
||||
prop_object_release(pkg_metad);
|
||||
|
@ -227,7 +227,7 @@ xbps_transaction_install_pkg(const char *pkgpattern)
|
||||
}
|
||||
|
||||
int
|
||||
xbps_transaction_remove_pkg(const char *pkgname, bool purge, bool recursive)
|
||||
xbps_transaction_remove_pkg(const char *pkgname, bool recursive)
|
||||
{
|
||||
prop_dictionary_t transd, pkgd;
|
||||
prop_array_t mdeps, orphans, orphans_pkg, unsorted, reqby;
|
||||
@ -238,11 +238,9 @@ xbps_transaction_remove_pkg(const char *pkgname, bool purge, bool recursive)
|
||||
|
||||
assert(pkgname != NULL);
|
||||
|
||||
pkgd = xbps_find_pkg_dict_installed(pkgname, false);
|
||||
if (prop_object_type(pkgd) != PROP_TYPE_DICTIONARY) {
|
||||
if ((pkgd = xbps_regpkgdb_get_pkgd(pkgname, false)) == NULL) {
|
||||
/* pkg not installed */
|
||||
rv = ENOENT;
|
||||
goto out;
|
||||
return ENOENT;
|
||||
}
|
||||
/*
|
||||
* Prepare transaction dictionary and missing deps array.
|
||||
@ -267,6 +265,7 @@ xbps_transaction_remove_pkg(const char *pkgname, bool purge, bool recursive)
|
||||
rv = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
prop_array_set_cstring_nocopy(orphans_pkg, 0, pkgname);
|
||||
orphans = xbps_find_pkg_orphans(orphans_pkg);
|
||||
prop_object_release(orphans_pkg);
|
||||
@ -274,13 +273,12 @@ xbps_transaction_remove_pkg(const char *pkgname, bool purge, bool recursive)
|
||||
rv = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
count = prop_array_count(orphans);
|
||||
while (count--) {
|
||||
obj = prop_array_get(orphans, count);
|
||||
prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
|
||||
prop_dictionary_set_cstring_nocopy(obj, "transaction", "remove");
|
||||
if (purge)
|
||||
prop_dictionary_set_bool(obj, "remove-and-purge", true);
|
||||
prop_array_add(unsorted, obj);
|
||||
xbps_dbg_printf("%s: added into transaction (remove).\n", pkgver);
|
||||
}
|
||||
@ -291,8 +289,6 @@ rmpkg:
|
||||
*/
|
||||
prop_dictionary_get_cstring_nocopy(pkgd, "pkgver", &pkgver);
|
||||
prop_dictionary_set_cstring_nocopy(pkgd, "transaction", "remove");
|
||||
if (purge)
|
||||
prop_dictionary_set_bool(pkgd, "remove-and-purge", true);
|
||||
prop_array_add(unsorted, pkgd);
|
||||
xbps_dbg_printf("%s: added into transaction (remove).\n", pkgver);
|
||||
reqby = prop_dictionary_get(pkgd, "requiredby");
|
||||
@ -303,15 +299,15 @@ rmpkg:
|
||||
if ((prop_object_type(reqby) == PROP_TYPE_ARRAY) &&
|
||||
(prop_array_count(reqby) > 0))
|
||||
rv = EEXIST;
|
||||
|
||||
out:
|
||||
if (prop_object_type(pkgd) == PROP_TYPE_DICTIONARY)
|
||||
prop_object_release(pkgd);
|
||||
prop_object_release(pkgd);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
xbps_transaction_autoremove_pkgs(bool purge)
|
||||
xbps_transaction_autoremove_pkgs(void)
|
||||
{
|
||||
prop_dictionary_t transd;
|
||||
prop_array_t orphans, mdeps, unsorted;
|
||||
@ -350,8 +346,6 @@ xbps_transaction_autoremove_pkgs(bool purge)
|
||||
prop_dictionary_get_cstring_nocopy(obj, "pkgver", &pkgver);
|
||||
prop_dictionary_set_cstring_nocopy(obj,
|
||||
"transaction", "remove");
|
||||
if (purge)
|
||||
prop_dictionary_set_bool(obj, "remove-and-purge", true);
|
||||
prop_array_add(unsorted, obj);
|
||||
xbps_dbg_printf("%s: added into transaction (remove).\n",
|
||||
pkgver);
|
||||
|
@ -121,8 +121,7 @@ xbps_transaction_package_replace(prop_dictionary_t transd)
|
||||
* If new package is providing a virtual package to the
|
||||
* package that we want to replace we should respect
|
||||
* its requiredby and automatic-install objects, so copy
|
||||
* them to the pkg's dictionary in transaction. Also
|
||||
* make sure that replaced package is also purged.
|
||||
* them to the pkg's dictionary in transaction.
|
||||
*/
|
||||
if (xbps_match_virtual_pkg_in_dict(pkg_repod,
|
||||
pattern, true) ||
|
||||
@ -135,8 +134,6 @@ xbps_transaction_package_replace(prop_dictionary_t transd)
|
||||
}
|
||||
prop_dictionary_set_bool(pkg_repod,
|
||||
"automatic-install", instd_auto);
|
||||
prop_dictionary_set_bool(instd,
|
||||
"remove-and-purge", true);
|
||||
}
|
||||
/*
|
||||
* Add package dictionary into the transaction and mark
|
||||
|
Loading…
Reference in New Issue
Block a user