diff options
Diffstat (limited to 'libpkgconf/queue.c')
| -rw-r--r-- | libpkgconf/queue.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/libpkgconf/queue.c b/libpkgconf/queue.c index 09c02e368f85..ff4e049612c0 100644 --- a/libpkgconf/queue.c +++ b/libpkgconf/queue.c @@ -2,6 +2,8 @@ * queue.c * compilation of a list of packages into a world dependency set * + * SPDX-License-Identifier: pkgconf + * * Copyright (c) 2012 pkgconf authors (see AUTHORS). * * Permission to use, copy, modify, and/or distribute this software for any @@ -32,6 +34,35 @@ /* * !doc * + * .. c:function:: void pkgconf_queue_push_dependency(pkgconf_list_t *list, const pkgconf_dependency_t *dep) + * + * Pushes a requested dependency onto the dependency resolver's queue which is described by + * a pkgconf_dependency_t node. + * + * :param pkgconf_list_t* list: the dependency resolution queue to add the package request to. + * :param pkgconf_dependency_t* dep: the dependency requested + * :return: nothing + */ +void +pkgconf_queue_push_dependency(pkgconf_list_t *list, const pkgconf_dependency_t *dep) +{ + pkgconf_buffer_t depbuf = PKGCONF_BUFFER_INITIALIZER; + pkgconf_queue_t *pkgq = calloc(1, sizeof(pkgconf_queue_t)); + + if (pkgq == NULL) + return; + + pkgconf_buffer_append(&depbuf, dep->package); + if (dep->version != NULL) + pkgconf_buffer_append_fmt(&depbuf, " %s %s", pkgconf_pkg_get_comparator(dep), dep->version); + + pkgq->package = pkgconf_buffer_freeze(&depbuf); + pkgconf_node_insert_tail(&pkgq->iter, pkgq, list); +} + +/* + * !doc + * * .. c:function:: void pkgconf_queue_push(pkgconf_list_t *list, const char *package) * * Pushes a requested dependency onto the dependency resolver's queue. @@ -45,6 +76,9 @@ pkgconf_queue_push(pkgconf_list_t *list, const char *package) { pkgconf_queue_t *pkgq = calloc(1, sizeof(pkgconf_queue_t)); + if (pkgq == NULL) + return; + pkgq->package = strdup(package); pkgconf_node_insert_tail(&pkgq->iter, pkgq, list); } @@ -165,6 +199,12 @@ pkgconf_queue_collect_dependencies_walk(pkgconf_client_t *client, eflags |= pkgconf_queue_collect_dependencies_main(client, pkg, data, depth - 1); flattened_dep = pkgconf_dependency_copy(client, dep); + if (flattened_dep == NULL) + { + eflags |= PKGCONF_PKG_ERRF_DEPGRAPH_BREAK; + continue; + } + pkgconf_node_insert(&flattened_dep->iter, flattened_dep, &world->required); } @@ -189,6 +229,15 @@ pkgconf_queue_collect_dependencies_main(pkgconf_client_t *client, root->serial = client->serial; + if (!(client->flags & PKGCONF_PKG_PKGF_MERGE_PRIVATE_FRAGMENTS)) + { + PKGCONF_TRACE(client, "%s: collecting shared dependencies, level %d", root->id, maxdepth); + + eflags = pkgconf_queue_collect_dependencies_walk(client, &root->requires_shared, data, maxdepth); + if (eflags != PKGCONF_PKG_ERRF_OK) + return eflags; + } + PKGCONF_TRACE(client, "%s: collecting private dependencies, level %d", root->id, maxdepth); /* XXX: ugly */ @@ -221,6 +270,50 @@ pkgconf_queue_collect_dependencies(pkgconf_client_t *client, } static inline unsigned int +pkgconf_queue_collect_conflicts(pkgconf_client_t *client, + pkgconf_pkg_t *root, + pkgconf_pkg_t *world, + int maxdepth) +{ + unsigned int eflags = PKGCONF_PKG_ERRF_OK; + pkgconf_node_t *node; + + PKGCONF_TRACE(client, "%s: collecting conflicts, level %d", root->id, maxdepth); + + PKGCONF_FOREACH_LIST_ENTRY(root->required.head, node) + { + pkgconf_dependency_t *dep = node->data; + pkgconf_pkg_t *pkg = dep->match; + pkgconf_node_t *cnode; + + if (*dep->package == '\0') + continue; + + if (pkg == NULL) + { + PKGCONF_TRACE(client, "WTF: unmatched dependency %p <%s>", dep, dep->package); + continue; + } + + PKGCONF_FOREACH_LIST_ENTRY(pkg->conflicts.head, cnode) + { + pkgconf_dependency_t *conflict = cnode->data; + pkgconf_dependency_t *flattened_conflict = pkgconf_dependency_copy(client, conflict); + if (flattened_conflict == NULL) + { + eflags |= PKGCONF_PKG_ERRF_DEPGRAPH_BREAK; + continue; + } + + flattened_conflict->why = strdup(pkg->id); + pkgconf_node_insert(&flattened_conflict->iter, flattened_conflict, &world->conflicts); + } + } + + return eflags; +} + +static inline unsigned int pkgconf_queue_verify(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list, int maxdepth) { unsigned int result; @@ -253,6 +346,13 @@ pkgconf_queue_verify(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_lis return result; } + result = pkgconf_queue_collect_conflicts(client, world, world, maxdepth); + if (result != PKGCONF_PKG_ERRF_OK) + { + pkgconf_solution_free(client, &initial_world); + return result; + } + if (client->flags & PKGCONF_PKG_PKGF_SEARCH_PRIVATE) { PKGCONF_TRACE(client, "marking public deps"); @@ -267,6 +367,18 @@ pkgconf_queue_verify(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_lis } } + if (!(client->flags & PKGCONF_PKG_PKGF_SKIP_CONFLICTS)) + { + PKGCONF_TRACE(client, "checking for conflicts"); + + result = pkgconf_pkg_walk_conflicts_list(client, world, &world->conflicts); + if (result != PKGCONF_PKG_ERRF_OK) + { + pkgconf_solution_free(client, &initial_world); + return result; + } + } + /* free the initial solution */ pkgconf_solution_free(client, &initial_world); @@ -293,6 +405,7 @@ pkgconf_solution_free(pkgconf_client_t *client, pkgconf_pkg_t *world) { pkgconf_dependency_free(&world->required); pkgconf_dependency_free(&world->requires_private); + pkgconf_dependency_free(&world->conflicts); } } |
