Merged purge code in remove, configurable transaction regpkgdb flushing.

See the NEWS file for info.
This commit is contained in:
Juan RP
2011-12-24 01:05:26 +01:00
parent d7a32a7eca
commit 3b7491d29b
32 changed files with 613 additions and 818 deletions

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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");

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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,

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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