1*a3cefe7fSPierre Pronchery /*
2*a3cefe7fSPierre Pronchery * queue.c
3*a3cefe7fSPierre Pronchery * compilation of a list of packages into a world dependency set
4*a3cefe7fSPierre Pronchery *
5*a3cefe7fSPierre Pronchery * Copyright (c) 2012 pkgconf authors (see AUTHORS).
6*a3cefe7fSPierre Pronchery *
7*a3cefe7fSPierre Pronchery * Permission to use, copy, modify, and/or distribute this software for any
8*a3cefe7fSPierre Pronchery * purpose with or without fee is hereby granted, provided that the above
9*a3cefe7fSPierre Pronchery * copyright notice and this permission notice appear in all copies.
10*a3cefe7fSPierre Pronchery *
11*a3cefe7fSPierre Pronchery * This software is provided 'as is' and without any warranty, express or
12*a3cefe7fSPierre Pronchery * implied. In no event shall the authors be liable for any damages arising
13*a3cefe7fSPierre Pronchery * from the use of this software.
14*a3cefe7fSPierre Pronchery */
15*a3cefe7fSPierre Pronchery
16*a3cefe7fSPierre Pronchery #include <libpkgconf/stdinc.h>
17*a3cefe7fSPierre Pronchery #include <libpkgconf/libpkgconf.h>
18*a3cefe7fSPierre Pronchery
19*a3cefe7fSPierre Pronchery /*
20*a3cefe7fSPierre Pronchery * !doc
21*a3cefe7fSPierre Pronchery *
22*a3cefe7fSPierre Pronchery * libpkgconf `queue` module
23*a3cefe7fSPierre Pronchery * =========================
24*a3cefe7fSPierre Pronchery *
25*a3cefe7fSPierre Pronchery * The `queue` module provides an interface that allows easily building a dependency graph from an
26*a3cefe7fSPierre Pronchery * arbitrary set of dependencies. It also provides support for doing "preflight" checks on the entire
27*a3cefe7fSPierre Pronchery * dependency graph prior to working with it.
28*a3cefe7fSPierre Pronchery *
29*a3cefe7fSPierre Pronchery * Using the `queue` module functions is the recommended way of working with dependency graphs.
30*a3cefe7fSPierre Pronchery */
31*a3cefe7fSPierre Pronchery
32*a3cefe7fSPierre Pronchery /*
33*a3cefe7fSPierre Pronchery * !doc
34*a3cefe7fSPierre Pronchery *
35*a3cefe7fSPierre Pronchery * .. c:function:: void pkgconf_queue_push(pkgconf_list_t *list, const char *package)
36*a3cefe7fSPierre Pronchery *
37*a3cefe7fSPierre Pronchery * Pushes a requested dependency onto the dependency resolver's queue.
38*a3cefe7fSPierre Pronchery *
39*a3cefe7fSPierre Pronchery * :param pkgconf_list_t* list: the dependency resolution queue to add the package request to.
40*a3cefe7fSPierre Pronchery * :param char* package: the dependency atom requested
41*a3cefe7fSPierre Pronchery * :return: nothing
42*a3cefe7fSPierre Pronchery */
43*a3cefe7fSPierre Pronchery void
pkgconf_queue_push(pkgconf_list_t * list,const char * package)44*a3cefe7fSPierre Pronchery pkgconf_queue_push(pkgconf_list_t *list, const char *package)
45*a3cefe7fSPierre Pronchery {
46*a3cefe7fSPierre Pronchery pkgconf_queue_t *pkgq = calloc(1, sizeof(pkgconf_queue_t));
47*a3cefe7fSPierre Pronchery
48*a3cefe7fSPierre Pronchery pkgq->package = strdup(package);
49*a3cefe7fSPierre Pronchery pkgconf_node_insert_tail(&pkgq->iter, pkgq, list);
50*a3cefe7fSPierre Pronchery }
51*a3cefe7fSPierre Pronchery
52*a3cefe7fSPierre Pronchery /*
53*a3cefe7fSPierre Pronchery * !doc
54*a3cefe7fSPierre Pronchery *
55*a3cefe7fSPierre Pronchery * .. c:function:: bool pkgconf_queue_compile(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list)
56*a3cefe7fSPierre Pronchery *
57*a3cefe7fSPierre Pronchery * Compile a dependency resolution queue into a dependency resolution problem if possible, otherwise report an error.
58*a3cefe7fSPierre Pronchery *
59*a3cefe7fSPierre Pronchery * :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
60*a3cefe7fSPierre Pronchery * :param pkgconf_pkg_t* world: The designated root of the dependency graph.
61*a3cefe7fSPierre Pronchery * :param pkgconf_list_t* list: The list of dependency requests to consider.
62*a3cefe7fSPierre Pronchery * :return: true if the built dependency resolution problem is consistent, else false
63*a3cefe7fSPierre Pronchery * :rtype: bool
64*a3cefe7fSPierre Pronchery */
65*a3cefe7fSPierre Pronchery bool
pkgconf_queue_compile(pkgconf_client_t * client,pkgconf_pkg_t * world,pkgconf_list_t * list)66*a3cefe7fSPierre Pronchery pkgconf_queue_compile(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list)
67*a3cefe7fSPierre Pronchery {
68*a3cefe7fSPierre Pronchery pkgconf_node_t *iter;
69*a3cefe7fSPierre Pronchery
70*a3cefe7fSPierre Pronchery PKGCONF_FOREACH_LIST_ENTRY(list->head, iter)
71*a3cefe7fSPierre Pronchery {
72*a3cefe7fSPierre Pronchery pkgconf_queue_t *pkgq;
73*a3cefe7fSPierre Pronchery
74*a3cefe7fSPierre Pronchery pkgq = iter->data;
75*a3cefe7fSPierre Pronchery pkgconf_dependency_parse(client, world, &world->required, pkgq->package, PKGCONF_PKG_DEPF_QUERY);
76*a3cefe7fSPierre Pronchery }
77*a3cefe7fSPierre Pronchery
78*a3cefe7fSPierre Pronchery return (world->required.head != NULL);
79*a3cefe7fSPierre Pronchery }
80*a3cefe7fSPierre Pronchery
81*a3cefe7fSPierre Pronchery /*
82*a3cefe7fSPierre Pronchery * !doc
83*a3cefe7fSPierre Pronchery *
84*a3cefe7fSPierre Pronchery * .. c:function:: void pkgconf_queue_free(pkgconf_list_t *list)
85*a3cefe7fSPierre Pronchery *
86*a3cefe7fSPierre Pronchery * Release any memory related to a dependency resolution queue.
87*a3cefe7fSPierre Pronchery *
88*a3cefe7fSPierre Pronchery * :param pkgconf_list_t* list: The dependency resolution queue to release.
89*a3cefe7fSPierre Pronchery * :return: nothing
90*a3cefe7fSPierre Pronchery */
91*a3cefe7fSPierre Pronchery void
pkgconf_queue_free(pkgconf_list_t * list)92*a3cefe7fSPierre Pronchery pkgconf_queue_free(pkgconf_list_t *list)
93*a3cefe7fSPierre Pronchery {
94*a3cefe7fSPierre Pronchery pkgconf_node_t *node, *tnode;
95*a3cefe7fSPierre Pronchery
96*a3cefe7fSPierre Pronchery PKGCONF_FOREACH_LIST_ENTRY_SAFE(list->head, tnode, node)
97*a3cefe7fSPierre Pronchery {
98*a3cefe7fSPierre Pronchery pkgconf_queue_t *pkgq = node->data;
99*a3cefe7fSPierre Pronchery
100*a3cefe7fSPierre Pronchery free(pkgq->package);
101*a3cefe7fSPierre Pronchery free(pkgq);
102*a3cefe7fSPierre Pronchery }
103*a3cefe7fSPierre Pronchery }
104*a3cefe7fSPierre Pronchery
105*a3cefe7fSPierre Pronchery static void
pkgconf_queue_mark_public(pkgconf_client_t * client,pkgconf_pkg_t * pkg,void * data)106*a3cefe7fSPierre Pronchery pkgconf_queue_mark_public(pkgconf_client_t *client, pkgconf_pkg_t *pkg, void *data)
107*a3cefe7fSPierre Pronchery {
108*a3cefe7fSPierre Pronchery if (pkg->flags & PKGCONF_PKG_PROPF_VISITED_PRIVATE)
109*a3cefe7fSPierre Pronchery {
110*a3cefe7fSPierre Pronchery pkgconf_list_t *list = data;
111*a3cefe7fSPierre Pronchery pkgconf_node_t *node;
112*a3cefe7fSPierre Pronchery
113*a3cefe7fSPierre Pronchery PKGCONF_FOREACH_LIST_ENTRY(list->head, node)
114*a3cefe7fSPierre Pronchery {
115*a3cefe7fSPierre Pronchery pkgconf_dependency_t *dep = node->data;
116*a3cefe7fSPierre Pronchery if (dep->match == pkg)
117*a3cefe7fSPierre Pronchery dep->flags &= ~PKGCONF_PKG_DEPF_PRIVATE;
118*a3cefe7fSPierre Pronchery }
119*a3cefe7fSPierre Pronchery
120*a3cefe7fSPierre Pronchery pkg->flags &= ~PKGCONF_PKG_PROPF_VISITED_PRIVATE;
121*a3cefe7fSPierre Pronchery
122*a3cefe7fSPierre Pronchery PKGCONF_TRACE(client, "%s: updated, public", pkg->id);
123*a3cefe7fSPierre Pronchery }
124*a3cefe7fSPierre Pronchery }
125*a3cefe7fSPierre Pronchery
126*a3cefe7fSPierre Pronchery static unsigned int
127*a3cefe7fSPierre Pronchery pkgconf_queue_collect_dependencies_main(pkgconf_client_t *client,
128*a3cefe7fSPierre Pronchery pkgconf_pkg_t *root,
129*a3cefe7fSPierre Pronchery void *data,
130*a3cefe7fSPierre Pronchery int maxdepth);
131*a3cefe7fSPierre Pronchery
132*a3cefe7fSPierre Pronchery static inline unsigned int
pkgconf_queue_collect_dependencies_walk(pkgconf_client_t * client,pkgconf_list_t * deplist,void * data,int depth)133*a3cefe7fSPierre Pronchery pkgconf_queue_collect_dependencies_walk(pkgconf_client_t *client,
134*a3cefe7fSPierre Pronchery pkgconf_list_t *deplist,
135*a3cefe7fSPierre Pronchery void *data,
136*a3cefe7fSPierre Pronchery int depth)
137*a3cefe7fSPierre Pronchery {
138*a3cefe7fSPierre Pronchery unsigned int eflags = PKGCONF_PKG_ERRF_OK;
139*a3cefe7fSPierre Pronchery pkgconf_node_t *node;
140*a3cefe7fSPierre Pronchery pkgconf_pkg_t *world = data;
141*a3cefe7fSPierre Pronchery
142*a3cefe7fSPierre Pronchery PKGCONF_FOREACH_LIST_ENTRY_REVERSE(deplist->tail, node)
143*a3cefe7fSPierre Pronchery {
144*a3cefe7fSPierre Pronchery pkgconf_dependency_t *dep = node->data;
145*a3cefe7fSPierre Pronchery pkgconf_dependency_t *flattened_dep;
146*a3cefe7fSPierre Pronchery pkgconf_pkg_t *pkg = dep->match;
147*a3cefe7fSPierre Pronchery
148*a3cefe7fSPierre Pronchery if (*dep->package == '\0')
149*a3cefe7fSPierre Pronchery continue;
150*a3cefe7fSPierre Pronchery
151*a3cefe7fSPierre Pronchery if (pkg == NULL)
152*a3cefe7fSPierre Pronchery {
153*a3cefe7fSPierre Pronchery PKGCONF_TRACE(client, "WTF: unmatched dependency %p <%s>", dep, dep->package);
154*a3cefe7fSPierre Pronchery continue;
155*a3cefe7fSPierre Pronchery }
156*a3cefe7fSPierre Pronchery
157*a3cefe7fSPierre Pronchery if (pkg->serial == client->serial)
158*a3cefe7fSPierre Pronchery continue;
159*a3cefe7fSPierre Pronchery
160*a3cefe7fSPierre Pronchery if (client->flags & PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE)
161*a3cefe7fSPierre Pronchery pkg->flags |= PKGCONF_PKG_PROPF_VISITED_PRIVATE;
162*a3cefe7fSPierre Pronchery else
163*a3cefe7fSPierre Pronchery pkg->flags &= ~PKGCONF_PKG_PROPF_VISITED_PRIVATE;
164*a3cefe7fSPierre Pronchery
165*a3cefe7fSPierre Pronchery eflags |= pkgconf_queue_collect_dependencies_main(client, pkg, data, depth - 1);
166*a3cefe7fSPierre Pronchery
167*a3cefe7fSPierre Pronchery flattened_dep = pkgconf_dependency_copy(client, dep);
168*a3cefe7fSPierre Pronchery pkgconf_node_insert(&flattened_dep->iter, flattened_dep, &world->required);
169*a3cefe7fSPierre Pronchery }
170*a3cefe7fSPierre Pronchery
171*a3cefe7fSPierre Pronchery return eflags;
172*a3cefe7fSPierre Pronchery }
173*a3cefe7fSPierre Pronchery
174*a3cefe7fSPierre Pronchery static unsigned int
pkgconf_queue_collect_dependencies_main(pkgconf_client_t * client,pkgconf_pkg_t * root,void * data,int maxdepth)175*a3cefe7fSPierre Pronchery pkgconf_queue_collect_dependencies_main(pkgconf_client_t *client,
176*a3cefe7fSPierre Pronchery pkgconf_pkg_t *root,
177*a3cefe7fSPierre Pronchery void *data,
178*a3cefe7fSPierre Pronchery int maxdepth)
179*a3cefe7fSPierre Pronchery {
180*a3cefe7fSPierre Pronchery unsigned int eflags = PKGCONF_PKG_ERRF_OK;
181*a3cefe7fSPierre Pronchery
182*a3cefe7fSPierre Pronchery if (maxdepth == 0)
183*a3cefe7fSPierre Pronchery return eflags;
184*a3cefe7fSPierre Pronchery
185*a3cefe7fSPierre Pronchery /* Short-circuit if we have already visited this node.
186*a3cefe7fSPierre Pronchery */
187*a3cefe7fSPierre Pronchery if (root->serial == client->serial)
188*a3cefe7fSPierre Pronchery return eflags;
189*a3cefe7fSPierre Pronchery
190*a3cefe7fSPierre Pronchery root->serial = client->serial;
191*a3cefe7fSPierre Pronchery
192*a3cefe7fSPierre Pronchery PKGCONF_TRACE(client, "%s: collecting private dependencies, level %d", root->id, maxdepth);
193*a3cefe7fSPierre Pronchery
194*a3cefe7fSPierre Pronchery /* XXX: ugly */
195*a3cefe7fSPierre Pronchery const unsigned int saved_flags = client->flags;
196*a3cefe7fSPierre Pronchery client->flags |= PKGCONF_PKG_PKGF_ITER_PKG_IS_PRIVATE;
197*a3cefe7fSPierre Pronchery eflags = pkgconf_queue_collect_dependencies_walk(client, &root->requires_private, data, maxdepth);
198*a3cefe7fSPierre Pronchery client->flags = saved_flags;
199*a3cefe7fSPierre Pronchery if (eflags != PKGCONF_PKG_ERRF_OK)
200*a3cefe7fSPierre Pronchery return eflags;
201*a3cefe7fSPierre Pronchery
202*a3cefe7fSPierre Pronchery PKGCONF_TRACE(client, "%s: collecting public dependencies, level %d", root->id, maxdepth);
203*a3cefe7fSPierre Pronchery
204*a3cefe7fSPierre Pronchery eflags = pkgconf_queue_collect_dependencies_walk(client, &root->required, data, maxdepth);
205*a3cefe7fSPierre Pronchery if (eflags != PKGCONF_PKG_ERRF_OK)
206*a3cefe7fSPierre Pronchery return eflags;
207*a3cefe7fSPierre Pronchery
208*a3cefe7fSPierre Pronchery PKGCONF_TRACE(client, "%s: finished, %s", root->id, (root->flags & PKGCONF_PKG_PROPF_VISITED_PRIVATE) ? "private" : "public");
209*a3cefe7fSPierre Pronchery
210*a3cefe7fSPierre Pronchery return eflags;
211*a3cefe7fSPierre Pronchery }
212*a3cefe7fSPierre Pronchery
213*a3cefe7fSPierre Pronchery static inline unsigned int
pkgconf_queue_collect_dependencies(pkgconf_client_t * client,pkgconf_pkg_t * root,void * data,int maxdepth)214*a3cefe7fSPierre Pronchery pkgconf_queue_collect_dependencies(pkgconf_client_t *client,
215*a3cefe7fSPierre Pronchery pkgconf_pkg_t *root,
216*a3cefe7fSPierre Pronchery void *data,
217*a3cefe7fSPierre Pronchery int maxdepth)
218*a3cefe7fSPierre Pronchery {
219*a3cefe7fSPierre Pronchery ++client->serial;
220*a3cefe7fSPierre Pronchery return pkgconf_queue_collect_dependencies_main(client, root, data, maxdepth);
221*a3cefe7fSPierre Pronchery }
222*a3cefe7fSPierre Pronchery
223*a3cefe7fSPierre Pronchery static inline unsigned int
pkgconf_queue_verify(pkgconf_client_t * client,pkgconf_pkg_t * world,pkgconf_list_t * list,int maxdepth)224*a3cefe7fSPierre Pronchery pkgconf_queue_verify(pkgconf_client_t *client, pkgconf_pkg_t *world, pkgconf_list_t *list, int maxdepth)
225*a3cefe7fSPierre Pronchery {
226*a3cefe7fSPierre Pronchery unsigned int result;
227*a3cefe7fSPierre Pronchery const unsigned int saved_flags = client->flags;
228*a3cefe7fSPierre Pronchery pkgconf_pkg_t initial_world = {
229*a3cefe7fSPierre Pronchery .id = "user:request",
230*a3cefe7fSPierre Pronchery .realname = "virtual world package",
231*a3cefe7fSPierre Pronchery .flags = PKGCONF_PKG_PROPF_STATIC | PKGCONF_PKG_PROPF_VIRTUAL,
232*a3cefe7fSPierre Pronchery };
233*a3cefe7fSPierre Pronchery
234*a3cefe7fSPierre Pronchery if (!pkgconf_queue_compile(client, &initial_world, list))
235*a3cefe7fSPierre Pronchery {
236*a3cefe7fSPierre Pronchery pkgconf_solution_free(client, &initial_world);
237*a3cefe7fSPierre Pronchery return PKGCONF_PKG_ERRF_DEPGRAPH_BREAK;
238*a3cefe7fSPierre Pronchery }
239*a3cefe7fSPierre Pronchery
240*a3cefe7fSPierre Pronchery PKGCONF_TRACE(client, "solving");
241*a3cefe7fSPierre Pronchery result = pkgconf_pkg_traverse(client, &initial_world, NULL, NULL, maxdepth, 0);
242*a3cefe7fSPierre Pronchery if (result != PKGCONF_PKG_ERRF_OK)
243*a3cefe7fSPierre Pronchery {
244*a3cefe7fSPierre Pronchery pkgconf_solution_free(client, &initial_world);
245*a3cefe7fSPierre Pronchery return result;
246*a3cefe7fSPierre Pronchery }
247*a3cefe7fSPierre Pronchery
248*a3cefe7fSPierre Pronchery PKGCONF_TRACE(client, "flattening");
249*a3cefe7fSPierre Pronchery result = pkgconf_queue_collect_dependencies(client, &initial_world, world, maxdepth);
250*a3cefe7fSPierre Pronchery if (result != PKGCONF_PKG_ERRF_OK)
251*a3cefe7fSPierre Pronchery {
252*a3cefe7fSPierre Pronchery pkgconf_solution_free(client, &initial_world);
253*a3cefe7fSPierre Pronchery return result;
254*a3cefe7fSPierre Pronchery }
255*a3cefe7fSPierre Pronchery
256*a3cefe7fSPierre Pronchery if (client->flags & PKGCONF_PKG_PKGF_SEARCH_PRIVATE)
257*a3cefe7fSPierre Pronchery {
258*a3cefe7fSPierre Pronchery PKGCONF_TRACE(client, "marking public deps");
259*a3cefe7fSPierre Pronchery client->flags &= ~PKGCONF_PKG_PKGF_SEARCH_PRIVATE;
260*a3cefe7fSPierre Pronchery client->flags |= PKGCONF_PKG_PKGF_SKIP_CONFLICTS;
261*a3cefe7fSPierre Pronchery result = pkgconf_pkg_traverse(client, &initial_world, pkgconf_queue_mark_public, &world->required, maxdepth, 0);
262*a3cefe7fSPierre Pronchery client->flags = saved_flags;
263*a3cefe7fSPierre Pronchery if (result != PKGCONF_PKG_ERRF_OK)
264*a3cefe7fSPierre Pronchery {
265*a3cefe7fSPierre Pronchery pkgconf_solution_free(client, &initial_world);
266*a3cefe7fSPierre Pronchery return result;
267*a3cefe7fSPierre Pronchery }
268*a3cefe7fSPierre Pronchery }
269*a3cefe7fSPierre Pronchery
270*a3cefe7fSPierre Pronchery /* free the initial solution */
271*a3cefe7fSPierre Pronchery pkgconf_solution_free(client, &initial_world);
272*a3cefe7fSPierre Pronchery
273*a3cefe7fSPierre Pronchery return PKGCONF_PKG_ERRF_OK;
274*a3cefe7fSPierre Pronchery }
275*a3cefe7fSPierre Pronchery
276*a3cefe7fSPierre Pronchery /*
277*a3cefe7fSPierre Pronchery * !doc
278*a3cefe7fSPierre Pronchery *
279*a3cefe7fSPierre Pronchery * .. c:function:: void pkgconf_solution_free(pkgconf_client_t *client, pkgconf_pkg_t *world, int maxdepth)
280*a3cefe7fSPierre Pronchery *
281*a3cefe7fSPierre Pronchery * Removes references to package nodes contained in a solution.
282*a3cefe7fSPierre Pronchery *
283*a3cefe7fSPierre Pronchery * :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
284*a3cefe7fSPierre Pronchery * :param pkgconf_pkg_t* world: The root for the generated dependency graph. Should have PKGCONF_PKG_PROPF_VIRTUAL flag.
285*a3cefe7fSPierre Pronchery * :returns: nothing
286*a3cefe7fSPierre Pronchery */
287*a3cefe7fSPierre Pronchery void
pkgconf_solution_free(pkgconf_client_t * client,pkgconf_pkg_t * world)288*a3cefe7fSPierre Pronchery pkgconf_solution_free(pkgconf_client_t *client, pkgconf_pkg_t *world)
289*a3cefe7fSPierre Pronchery {
290*a3cefe7fSPierre Pronchery (void) client;
291*a3cefe7fSPierre Pronchery
292*a3cefe7fSPierre Pronchery if (world->flags & PKGCONF_PKG_PROPF_VIRTUAL)
293*a3cefe7fSPierre Pronchery {
294*a3cefe7fSPierre Pronchery pkgconf_dependency_free(&world->required);
295*a3cefe7fSPierre Pronchery pkgconf_dependency_free(&world->requires_private);
296*a3cefe7fSPierre Pronchery }
297*a3cefe7fSPierre Pronchery }
298*a3cefe7fSPierre Pronchery
299*a3cefe7fSPierre Pronchery /*
300*a3cefe7fSPierre Pronchery * !doc
301*a3cefe7fSPierre Pronchery *
302*a3cefe7fSPierre Pronchery * .. c:function:: bool pkgconf_queue_solve(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_pkg_t *world, int maxdepth)
303*a3cefe7fSPierre Pronchery *
304*a3cefe7fSPierre Pronchery * Solves and flattens the dependency graph for the supplied dependency list.
305*a3cefe7fSPierre Pronchery *
306*a3cefe7fSPierre Pronchery * :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
307*a3cefe7fSPierre Pronchery * :param pkgconf_list_t* list: The list of dependency requests to consider.
308*a3cefe7fSPierre Pronchery * :param pkgconf_pkg_t* world: The root for the generated dependency graph, provided by the caller. Should have PKGCONF_PKG_PROPF_VIRTUAL flag.
309*a3cefe7fSPierre Pronchery * :param int maxdepth: The maximum allowed depth for the dependency resolver. A depth of -1 means unlimited.
310*a3cefe7fSPierre Pronchery * :returns: true if the dependency resolver found a solution, otherwise false.
311*a3cefe7fSPierre Pronchery * :rtype: bool
312*a3cefe7fSPierre Pronchery */
313*a3cefe7fSPierre Pronchery bool
pkgconf_queue_solve(pkgconf_client_t * client,pkgconf_list_t * list,pkgconf_pkg_t * world,int maxdepth)314*a3cefe7fSPierre Pronchery pkgconf_queue_solve(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_pkg_t *world, int maxdepth)
315*a3cefe7fSPierre Pronchery {
316*a3cefe7fSPierre Pronchery /* if maxdepth is one, then we will not traverse deeper than our virtual package. */
317*a3cefe7fSPierre Pronchery if (!maxdepth)
318*a3cefe7fSPierre Pronchery maxdepth = -1;
319*a3cefe7fSPierre Pronchery
320*a3cefe7fSPierre Pronchery unsigned int flags = client->flags;
321*a3cefe7fSPierre Pronchery client->flags |= PKGCONF_PKG_PKGF_SEARCH_PRIVATE;
322*a3cefe7fSPierre Pronchery
323*a3cefe7fSPierre Pronchery unsigned int ret = pkgconf_queue_verify(client, world, list, maxdepth);
324*a3cefe7fSPierre Pronchery client->flags = flags;
325*a3cefe7fSPierre Pronchery
326*a3cefe7fSPierre Pronchery return ret == PKGCONF_PKG_ERRF_OK;
327*a3cefe7fSPierre Pronchery }
328*a3cefe7fSPierre Pronchery
329*a3cefe7fSPierre Pronchery /*
330*a3cefe7fSPierre Pronchery * !doc
331*a3cefe7fSPierre Pronchery *
332*a3cefe7fSPierre Pronchery * .. c:function:: void pkgconf_queue_apply(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_queue_apply_func_t func, int maxdepth, void *data)
333*a3cefe7fSPierre Pronchery *
334*a3cefe7fSPierre Pronchery * Attempt to compile a dependency resolution queue into a dependency resolution problem, then attempt to solve the problem and
335*a3cefe7fSPierre Pronchery * feed the solution to a callback function if a complete dependency graph is found.
336*a3cefe7fSPierre Pronchery *
337*a3cefe7fSPierre Pronchery * This function should not be used in new code. Use pkgconf_queue_solve instead.
338*a3cefe7fSPierre Pronchery *
339*a3cefe7fSPierre Pronchery * :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
340*a3cefe7fSPierre Pronchery * :param pkgconf_list_t* list: The list of dependency requests to consider.
341*a3cefe7fSPierre Pronchery * :param pkgconf_queue_apply_func_t func: The callback function to call if a solution is found by the dependency resolver.
342*a3cefe7fSPierre Pronchery * :param int maxdepth: The maximum allowed depth for the dependency resolver. A depth of -1 means unlimited.
343*a3cefe7fSPierre Pronchery * :param void* data: An opaque pointer which is passed to the callback function.
344*a3cefe7fSPierre Pronchery * :returns: true if the dependency resolver found a solution, otherwise false.
345*a3cefe7fSPierre Pronchery * :rtype: bool
346*a3cefe7fSPierre Pronchery */
347*a3cefe7fSPierre Pronchery bool
pkgconf_queue_apply(pkgconf_client_t * client,pkgconf_list_t * list,pkgconf_queue_apply_func_t func,int maxdepth,void * data)348*a3cefe7fSPierre Pronchery pkgconf_queue_apply(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_queue_apply_func_t func, int maxdepth, void *data)
349*a3cefe7fSPierre Pronchery {
350*a3cefe7fSPierre Pronchery bool ret = false;
351*a3cefe7fSPierre Pronchery pkgconf_pkg_t world = {
352*a3cefe7fSPierre Pronchery .id = "virtual:world",
353*a3cefe7fSPierre Pronchery .realname = "virtual world package",
354*a3cefe7fSPierre Pronchery .flags = PKGCONF_PKG_PROPF_STATIC | PKGCONF_PKG_PROPF_VIRTUAL,
355*a3cefe7fSPierre Pronchery };
356*a3cefe7fSPierre Pronchery
357*a3cefe7fSPierre Pronchery /* if maxdepth is one, then we will not traverse deeper than our virtual package. */
358*a3cefe7fSPierre Pronchery if (!maxdepth)
359*a3cefe7fSPierre Pronchery maxdepth = -1;
360*a3cefe7fSPierre Pronchery
361*a3cefe7fSPierre Pronchery if (!pkgconf_queue_solve(client, list, &world, maxdepth))
362*a3cefe7fSPierre Pronchery goto cleanup;
363*a3cefe7fSPierre Pronchery
364*a3cefe7fSPierre Pronchery /* the world dependency set is flattened after it is returned from pkgconf_queue_verify */
365*a3cefe7fSPierre Pronchery if (!func(client, &world, data, maxdepth))
366*a3cefe7fSPierre Pronchery goto cleanup;
367*a3cefe7fSPierre Pronchery
368*a3cefe7fSPierre Pronchery ret = true;
369*a3cefe7fSPierre Pronchery
370*a3cefe7fSPierre Pronchery cleanup:
371*a3cefe7fSPierre Pronchery pkgconf_pkg_free(client, &world);
372*a3cefe7fSPierre Pronchery return ret;
373*a3cefe7fSPierre Pronchery }
374*a3cefe7fSPierre Pronchery
375*a3cefe7fSPierre Pronchery /*
376*a3cefe7fSPierre Pronchery * !doc
377*a3cefe7fSPierre Pronchery *
378*a3cefe7fSPierre Pronchery * .. c:function:: void pkgconf_queue_validate(pkgconf_client_t *client, pkgconf_list_t *list, pkgconf_queue_apply_func_t func, int maxdepth, void *data)
379*a3cefe7fSPierre Pronchery *
380*a3cefe7fSPierre Pronchery * Attempt to compile a dependency resolution queue into a dependency resolution problem, then attempt to solve the problem.
381*a3cefe7fSPierre Pronchery *
382*a3cefe7fSPierre Pronchery * :param pkgconf_client_t* client: The pkgconf client object to use for dependency resolution.
383*a3cefe7fSPierre Pronchery * :param pkgconf_list_t* list: The list of dependency requests to consider.
384*a3cefe7fSPierre Pronchery * :param int maxdepth: The maximum allowed depth for the dependency resolver. A depth of -1 means unlimited.
385*a3cefe7fSPierre Pronchery * :returns: true if the dependency resolver found a solution, otherwise false.
386*a3cefe7fSPierre Pronchery * :rtype: bool
387*a3cefe7fSPierre Pronchery */
388*a3cefe7fSPierre Pronchery bool
pkgconf_queue_validate(pkgconf_client_t * client,pkgconf_list_t * list,int maxdepth)389*a3cefe7fSPierre Pronchery pkgconf_queue_validate(pkgconf_client_t *client, pkgconf_list_t *list, int maxdepth)
390*a3cefe7fSPierre Pronchery {
391*a3cefe7fSPierre Pronchery bool retval = true;
392*a3cefe7fSPierre Pronchery pkgconf_pkg_t world = {
393*a3cefe7fSPierre Pronchery .id = "virtual:world",
394*a3cefe7fSPierre Pronchery .realname = "virtual world package",
395*a3cefe7fSPierre Pronchery .flags = PKGCONF_PKG_PROPF_STATIC | PKGCONF_PKG_PROPF_VIRTUAL,
396*a3cefe7fSPierre Pronchery };
397*a3cefe7fSPierre Pronchery
398*a3cefe7fSPierre Pronchery /* if maxdepth is one, then we will not traverse deeper than our virtual package. */
399*a3cefe7fSPierre Pronchery if (!maxdepth)
400*a3cefe7fSPierre Pronchery maxdepth = -1;
401*a3cefe7fSPierre Pronchery
402*a3cefe7fSPierre Pronchery if (pkgconf_queue_verify(client, &world, list, maxdepth) != PKGCONF_PKG_ERRF_OK)
403*a3cefe7fSPierre Pronchery retval = false;
404*a3cefe7fSPierre Pronchery
405*a3cefe7fSPierre Pronchery pkgconf_pkg_free(client, &world);
406*a3cefe7fSPierre Pronchery
407*a3cefe7fSPierre Pronchery return retval;
408*a3cefe7fSPierre Pronchery }
409