Esempio n. 1
0
/* Re-order a list of target packages with respect to their dependencies.
 *
 * Example (reverse == 0):
 *   A depends on C
 *   B depends on A
 *   Target order is A,B,C,D
 *
 *   Should be re-ordered to C,A,B,D
 *
 * packages listed in ignore will not be used to detect indirect dependencies
 *
 * if reverse is > 0, the dependency order will be reversed.
 *
 * This function returns the new alpm_list_t* target list.
 *
 */
alpm_list_t *_alpm_sortbydeps(alpm_handle_t *handle,
		alpm_list_t *targets, alpm_list_t *ignore, int reverse)
{
	alpm_list_t *newtargs = NULL;
	alpm_list_t *vertices = NULL;
	alpm_list_t *vptr;
	alpm_graph_t *vertex;

	if(targets == NULL) {
		return NULL;
	}

	_alpm_log(handle, ALPM_LOG_DEBUG, "started sorting dependencies\n");

	vertices = dep_graph_init(handle, targets, ignore);

	vptr = vertices;
	vertex = vertices->data;
	while(vptr) {
		/* mark that we touched the vertex */
		vertex->state = -1;
		int found = 0;
		while(vertex->childptr && !found) {
			alpm_graph_t *nextchild = vertex->childptr->data;
			vertex->childptr = vertex->childptr->next;
			if(nextchild->state == 0) {
				found = 1;
				nextchild->parent = vertex;
				vertex = nextchild;
			} else if(nextchild->state == -1) {
				/* child is an ancestor of vertex */
				alpm_graph_t *transvertex = vertex;

				if(!alpm_list_find(targets, nextchild->data, ptr_cmp)) {
					/* child is not part of the transaction, not a problem */
					continue;
				}

				/* find the nearest parent that's part of the transaction */
				while(transvertex) {
					if(alpm_list_find(targets, transvertex->data, ptr_cmp)) {
						break;
					}
					transvertex = transvertex->parent;
				}

				if(!transvertex || transvertex == nextchild) {
					/* no transaction package in our ancestry or the package has
					 * a circular dependency with itself, not a problem */
				} else {
					alpm_pkg_t *transpkg = transvertex->data;
					alpm_pkg_t *childpkg = nextchild->data;
					_alpm_log(handle, ALPM_LOG_WARNING, _("dependency cycle detected:\n"));
					if(reverse) {
						_alpm_log(handle, ALPM_LOG_WARNING,
								_("%s will be removed after its %s dependency\n"),
								transpkg->name, childpkg->name);
					} else {
						_alpm_log(handle, ALPM_LOG_WARNING,
								_("%s will be installed before its %s dependency\n"),
								transpkg->name, childpkg->name);
					}
				}
			}
		}
		if(!found) {
			if(alpm_list_find(targets, vertex->data, ptr_cmp)) {
				newtargs = alpm_list_add(newtargs, vertex->data);
			}
			/* mark that we've left this vertex */
			vertex->state = 1;
			vertex = vertex->parent;
			if(!vertex) {
				/* top level vertex reached, move to the next unprocessed vertex */
				for( vptr = vptr->next; vptr; vptr = vptr->next) {
					vertex = vptr->data;
					if(vertex->state == 0) {
						break;
					}
				}
			}
		}
	}

	_alpm_log(handle, ALPM_LOG_DEBUG, "sorting dependencies finished\n");

	if(reverse) {
		/* reverse the order */
		alpm_list_t *tmptargs = alpm_list_reverse(newtargs);
		/* free the old one */
		alpm_list_free(newtargs);
		newtargs = tmptargs;
	}

	alpm_list_free_inner(vertices, _alpm_graph_free);
	alpm_list_free(vertices);

	return newtargs;
}
Esempio n. 2
0
File: deps.c Progetto: mineo/pacman
/* Re-order a list of target packages with respect to their dependencies.
 *
 * Example (reverse == 0):
 *   A depends on C
 *   B depends on A
 *   Target order is A,B,C,D
 *
 *   Should be re-ordered to C,A,B,D
 *
 * if reverse is > 0, the dependency order will be reversed.
 *
 * This function returns the new alpm_list_t* target list.
 *
 */
alpm_list_t *_alpm_sortbydeps(pmhandle_t *handle,
		alpm_list_t *targets, int reverse)
{
	alpm_list_t *newtargs = NULL;
	alpm_list_t *vertices = NULL;
	alpm_list_t *vptr;
	pmgraph_t *vertex;

	if(targets == NULL) {
		return NULL;
	}

	_alpm_log(handle, PM_LOG_DEBUG, "started sorting dependencies\n");

	vertices = dep_graph_init(targets);

	vptr = vertices;
	vertex = vertices->data;
	while(vptr) {
		/* mark that we touched the vertex */
		vertex->state = -1;
		int found = 0;
		while(vertex->childptr && !found) {
			pmgraph_t *nextchild = vertex->childptr->data;
			vertex->childptr = vertex->childptr->next;
			if(nextchild->state == 0) {
				found = 1;
				nextchild->parent = vertex;
				vertex = nextchild;
			}
			else if(nextchild->state == -1) {
				pmpkg_t *vertexpkg = vertex->data;
				pmpkg_t *childpkg = nextchild->data;
				const char *message;

				_alpm_log(handle, PM_LOG_WARNING, _("dependency cycle detected:\n"));
				if(reverse) {
					message =_("%s will be removed after its %s dependency\n");
				} else {
					message =_("%s will be installed before its %s dependency\n");
				}
				_alpm_log(handle, PM_LOG_WARNING, message, vertexpkg->name, childpkg->name);
			}
		}
		if(!found) {
			newtargs = alpm_list_add(newtargs, vertex->data);
			/* mark that we've left this vertex */
			vertex->state = 1;
			vertex = vertex->parent;
			if(!vertex) {
				vptr = vptr->next;
				while(vptr) {
					vertex = vptr->data;
					if(vertex->state == 0) break;
					vptr = vptr->next;
				}
			}
		}
	}

	_alpm_log(handle, PM_LOG_DEBUG, "sorting dependencies finished\n");

	if(reverse) {
		/* reverse the order */
		alpm_list_t *tmptargs = alpm_list_reverse(newtargs);
		/* free the old one */
		alpm_list_free(newtargs);
		newtargs = tmptargs;
	}

	alpm_list_free_inner(vertices, _alpm_graph_free);
	alpm_list_free(vertices);

	return newtargs;
}