diff --git a/include/xbps_api.h b/include/xbps_api.h index 1b0e5247..e97d44f3 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-2" +#define XBPS_API_VERSION "20120525-3" #define XBPS_VERSION "0.16" /** diff --git a/lib/package_unpack.c b/lib/package_unpack.c index e193ee18..5ff0452d 100644 --- a/lib/package_unpack.c +++ b/lib/package_unpack.c @@ -166,13 +166,17 @@ unpack_archive(prop_dictionary_t pkg_repod, struct archive *ar) char *buf = NULL, *pkgfilesd = NULL; int rv, flags; bool preserve, update, conf_file, file_exists, skip_obsoletes; + bool softreplace; assert(prop_object_type(pkg_repod) == PROP_TYPE_DICTIONARY); assert(ar != NULL); - preserve = update = conf_file = file_exists = skip_obsoletes = false; + preserve = update = conf_file = file_exists = false; + skip_obsoletes = softreplace = false; + prop_dictionary_get_bool(pkg_repod, "preserve", &preserve); prop_dictionary_get_bool(pkg_repod, "skip-obsoletes", &skip_obsoletes); + prop_dictionary_get_bool(pkg_repod, "softreplace", &softreplace); prop_dictionary_get_cstring_nocopy(pkg_repod, "transaction", &transact); prop_dictionary_get_cstring_nocopy(pkg_repod, "pkgname", &pkgname); @@ -480,9 +484,9 @@ unpack_archive(prop_dictionary_t pkg_repod, struct archive *ar) } /* * Skip checking for obsolete files on: - * - New package installation. - * - Package with "preserve" keyword. - * - Package with "skip-obsoletes" keyword. + * - New package installation without "softreplace" keyword. + * - Package with "preserve" keyword. + * - Package with "skip-obsoletes" keyword. */ pkgfilesd = xbps_xasprintf("%s/metadata/%s/%s", XBPS_META_PATH, pkgname, XBPS_PKGFILES); @@ -490,10 +494,12 @@ unpack_archive(prop_dictionary_t pkg_repod, struct archive *ar) rv = ENOMEM; goto out; } - if (skip_obsoletes || preserve || !update) + if (skip_obsoletes || preserve || (!softreplace && !update)) goto out1; /* - * Check for obsolete files. + * Check for obsolete files on: + * - Package upgrade. + * - Package with "softreplace" keyword. */ old_filesd = prop_dictionary_internalize_from_zfile(pkgfilesd); if (prop_object_type(old_filesd) == PROP_TYPE_DICTIONARY) { diff --git a/lib/transaction_package_replace.c b/lib/transaction_package_replace.c index 31d496ae..0f315f0b 100644 --- a/lib/transaction_package_replace.c +++ b/lib/transaction_package_replace.c @@ -29,17 +29,20 @@ #include #include #include +#include #include "xbps_api_impl.h" int HIDDEN xbps_transaction_package_replace(prop_dictionary_t transd) { + struct xbps_handle *xhp = xbps_handle_get(); prop_array_t replaces, instd_reqby, transd_unsorted; - prop_dictionary_t instd, pkg_repod, reppkgd; + prop_dictionary_t instd, pkg_repod, reppkgd, filesd; prop_object_t obj; prop_object_iterator_t iter; const char *pattern, *pkgname, *curpkgname, *pkgver, *curpkgver; + char *dirc, *buf, *dname; bool instd_auto, sr; size_t idx; @@ -144,7 +147,9 @@ xbps_transaction_package_replace(prop_dictionary_t transd) /* * Copy requiredby and automatic-install objects * from replaced package into pkg's dictionary - * for "softreplace" packages. + * for "softreplace" packages. Also externalize + * PKGFILES from package being replaced to remove + * obsolete files. */ sr = false; prop_dictionary_get_bool(pkg_repod, "softreplace", &sr); @@ -158,6 +163,39 @@ xbps_transaction_package_replace(prop_dictionary_t transd) "automatic-install", instd_auto); prop_dictionary_set_bool(instd, "softreplace", true); + buf = xbps_xasprintf("%s/%s/metadata/%s/%s", + xhp->rootdir, XBPS_META_PATH, curpkgname, + XBPS_PKGFILES); + assert(buf != NULL); + filesd = prop_dictionary_internalize_from_zfile(buf); + free(buf); + assert(filesd != NULL); + buf = xbps_xasprintf("%s/%s/metadata/%s/%s", + xhp->rootdir, XBPS_META_PATH, pkgname, + XBPS_PKGFILES); + assert(buf != NULL); + dirc = strdup(buf); + assert(dirc != NULL); + dname = dirname(dirc); + if (xbps_mkpath(dname, 0755) == -1) { + if (errno != EEXIST) { + free(buf); + prop_object_release(instd); + prop_object_iterator_release(iter); + return errno; + } + } + if (!prop_dictionary_externalize_to_zfile(filesd, buf)) { + free(buf); + free(dirc); + prop_object_release(filesd); + prop_object_release(instd); + prop_object_iterator_release(iter); + return errno; + } + prop_object_release(filesd); + free(buf); + free(dirc); } /* * Add package dictionary into the transaction and mark