From 95fee14dfa5bd3896c510077af36ea371a9a2975 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Fri, 26 Oct 2018 13:47:53 +0300 Subject: Merge with 1.5.4 upstream package version --- libpkgconf/dependency.c | 94 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 80 insertions(+), 14 deletions(-) (limited to 'libpkgconf/dependency.c') diff --git a/libpkgconf/dependency.c b/libpkgconf/dependency.c index cd01a06..b3722b1 100644 --- a/libpkgconf/dependency.c +++ b/libpkgconf/dependency.c @@ -52,11 +52,76 @@ dependency_to_str(const pkgconf_dependency_t *dep, char *buf, size_t buflen) return buf; } +/* find a colliding dependency that is coloured differently */ static inline pkgconf_dependency_t * -pkgconf_dependency_addraw(const pkgconf_client_t *client, pkgconf_list_t *list, const char *package, size_t package_sz, const char *version, size_t version_sz, pkgconf_pkg_comparator_t compare) +find_colliding_dependency(const pkgconf_dependency_t *dep, const pkgconf_list_t *list) +{ + const pkgconf_node_t *n; + + PKGCONF_FOREACH_LIST_ENTRY(list->head, n) + { + pkgconf_dependency_t *dep2 = n->data; + + if (strcmp(dep->package, dep2->package)) + continue; + + if (dep->flags != dep2->flags) + return dep2; + } + + return NULL; +} + +static inline pkgconf_dependency_t * +add_or_replace_dependency_node(const pkgconf_client_t *client, pkgconf_dependency_t *dep, pkgconf_list_t *list) { - pkgconf_dependency_t *dep; char depbuf[PKGCONF_ITEM_SIZE]; + pkgconf_dependency_t *dep2 = find_colliding_dependency(dep, list); + + /* there is already a node in the graph which describes this dependency */ + if (dep2 != NULL) + { + char depbuf2[PKGCONF_ITEM_SIZE]; + + PKGCONF_TRACE(client, "dependency collision: [%s/%x] -- [%s/%x]", + dependency_to_str(dep, depbuf, sizeof depbuf), dep->flags, + dependency_to_str(dep2, depbuf2, sizeof depbuf2), dep2->flags); + + /* prefer the uncoloured node, either dep or dep2 */ + if (dep->flags && dep2->flags == 0) + { + PKGCONF_TRACE(client, "dropping dependency [%s]@%p because of collision", depbuf, dep); + + free(dep); + return NULL; + } + else if (dep2->flags && dep->flags == 0) + { + PKGCONF_TRACE(client, "dropping dependency [%s]@%p because of collision", depbuf2, dep2); + + pkgconf_node_delete(&dep2->iter, list); + free(dep2); + } + else + /* If both dependencies have equal strength, we keep both, because of situations like: + * Requires: foo > 1, foo < 3 + * + * If the situation is that both dependencies are literally equal, it is still harmless because + * fragment deduplication will handle the excessive fragments. + */ + PKGCONF_TRACE(client, "keeping both dependencies (harmless)"); + } + + PKGCONF_TRACE(client, "added dependency [%s] to list @%p; flags=%x", dependency_to_str(dep, depbuf, sizeof depbuf), list, dep->flags); + pkgconf_node_insert_tail(&dep->iter, dep, list); + + return dep; +} + +static inline pkgconf_dependency_t * +pkgconf_dependency_addraw(const pkgconf_client_t *client, pkgconf_list_t *list, const char *package, size_t package_sz, const char *version, size_t version_sz, pkgconf_pkg_comparator_t compare, unsigned int flags) +{ + pkgconf_dependency_t *dep; dep = calloc(sizeof(pkgconf_dependency_t), 1); dep->package = pkgconf_strndup(package, package_sz); @@ -65,11 +130,9 @@ pkgconf_dependency_addraw(const pkgconf_client_t *client, pkgconf_list_t *list, dep->version = pkgconf_strndup(version, version_sz); dep->compare = compare; + dep->flags = flags; - PKGCONF_TRACE(client, "added dependency [%s] to list @%p", dependency_to_str(dep, depbuf, sizeof depbuf), list); - pkgconf_node_insert_tail(&dep->iter, dep, list); - - return dep; + return add_or_replace_dependency_node(client, dep, list); } /* @@ -84,16 +147,17 @@ pkgconf_dependency_addraw(const pkgconf_client_t *client, pkgconf_list_t *list, * :param char* package: The package `atom` to set on the dependency node. * :param char* version: The package `version` to set on the dependency node. * :param pkgconf_pkg_comparator_t compare: The comparison operator to set on the dependency node. + * :param uint flags: Any flags to attach to the dependency node. * :return: A dependency node. * :rtype: pkgconf_dependency_t * */ pkgconf_dependency_t * -pkgconf_dependency_add(const pkgconf_client_t *client, pkgconf_list_t *list, const char *package, const char *version, pkgconf_pkg_comparator_t compare) +pkgconf_dependency_add(const pkgconf_client_t *client, pkgconf_list_t *list, const char *package, const char *version, pkgconf_pkg_comparator_t compare, unsigned int flags) { if (version != NULL) - return pkgconf_dependency_addraw(client, list, package, strlen(package), version, strlen(version), compare); + return pkgconf_dependency_addraw(client, list, package, strlen(package), version, strlen(version), compare, flags); - return pkgconf_dependency_addraw(client, list, package, strlen(package), NULL, 0, compare); + return pkgconf_dependency_addraw(client, list, package, strlen(package), NULL, 0, compare, flags); } /* @@ -157,10 +221,11 @@ pkgconf_dependency_free(pkgconf_list_t *list) * :param pkgconf_client_t* client: The client object that owns the package this dependency list belongs to. * :param pkgconf_list_t* deplist_head: The dependency list to populate with dependency nodes. * :param char* depends: The dependency data to parse. + * :param uint flags: Any flags to attach to the dependency nodes. * :return: nothing */ void -pkgconf_dependency_parse_str(const pkgconf_client_t *client, pkgconf_list_t *deplist_head, const char *depends) +pkgconf_dependency_parse_str(const pkgconf_client_t *client, pkgconf_list_t *deplist_head, const char *depends, unsigned int flags) { parse_state_t state = OUTSIDE_MODULE; pkgconf_pkg_comparator_t compare = PKGCONF_CMP_ANY; @@ -227,7 +292,7 @@ pkgconf_dependency_parse_str(const pkgconf_client_t *client, pkgconf_list_t *dep if (state == OUTSIDE_MODULE) { - pkgconf_dependency_addraw(client, deplist_head, package, package_sz, NULL, 0, compare); + pkgconf_dependency_addraw(client, deplist_head, package, package_sz, NULL, 0, compare, flags); compare = PKGCONF_CMP_ANY; package_sz = 0; @@ -270,7 +335,7 @@ pkgconf_dependency_parse_str(const pkgconf_client_t *client, pkgconf_list_t *dep version_sz = ptr - vstart; state = OUTSIDE_MODULE; - pkgconf_dependency_addraw(client, deplist_head, package, package_sz, version, version_sz, compare); + pkgconf_dependency_addraw(client, deplist_head, package, package_sz, version, version_sz, compare, flags); compare = PKGCONF_CMP_ANY; cnameptr = cmpname; @@ -300,13 +365,14 @@ pkgconf_dependency_parse_str(const pkgconf_client_t *client, pkgconf_list_t *dep * :param pkgconf_pkg_t* pkg: The package object that owns this dependency list. * :param pkgconf_list_t* deplist: The dependency list to populate with dependency nodes. * :param char* depends: The dependency data to parse. + * :param uint flags: Any flags to attach to the dependency nodes. * :return: nothing */ void -pkgconf_dependency_parse(const pkgconf_client_t *client, pkgconf_pkg_t *pkg, pkgconf_list_t *deplist, const char *depends) +pkgconf_dependency_parse(const pkgconf_client_t *client, pkgconf_pkg_t *pkg, pkgconf_list_t *deplist, const char *depends, unsigned int flags) { char *kvdepends = pkgconf_tuple_parse(client, &pkg->vars, depends); - pkgconf_dependency_parse_str(client, deplist, kvdepends); + pkgconf_dependency_parse_str(client, deplist, kvdepends, flags); free(kvdepends); } -- cgit v1.1