From c61ba8dfcc892fee4a7c7b3d052fdd0f8c53f887 Mon Sep 17 00:00:00 2001 From: Juan RP Date: Mon, 11 Jun 2012 16:14:03 +0200 Subject: [PATCH] Added support for package conflicts. --- NEWS | 5 +++ TODO | 1 - bin/xbps-bin/transaction.c | 31 ++++++++++---- include/xbps_api.h | 2 +- include/xbps_api_impl.h | 6 +++ lib/Makefile | 2 +- lib/package_conflicts.c | 82 ++++++++++++++++++++++++++++++++++++ lib/repository_finddeps.c | 4 ++ lib/transaction_dictionary.c | 24 +++++++++-- lib/transaction_ops.c | 10 ++++- 10 files changed, 151 insertions(+), 16 deletions(-) create mode 100644 lib/package_conflicts.c diff --git a/NEWS b/NEWS index f76d0f31..2571471f 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,10 @@ xbps-0.16 (???): + * Added support for package conflicts. If any conflicting pkg has been found + in a transaction, xbps_transaction_prepare() will return EAGAIN and + the array object "conflicts" in transaction dictionary must be inspected + to know what conflicts have been found. + * Always require an underscore at package versions, if any provided pkgver (i.e 'foo-1.0_1') does not contain an underscore the name/version won't be detected for a string. That means that now any package can contain diff --git a/TODO b/TODO index b5f6954b..e1e09f34 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,4 @@ libxbps: - - conflicts: the object is there but is not handled yet (ETA 0.16) - properties: (update-first) still unimplemented. xbps-repo: diff --git a/bin/xbps-bin/transaction.c b/bin/xbps-bin/transaction.c index 77646aa6..8fb78a91 100644 --- a/bin/xbps-bin/transaction.c +++ b/bin/xbps-bin/transaction.c @@ -50,16 +50,26 @@ struct transaction { static void show_missing_deps(prop_array_t a) { - prop_object_t obj; size_t i; + const char *str; - fprintf(stderr, - "xbps-bin: unable to locate some required packages:\n"); - + fprintf(stderr, "xbps-bin: unable to locate some required packages:\n"); for (i = 0; i < prop_array_count(a); i++) { - obj = prop_array_get(a, i); - fprintf(stderr, " * Missing binary package for: %s\n", - prop_string_cstring_nocopy(obj)); + prop_array_get_cstring_nocopy(a, i, &str); + fprintf(stderr, " * Missing binary package for: %s\n", str); + } +} + +static void +show_conflicts(prop_array_t a) +{ + size_t i; + const char *str; + + fprintf(stderr, "xbps-bin: conflicting packages were found:\n"); + for (i = 0; i < prop_array_count(a); i++) { + prop_array_get_cstring_nocopy(a, i, &str); + fprintf(stderr, " %s\n", str); } } @@ -350,7 +360,7 @@ remove_pkg(const char *pkgname, bool recursive) int exec_transaction(bool yes, bool dry_run, bool show_download_urls) { - prop_array_t mdeps; + prop_array_t mdeps, cflicts; struct transaction *trans; struct xbps_handle *xhp = xbps_handle_get(); int rv = 0; @@ -366,6 +376,11 @@ exec_transaction(bool yes, bool dry_run, bool show_download_urls) /* missing packages */ show_missing_deps(mdeps); goto out; + } else if (rv == EAGAIN) { + /* conflicts */ + cflicts = prop_dictionary_get(xhp->transd, "conflicts"); + show_conflicts(cflicts); + goto out; } xbps_dbg_printf("Empty transaction dictionary: %s\n", strerror(errno)); diff --git a/include/xbps_api.h b/include/xbps_api.h index 701b43bc..de9f3a2c 100644 --- a/include/xbps_api.h +++ b/include/xbps_api.h @@ -56,7 +56,7 @@ */ #define XBPS_PKGINDEX_VERSION "1.5" -#define XBPS_API_VERSION "20120609" +#define XBPS_API_VERSION "20120611" #define XBPS_VERSION "0.16" /** diff --git a/include/xbps_api_impl.h b/include/xbps_api_impl.h index 885352ed..b068e293 100644 --- a/include/xbps_api_impl.h +++ b/include/xbps_api_impl.h @@ -181,6 +181,12 @@ void HIDDEN xbps_set_cb_state(xbps_state_t, int, const char *, */ int HIDDEN xbps_unpack_binary_pkg(prop_dictionary_t); +/** + * @private + * From lib/package_conflicts.c + */ +void HIDDEN xbps_pkg_find_conflicts(struct xbps_handle *, prop_dictionary_t); + __END_DECLS #endif /* !_XBPS_API_IMPL_H_ */ diff --git a/lib/Makefile b/lib/Makefile index f98966c0..f577e679 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -46,7 +46,7 @@ OBJS += package_remove.o package_remove_obsoletes.o package_state.o OBJS += package_unpack.o package_requiredby.o package_register.o OBJS += transaction_commit.o transaction_package_replace.o OBJS += transaction_dictionary.o transaction_sortdeps.o transaction_ops.o -OBJS += download.o initend.o pkgdb.o +OBJS += download.o initend.o pkgdb.o package_conflicts.o OBJS += plist.o plist_archive_entry.o plist_find.o plist_match.o OBJS += plist_remove.o plist_fetch.o util.o util_hash.o OBJS += repository_finddeps.o cb_util.o diff --git a/lib/package_conflicts.c b/lib/package_conflicts.c new file mode 100644 index 00000000..68cefbf0 --- /dev/null +++ b/lib/package_conflicts.c @@ -0,0 +1,82 @@ +/*- + * Copyright (c) 2012 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 +#include +#include +#include +#include + +#include "xbps_api_impl.h" + +void HIDDEN +xbps_pkg_find_conflicts(struct xbps_handle *xhp, prop_dictionary_t pkg_repod) +{ + prop_array_t pkg_cflicts, trans_cflicts; + prop_dictionary_t pkgd; + const char *cfpkg, *repopkgver, *pkgver; + char *buf; + size_t i; + + pkg_cflicts = prop_dictionary_get(pkg_repod, "conflicts"); + if (pkg_cflicts == NULL || prop_array_count(pkg_cflicts) == 0) + return; + + trans_cflicts = prop_dictionary_get(xhp->transd, "conflicts"); + prop_dictionary_get_cstring_nocopy(pkg_repod, "pkgver", &repopkgver); + + for (i = 0; i < prop_array_count(pkg_cflicts); i++) { + prop_array_get_cstring_nocopy(pkg_cflicts, i, &cfpkg); + /* + * Check if current pkg conflicts with an installed package. + */ + if ((pkgd = xbps_pkgdb_get_pkgd(cfpkg, true))) { + prop_dictionary_get_cstring_nocopy(pkgd, + "pkgver", &pkgver); + buf = xbps_xasprintf("%s conflicts with " + "installed pkg %s", repopkgver, pkgver); + assert(buf != NULL); + prop_array_add_cstring(trans_cflicts, buf); + prop_object_release(pkgd); + free(buf); + continue; + } + /* + * Check if current pkg conflicts with any pkg in transaction. + */ + pkgd = xbps_find_pkg_in_dict_by_pattern(xhp->transd, + "unsorted_deps", cfpkg); + if (pkgd != NULL) { + prop_dictionary_get_cstring_nocopy(pkgd, + "pkgver", &pkgver); + buf = xbps_xasprintf("%s conflicts with " + "%s in transaction", repopkgver, pkgver); + assert(buf != NULL); + prop_array_add_cstring(trans_cflicts, buf); + free(buf); + continue; + } + } +} diff --git a/lib/repository_finddeps.c b/lib/repository_finddeps.c index 35bfc47d..492c40b6 100644 --- a/lib/repository_finddeps.c +++ b/lib/repository_finddeps.c @@ -359,6 +359,10 @@ find_repo_deps(prop_dictionary_t transd, /* transaction dictionary */ continue; } } + /* + * Check if package has matched conflicts. + */ + xbps_pkg_find_conflicts(xhp, curpkgd); /* * Package is on repo, add it into the transaction dictionary. */ diff --git a/lib/transaction_dictionary.c b/lib/transaction_dictionary.c index 61cd128e..5ffd4337 100644 --- a/lib/transaction_dictionary.c +++ b/lib/transaction_dictionary.c @@ -190,7 +190,7 @@ out: int HIDDEN xbps_transaction_init(struct xbps_handle *xhp) { - prop_array_t unsorted, mdeps; + prop_array_t unsorted, mdeps, conflicts; if (xhp->transd != NULL) return 0; @@ -218,6 +218,16 @@ xbps_transaction_init(struct xbps_handle *xhp) xhp->transd = NULL; return EINVAL; } + if ((conflicts = prop_array_create()) == NULL) { + prop_object_release(xhp->transd); + xhp->transd = NULL; + return ENOMEM; + } + if (!xbps_add_obj_to_dict(xhp->transd, conflicts, "conflicts")) { + prop_object_release(xhp->transd); + xhp->transd = NULL; + return EINVAL; + } return 0; } @@ -225,7 +235,7 @@ xbps_transaction_init(struct xbps_handle *xhp) int xbps_transaction_prepare(void) { - prop_array_t mdeps; + prop_array_t mdeps, conflicts; struct xbps_handle *xhp = xbps_handle_get(); int rv = 0; @@ -239,6 +249,13 @@ xbps_transaction_prepare(void) if (prop_array_count(mdeps) > 0) return ENODEV; + /* + * If there are package conflicts bail out. + */ + conflicts = prop_dictionary_get(xhp->transd, "conflicts"); + if (prop_array_count(conflicts) > 0) + return EAGAIN; + /* * Check for packages to be replaced. */ @@ -266,9 +283,10 @@ xbps_transaction_prepare(void) return rv; } /* - * The missing deps array is not necessary anymore. + * The missing deps and conflicts arrays are not necessary anymore. */ prop_dictionary_remove(xhp->transd, "missing_deps"); + prop_dictionary_remove(xhp->transd, "conflicts"); prop_dictionary_make_immutable(xhp->transd); return 0; diff --git a/lib/transaction_ops.c b/lib/transaction_ops.c index 87cda5c1..a4fa80a2 100644 --- a/lib/transaction_ops.c +++ b/lib/transaction_ops.c @@ -126,16 +126,22 @@ transaction_find_pkg(const char *pkg, bool bypattern, bool best, bool exact, } } /* - * Prepare transaction dictionary and missing deps array. + * Prepare transaction dictionary. */ if ((rv = xbps_transaction_init(xhp)) != 0) goto out; + + /* + * Find out if package has matched conflicts. + */ + xbps_pkg_find_conflicts(xhp, pkg_repod); + /* * Prepare required package dependencies and add them into the * "unsorted" array in transaction dictionary. */ if ((rv = xbps_repository_find_pkg_deps(xhp, pkg_repod)) != 0) - goto out; + goto out; /* * Set package state in dictionary with same state than the * package currently uses, otherwise not-installed.