/* 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; }
/* 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; }