Backport from pacman 2.9.5
- list_remove, list_check and list_reverse - sortbydeps(mode)
This commit is contained in:
parent
6e63ccfd0f
commit
7c847fd7d4
|
@ -189,7 +189,7 @@ int add_prepare(pmdb_t *db, pmtrans_t *trans, PMList **data)
|
|||
|
||||
/* re-order w.r.t. dependencies */
|
||||
_alpm_log(PM_LOG_FLOW2, "sorting by dependencies...");
|
||||
lp = sortbydeps(trans->packages);
|
||||
lp = sortbydeps(trans->packages, PM_TRANS_TYPE_ADD);
|
||||
/* free the old alltargs */
|
||||
for(j = trans->packages; j; j = j->next) {
|
||||
j->data = NULL;
|
||||
|
|
|
@ -35,17 +35,20 @@
|
|||
|
||||
/* Re-order a list of target packages with respect to their dependencies.
|
||||
*
|
||||
* Example:
|
||||
* Example (PM_TRANS_TYPE_ADD):
|
||||
* A depends on C
|
||||
* B depends on A
|
||||
* Target order is A,B,C,D
|
||||
*
|
||||
* Should be re-ordered to C,A,B,D
|
||||
*
|
||||
* mode should be either PM_TRANS_TYPE_ADD or PM_TRANS_TYPE_REMOVE. This
|
||||
* affects the dependency order sortbydeps() will use.
|
||||
*
|
||||
* This function returns the new PMList* target list.
|
||||
*
|
||||
*/
|
||||
PMList *sortbydeps(PMList *targets)
|
||||
PMList *sortbydeps(PMList *targets, int mode)
|
||||
{
|
||||
PMList *newtargs = NULL;
|
||||
PMList *i, *j, *k;
|
||||
|
@ -104,11 +107,22 @@ PMList *sortbydeps(PMList *targets)
|
|||
for(i = targets; i; i = i->next) {
|
||||
i->data = NULL;
|
||||
}
|
||||
pm_list_free(targets);
|
||||
FREELIST(targets);
|
||||
}
|
||||
targets = newtargs;
|
||||
clean = 1;
|
||||
}
|
||||
if(mode == PM_TRANS_TYPE_REMOVE) {
|
||||
/* we're removing packages, so reverse the order */
|
||||
newtargs = _alpm_list_reverse(targets);
|
||||
/* free the old one */
|
||||
for(i = targets; i; i = i->next) {
|
||||
i->data = NULL;
|
||||
}
|
||||
FREELIST(targets);
|
||||
targets = newtargs;
|
||||
}
|
||||
|
||||
return(targets);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "db.h"
|
||||
#include "sync.h"
|
||||
|
||||
PMList *sortbydeps(PMList *targets);
|
||||
PMList *sortbydeps(PMList *targets, int mode);
|
||||
PMList *checkdeps(pmdb_t *db, unsigned short op, PMList *packages);
|
||||
void splitdep(char *depstr, pmdepend_t *depend);
|
||||
PMList *removedeps(pmdb_t *db, PMList *targs);
|
||||
|
|
|
@ -23,9 +23,34 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
/* pacman */
|
||||
#include "list.h"
|
||||
|
||||
/* Check PMList sanity
|
||||
*
|
||||
* 1: List seems to be OK.
|
||||
* 0: We're in deep ...
|
||||
*/
|
||||
int _alpm_list_check(PMList* list)
|
||||
{
|
||||
PMList* it = NULL;
|
||||
|
||||
if(list == NULL) {
|
||||
return(1);
|
||||
}
|
||||
if(list->last == NULL) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
for(it = list; it && it->next; it = it->next);
|
||||
if(it != list->last) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
PMList* pm_list_new()
|
||||
{
|
||||
PMList *list = NULL;
|
||||
|
@ -37,6 +62,7 @@ PMList* pm_list_new()
|
|||
list->data = NULL;
|
||||
list->prev = NULL;
|
||||
list->next = NULL;
|
||||
list->last = list;
|
||||
return(list);
|
||||
}
|
||||
|
||||
|
@ -74,9 +100,13 @@ PMList* pm_list_add(PMList *list, void *data)
|
|||
return(NULL);
|
||||
}
|
||||
lp->next->prev = lp;
|
||||
lp->last = NULL;
|
||||
lp = lp->next;
|
||||
}
|
||||
|
||||
lp->data = data;
|
||||
ptr->last = lp;
|
||||
|
||||
return(ptr);
|
||||
}
|
||||
|
||||
|
@ -102,64 +132,79 @@ PMList* pm_list_add_sorted(PMList *list, void *data, pm_fn_cmp fn)
|
|||
/* Insert node before insertion point. */
|
||||
add->prev = prev;
|
||||
add->next = iter;
|
||||
|
||||
if(iter != NULL) {
|
||||
/* Not at end. */
|
||||
iter->prev = add;
|
||||
}
|
||||
if(prev != NULL) {
|
||||
/* In middle. */
|
||||
prev->next = add;
|
||||
iter->prev = add; /* Not at end. */
|
||||
} else {
|
||||
/* Start or empty, new list head. */
|
||||
list = add;
|
||||
if (list != NULL) {
|
||||
list->last = add; /* Added new to end, so update the link to last. */
|
||||
}
|
||||
}
|
||||
|
||||
if(prev != NULL) {
|
||||
prev->next = add; /* In middle. */
|
||||
} else {
|
||||
if(list == NULL) {
|
||||
add->last = add;
|
||||
} else {
|
||||
add->last = list->last;
|
||||
list->last = NULL;
|
||||
}
|
||||
list = add; /* Start or empty, new list head. */
|
||||
}
|
||||
|
||||
return(list);
|
||||
}
|
||||
|
||||
/* Remove an item in a list. Use the given comparaison function to find the
|
||||
* item.
|
||||
* If found, 'ptr' is set to point to the removed element, so that the caller
|
||||
* can free it. Otherwise, ptr is NULL.
|
||||
* Return the new list (without the removed element).
|
||||
/* list: the beginning of the list
|
||||
* item: the item in the list to be removed
|
||||
*
|
||||
* returns:
|
||||
* list with item removed
|
||||
*/
|
||||
PMList *_alpm_list_remove(PMList *list, void *data, pm_fn_cmp fn, void **ptr)
|
||||
|
||||
PMList* list_remove(PMList* list, PMList* item)
|
||||
{
|
||||
PMList *i = list;
|
||||
assert(_alpm_list_check(list));
|
||||
|
||||
while(i) {
|
||||
if(fn(data, i->data) == 0) {
|
||||
break;
|
||||
}
|
||||
i = i->next;
|
||||
if(list == NULL || item == NULL) {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if(ptr) {
|
||||
*ptr = NULL;
|
||||
}
|
||||
|
||||
if(i) {
|
||||
/* we found a matching item */
|
||||
if(i->next) {
|
||||
i->next->prev = i->prev;
|
||||
}
|
||||
if(i->prev) {
|
||||
i->prev->next = i->next;
|
||||
}
|
||||
if(i == list) {
|
||||
/* The item found is the first in the chain,
|
||||
* so we move the header to the next element.
|
||||
*/
|
||||
/* Remove first item in list. */
|
||||
if(item == list) {
|
||||
if(list->next == NULL) { /* Only item in list. */
|
||||
pm_list_free(item);
|
||||
return(NULL);
|
||||
} else {
|
||||
list->next->prev = NULL;
|
||||
list->next->last = list->last;
|
||||
list = list->next;
|
||||
item->prev = item->next = NULL;
|
||||
pm_list_free(item);
|
||||
return(list);
|
||||
}
|
||||
|
||||
if(ptr) {
|
||||
*ptr = i->data;
|
||||
}
|
||||
|
||||
free(i);
|
||||
}
|
||||
|
||||
/* Remove last item in list. */
|
||||
if(list->last == item) {
|
||||
list->last = item->prev;
|
||||
item->prev->next = NULL;
|
||||
item->prev = item->next = NULL;
|
||||
pm_list_free(item);
|
||||
return(list);
|
||||
}
|
||||
|
||||
/* Remove middle item in list. */
|
||||
assert(item->prev != NULL && item->next != NULL);
|
||||
|
||||
item->prev->next = item->next;
|
||||
item->next->prev = item->prev;
|
||||
item->prev = item->next = NULL;
|
||||
pm_list_free(item);
|
||||
|
||||
assert(_alpm_list_check(list));
|
||||
|
||||
return(list);
|
||||
}
|
||||
|
||||
|
@ -201,10 +246,31 @@ PMList *pm_list_is_strin(char *needle, PMList *haystack)
|
|||
|
||||
PMList* pm_list_last(PMList *list)
|
||||
{
|
||||
PMList *ptr;
|
||||
if (list == NULL)
|
||||
return(NULL);
|
||||
|
||||
for(ptr = list; ptr && ptr->next; ptr = ptr->next);
|
||||
return(ptr);
|
||||
assert(list->last != NULL);
|
||||
|
||||
return(list->last);
|
||||
}
|
||||
|
||||
/* Reverse the order of a list
|
||||
*
|
||||
* The caller is responsible for freeing the old list
|
||||
*/
|
||||
PMList* _alpm_list_reverse(PMList *list)
|
||||
{
|
||||
/* simple but functional -- we just build a new list, starting
|
||||
* with the old list's tail
|
||||
*/
|
||||
PMList *newlist = NULL;
|
||||
PMList *lp;
|
||||
|
||||
for(lp = list->last; lp; lp = lp->prev) {
|
||||
newlist = pm_list_add(newlist, lp->data);
|
||||
}
|
||||
|
||||
return(newlist);
|
||||
}
|
||||
|
||||
/* vim: set ts=2 sw=2 noet: */
|
||||
|
|
|
@ -26,6 +26,7 @@ typedef struct __pmlist_t {
|
|||
void *data;
|
||||
struct __pmlist_t *prev;
|
||||
struct __pmlist_t *next;
|
||||
struct __pmlist_t *last;
|
||||
} pmlist_t;
|
||||
|
||||
typedef struct __pmlist_t PMList;
|
||||
|
@ -39,11 +40,12 @@ PMList *pm_list_new();
|
|||
void pm_list_free(PMList *list);
|
||||
PMList *pm_list_add(PMList *list, void *data);
|
||||
PMList *pm_list_add_sorted(PMList *list, void *data, pm_fn_cmp fn);
|
||||
PMList *_alpm_list_remove(PMList *list, void *data, pm_fn_cmp fn, void **ptr);
|
||||
PMList* _alpm_list_remove(PMList* list, PMList* item);
|
||||
int pm_list_count(PMList *list);
|
||||
int pm_list_is_ptrin(PMList *haystack, void *needle);
|
||||
PMList *pm_list_is_strin(char *needle, PMList *haystack);
|
||||
PMList *pm_list_last(PMList *list);
|
||||
PMList *_alpm_list_reverse(PMList *list);
|
||||
|
||||
#endif /* _ALPM_LIST_H */
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ int remove_loadtarget(pmdb_t *db, pmtrans_t *trans, char *name)
|
|||
int remove_prepare(pmdb_t *db, pmtrans_t *trans, PMList **data)
|
||||
{
|
||||
pmpkg_t *info;
|
||||
PMList *lp;
|
||||
PMList *lp, *i;
|
||||
|
||||
ASSERT(db != NULL, RET_ERR(PM_ERR_DB_NULL, -1));
|
||||
ASSERT(trans != NULL, RET_ERR(PM_ERR_TRANS_NULL, -1));
|
||||
|
@ -99,6 +99,16 @@ int remove_prepare(pmdb_t *db, pmtrans_t *trans, PMList **data)
|
|||
trans->packages = removedeps(db, trans->packages);
|
||||
}
|
||||
|
||||
/* re-order w.r.t. dependencies */
|
||||
_alpm_log(PM_LOG_FLOW2, "sorting by dependencies...");
|
||||
lp = sortbydeps(trans->packages, PM_TRANS_TYPE_REMOVE);
|
||||
/* free the old alltargs */
|
||||
for(i = trans->packages; i; i = i->next) {
|
||||
i->data = NULL;
|
||||
}
|
||||
FREELIST(trans->packages);
|
||||
trans->packages = lp;
|
||||
|
||||
TRANS_CB(trans, PM_TRANS_EVT_DEPS_DONE, NULL, NULL);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue