diff --git a/NEWS b/NEWS index 76704548..fb984865 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,11 @@ xbps-0.16 (???): + * libxbps: introduce the concept of "soft replace". When a package + contains that boolean object set in pkg's metadata props.plist, + some steps will be skipped at remove time for the package being + replaced: its files won't be removed and the post action in REMOVE + file won't be executed. + * libxbps: change the order in which package files are removed: current: files, conf_files, links, directories. diff --git a/include/xbps_api.h b/include/xbps_api.h index b4de93b4..43e359f5 100644 --- a/include/xbps_api.h +++ b/include/xbps_api.h @@ -56,7 +56,7 @@ */ #define XBPS_PKGINDEX_VERSION "1.4" -#define XBPS_API_VERSION "20120525" +#define XBPS_API_VERSION "20120525-1" #define XBPS_VERSION "0.16" /** @@ -1330,10 +1330,13 @@ int xbps_unregister_pkg(const char *pkgname, const char *version, bool flush); * @param[in] version Package version associated. * @param[in] update If true, some steps will be skipped. See in the * detailed description above for more information. + * @param[in] soft_replace If true, some steps will be skipped. See in + * the detailed description above for more information. * * @return 0 on success, otherwise an errno value. */ -int xbps_remove_pkg(const char *pkgname, const char *version, bool update); +int xbps_remove_pkg(const char *pkgname, const char *version, bool update, + bool soft_replace); /** * Remove files defined in a proplib array as specified by \a key diff --git a/lib/package_remove.c b/lib/package_remove.c index d6cdd331..274c91a5 100644 --- a/lib/package_remove.c +++ b/lib/package_remove.c @@ -264,7 +264,8 @@ xbps_remove_pkg_files(prop_dictionary_t dict, } int -xbps_remove_pkg(const char *pkgname, const char *version, bool update) +xbps_remove_pkg(const char *pkgname, const char *version, bool update, + bool soft_replace) { struct xbps_handle *xhp; prop_dictionary_t pkgd = NULL; @@ -343,6 +344,13 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update) free(pkgver); free(buf); return xbps_requiredby_pkg_remove(pkgname); + } else if (soft_replace) { + /* + * Soft replace a package. Do not remove its files, but + * execute PURGE action, remove metadata files and unregister + * from pkgdb. + */ + goto softreplace; } pkgd = xbps_dictionary_from_metadata_plist(pkgname, XBPS_PKGFILES); @@ -383,6 +391,8 @@ xbps_remove_pkg(const char *pkgname, const char *version, bool update) pkgver, strerror(rv)); goto out; } + +softreplace: /* * Set package state to "half-removed". */ diff --git a/lib/transaction_commit.c b/lib/transaction_commit.c index d9412c61..cbae97d0 100644 --- a/lib/transaction_commit.c +++ b/lib/transaction_commit.c @@ -190,7 +190,7 @@ xbps_transaction_commit(void) size_t i; const char *pkgname, *version, *pkgver, *tract; int rv = 0; - bool update, install; + bool update, install, sr; assert(prop_object_type(xhp->transd) == PROP_TYPE_DICTIONARY); @@ -234,12 +234,14 @@ xbps_transaction_commit(void) if (strcmp(tract, "remove") == 0) { update = false; + sr = false; /* * Remove package. */ prop_dictionary_get_bool(obj, "remove-and-update", &update); - rv = xbps_remove_pkg(pkgname, version, update); + prop_dictionary_get_bool(obj, "softreplace", &sr); + rv = xbps_remove_pkg(pkgname, version, update, sr); if (rv != 0) goto out; } else if (strcmp(tract, "configure") == 0) { @@ -265,7 +267,8 @@ xbps_transaction_commit(void) */ xbps_set_cb_state(XBPS_STATE_UPDATE, 0, pkgname, version, NULL); - rv = xbps_remove_pkg(pkgname, version, true); + rv = xbps_remove_pkg(pkgname, version, + true, false); if (rv != 0) { xbps_set_cb_state( XBPS_STATE_UPDATE_FAIL, diff --git a/lib/transaction_package_replace.c b/lib/transaction_package_replace.c index f5a19730..9bf07f37 100644 --- a/lib/transaction_package_replace.c +++ b/lib/transaction_package_replace.c @@ -40,7 +40,7 @@ xbps_transaction_package_replace(prop_dictionary_t transd) prop_object_t obj; prop_object_iterator_t iter; const char *pattern, *pkgname, *curpkgname, *pkgver, *curpkgver; - bool instd_auto; + bool instd_auto, sr; size_t idx; assert(prop_object_type(transd) == PROP_TYPE_DICTIONARY); @@ -141,6 +141,22 @@ xbps_transaction_package_replace(prop_dictionary_t transd) prop_dictionary_set_bool(pkg_repod, "automatic-install", instd_auto); } + /* + * Copy requiredby and automatic-install objects + * from replaced package into pkg's dictionary + * for "softreplace" packages. + */ + sr = false; + prop_dictionary_get_bool(pkg_repod, "softreplace", &sr); + if (sr) { + if (instd_reqby && + prop_array_count(instd_reqby)) { + prop_dictionary_set(pkg_repod, + "requiredby", instd_reqby); + } + prop_dictionary_set_bool(pkg_repod, + "automatic-install", instd_auto); + } /* * Add package dictionary into the transaction and mark * it as to be "removed".