libopkg: implement lightweight package listing logic
[oweals/opkg-lede.git] / libopkg / pkg_depends.c
index 70c292291855e2707cc4d31e756bb1fcd0e08d7c..3abdcd38c4436468bed71929c7114ceb3dfacdc9 100644 (file)
@@ -26,7 +26,7 @@
 #include "hash_table.h"
 #include "libbb/libbb.h"
 
-static int parseDepends(compound_depend_t * compound_depend, char *depend_str);
+static int parseDepends(compound_depend_t * compound_depend, char *depend_str, enum depend_type type);
 static depend_t *depend_init(void);
 static char **add_unresolved_dep(pkg_t * pkg, char **the_lost, int ref_ndx);
 static char **merge_unresolved(char **oldstuff, char **newstuff);
@@ -59,9 +59,10 @@ pkg_hash_fetch_unsatisfied_dependencies(pkg_t * pkg, pkg_vec_t * unsatisfied,
 {
        pkg_t *satisfier_entry_pkg;
        int i, j, k;
-       int count, found;
+       int found;
        char **the_lost;
        abstract_pkg_t *ab_pkg;
+       compound_depend_t *compound_depend;
 
        /*
         * this is a setup to check for redundant/cyclic dependency checks,
@@ -78,11 +79,10 @@ pkg_hash_fetch_unsatisfied_dependencies(pkg_t * pkg, pkg_vec_t * unsatisfied,
        } else {
                ab_pkg->dependencies_checked = 1;       /* mark it for subsequent visits */
        }
-        /**/
-           count =
-           pkg->pre_depends_count + pkg->depends_count +
-           pkg->recommends_count + pkg->suggests_count;
-       if (!count) {
+
+       compound_depend = pkg_get_ptr(pkg, PKG_DEPENDS);
+
+       if (!compound_depend || !compound_depend->type) {
                *unresolved = NULL;
                return 0;
        }
@@ -90,8 +90,7 @@ pkg_hash_fetch_unsatisfied_dependencies(pkg_t * pkg, pkg_vec_t * unsatisfied,
        the_lost = NULL;
 
        /* foreach dependency */
-       for (i = 0; i < count; i++) {
-               compound_depend_t *compound_depend = &pkg->depends[i];
+       for (i = 0; compound_depend && compound_depend->type; compound_depend++, i++) {
                depend_t **possible_satisfiers =
                    compound_depend->possibilities;;
                found = 0;
@@ -101,17 +100,13 @@ pkg_hash_fetch_unsatisfied_dependencies(pkg_t * pkg, pkg_vec_t * unsatisfied,
                        /* foreach possible satisfier */
                        for (j = 0; j < compound_depend->possibility_count; j++) {
                                /* foreach provided_by, which includes the abstract_pkg itself */
-                               abstract_pkg_t *abpkg =
-                                   possible_satisfiers[j]->pkg;
-                               abstract_pkg_vec_t *ab_provider_vec =
-                                   abpkg->provided_by;
+                               abstract_pkg_t *abpkg = possible_satisfiers[j]->pkg;
+                               abstract_pkg_vec_t *ab_provider_vec = abpkg->provided_by;
                                int nposs = ab_provider_vec->len;
-                               abstract_pkg_t **ab_providers =
-                                   ab_provider_vec->pkgs;
+                               abstract_pkg_t **ab_providers = ab_provider_vec->pkgs;
                                int l;
                                for (l = 0; l < nposs; l++) {
-                                       pkg_vec_t *test_vec =
-                                           ab_providers[l]->pkgs;
+                                       pkg_vec_t *test_vec = ab_providers[l]->pkgs;
                                        /* if no depends on this one, try the first package that Provides this one */
                                        if (!test_vec) {        /* no pkg_vec hooked up to the abstract_pkg!  (need another feed?) */
                                                continue;
@@ -119,69 +114,45 @@ pkg_hash_fetch_unsatisfied_dependencies(pkg_t * pkg, pkg_vec_t * unsatisfied,
 
                                        /* cruise this possiblity's pkg_vec looking for an installed version */
                                        for (k = 0; k < test_vec->len; k++) {
-                                               pkg_t *pkg_scout =
-                                                   test_vec->pkgs[k];
+                                               pkg_t *pkg_scout = test_vec->pkgs[k];
                                                /* not installed, and not already known about? */
-                                               if ((pkg_scout->state_want !=
-                                                    SW_INSTALL)
-                                                   && !pkg_scout->parent->
-                                                   dependencies_checked
-                                                   &&
-                                                   !is_pkg_in_pkg_vec
-                                                   (unsatisfied, pkg_scout)) {
+                                               if ((pkg_scout->state_want != SW_INSTALL)
+                                                   && !pkg_scout->parent->dependencies_checked
+                                                   && !is_pkg_in_pkg_vec(unsatisfied, pkg_scout)) {
                                                        char **newstuff = NULL;
                                                        int rc;
-                                                       pkg_vec_t *tmp_vec =
-                                                           pkg_vec_alloc();
+                                                       pkg_vec_t *tmp_vec = pkg_vec_alloc();
                                                        /* check for not-already-installed dependencies */
-                                                       rc = pkg_hash_fetch_unsatisfied_dependencies(pkg_scout, tmp_vec, &newstuff);
+                                                       rc = pkg_hash_fetch_unsatisfied_dependencies(
+                                                               pkg_scout, tmp_vec, &newstuff);
                                                        if (newstuff == NULL) {
                                                                int m;
                                                                int ok = 1;
-                                                               for (m = 0;
-                                                                    m < rc;
-                                                                    m++) {
-                                                                       pkg_t *p
-                                                                           =
-                                                                           tmp_vec->
-                                                                           pkgs
-                                                                           [m];
-                                                                       if (p->
-                                                                           state_want
-                                                                           ==
-                                                                           SW_INSTALL)
+                                                               for (m = 0; m < rc; m++) {
+                                                                       pkg_t *p = tmp_vec->pkgs[m];
+                                                                       if (p->state_want == SW_INSTALL)
                                                                                continue;
-                                                                       opkg_msg
-                                                                           (DEBUG,
+                                                                       opkg_msg(DEBUG,
                                                                             "Not installing %s due"
                                                                             " to requirement for %s.\n",
-                                                                            pkg_scout->
-                                                                            name,
-                                                                            p->
-                                                                            name);
+                                                                            pkg_scout->name, p->name);
                                                                        ok = 0;
                                                                        break;
                                                                }
-                                                               pkg_vec_free
-                                                                   (tmp_vec);
+                                                               pkg_vec_free(tmp_vec);
                                                                if (ok) {
                                                                        /* mark this one for installation */
-                                                                       opkg_msg
-                                                                           (NOTICE,
+                                                                       opkg_msg(NOTICE,
                                                                             "Adding satisfier for greedy"
                                                                             " dependence %s.\n",
-                                                                            pkg_scout->
-                                                                            name);
-                                                                       pkg_vec_insert
-                                                                           (unsatisfied,
-                                                                            pkg_scout);
+                                                                            pkg_scout->name);
+                                                                       pkg_vec_insert(unsatisfied, pkg_scout);
                                                                }
                                                        } else {
                                                                opkg_msg(DEBUG,
                                                                         "Not installing %s due to "
                                                                         "broken depends.\n",
-                                                                        pkg_scout->
-                                                                        name);
+                                                                        pkg_scout->name);
                                                                free(newstuff);
                                                        }
                                                }
@@ -195,15 +166,12 @@ pkg_hash_fetch_unsatisfied_dependencies(pkg_t * pkg, pkg_vec_t * unsatisfied,
                /* foreach possible satisfier, look for installed package  */
                for (j = 0; j < compound_depend->possibility_count; j++) {
                        /* foreach provided_by, which includes the abstract_pkg itself */
-                       depend_t *dependence_to_satisfy =
-                           possible_satisfiers[j];
-                       abstract_pkg_t *satisfying_apkg =
-                           possible_satisfiers[j]->pkg;
+                       depend_t *dependence_to_satisfy = possible_satisfiers[j];
+                       abstract_pkg_t *satisfying_apkg = possible_satisfiers[j]->pkg;
                        pkg_t *satisfying_pkg =
-                           pkg_hash_fetch_best_installation_candidate
-                           (satisfying_apkg,
-                            pkg_installed_and_constraint_satisfied,
-                            dependence_to_satisfy, 1);
+                               pkg_hash_fetch_best_installation_candidate(satisfying_apkg,
+                                       pkg_installed_and_constraint_satisfied,
+                                       dependence_to_satisfy, 1);
                        /* Being that I can't test constraing in pkg_hash, I will test it here */
                        if (satisfying_pkg != NULL) {
                                if (!pkg_installed_and_constraint_satisfied
@@ -223,20 +191,15 @@ pkg_hash_fetch_unsatisfied_dependencies(pkg_t * pkg, pkg_vec_t * unsatisfied,
                        /* foreach possible satisfier, look for installed package  */
                        for (j = 0; j < compound_depend->possibility_count; j++) {
                                /* foreach provided_by, which includes the abstract_pkg itself */
-                               depend_t *dependence_to_satisfy =
-                                   possible_satisfiers[j];
-                               abstract_pkg_t *satisfying_apkg =
-                                   possible_satisfiers[j]->pkg;
+                               depend_t *dependence_to_satisfy = possible_satisfiers[j];
+                               abstract_pkg_t *satisfying_apkg = possible_satisfiers[j]->pkg;
                                pkg_t *satisfying_pkg =
-                                   pkg_hash_fetch_best_installation_candidate
-                                   (satisfying_apkg,
-                                    pkg_constraint_satisfied,
-                                    dependence_to_satisfy, 1);
+                                       pkg_hash_fetch_best_installation_candidate(satisfying_apkg,
+                                               pkg_constraint_satisfied, dependence_to_satisfy, 1);
                                /* Being that I can't test constraing in pkg_hash, I will test it here too */
                                if (satisfying_pkg != NULL) {
-                                       if (!pkg_constraint_satisfied
-                                           (satisfying_pkg,
-                                            dependence_to_satisfy)) {
+                                       if (!pkg_constraint_satisfied(satisfying_pkg,
+                                                       dependence_to_satisfy)) {
                                                satisfying_pkg = NULL;
                                        }
                                }
@@ -244,16 +207,13 @@ pkg_hash_fetch_unsatisfied_dependencies(pkg_t * pkg, pkg_vec_t * unsatisfied,
                                /* user request overrides package recommendation */
                                if (satisfying_pkg != NULL
                                    && (compound_depend->type == RECOMMEND
-                                       || compound_depend->type == SUGGEST)
-                                   && (satisfying_pkg->state_want ==
-                                       SW_DEINSTALL
-                                       || satisfying_pkg->state_want ==
-                                       SW_PURGE)) {
+                                           || compound_depend->type == SUGGEST)
+                                   && (satisfying_pkg->state_want == SW_DEINSTALL
+                                           || satisfying_pkg->state_want == SW_PURGE)) {
                                        opkg_msg(NOTICE,
                                                 "%s: ignoring recommendation for "
                                                 "%s at user request\n",
-                                                pkg->name,
-                                                satisfying_pkg->name);
+                                                pkg->name, satisfying_pkg->name);
                                        continue;
                                }
 
@@ -272,37 +232,28 @@ pkg_hash_fetch_unsatisfied_dependencies(pkg_t * pkg, pkg_vec_t * unsatisfied,
                                /* failure to meet recommendations is not an error */
                                if (compound_depend->type != RECOMMEND
                                    && compound_depend->type != SUGGEST)
-                                       the_lost =
-                                           add_unresolved_dep(pkg, the_lost,
-                                                              i);
+                                       the_lost = add_unresolved_dep(pkg, the_lost, i);
                                else
                                        opkg_msg(NOTICE,
-                                                "%s: unsatisfied recommendation for %s\n",
-                                                pkg->name,
-                                                compound_depend->
-                                                possibilities[0]->pkg->name);
+                                               "%s: unsatisfied recommendation for %s\n",
+                                               pkg->name,
+                                               compound_depend->possibilities[0]->pkg->name);
                        } else {
                                if (compound_depend->type == SUGGEST) {
                                        /* just mention it politely */
                                        opkg_msg(NOTICE,
-                                                "package %s suggests installing %s\n",
-                                                pkg->name,
-                                                satisfier_entry_pkg->name);
+                                               "package %s suggests installing %s\n",
+                                               pkg->name, satisfier_entry_pkg->name);
                                } else {
                                        char **newstuff = NULL;
 
                                        if (satisfier_entry_pkg != pkg &&
-                                           !is_pkg_in_pkg_vec(unsatisfied,
-                                                              satisfier_entry_pkg))
+                                           !is_pkg_in_pkg_vec(unsatisfied, satisfier_entry_pkg))
                                        {
-                                               pkg_vec_insert(unsatisfied,
-                                                              satisfier_entry_pkg);
-                                               pkg_hash_fetch_unsatisfied_dependencies
-                                                   (satisfier_entry_pkg,
-                                                    unsatisfied, &newstuff);
-                                               the_lost =
-                                                   merge_unresolved(the_lost,
-                                                                    newstuff);
+                                               pkg_hash_fetch_unsatisfied_dependencies(
+                                                       satisfier_entry_pkg, unsatisfied, &newstuff);
+                                               pkg_vec_insert(unsatisfied, satisfier_entry_pkg);
+                                               the_lost = merge_unresolved(the_lost, newstuff);
                                                if (newstuff)
                                                        free(newstuff);
                                        }
@@ -322,34 +273,30 @@ pkg_hash_fetch_unsatisfied_dependencies(pkg_t * pkg, pkg_vec_t * unsatisfied,
 */
 static int is_pkg_a_replaces(pkg_t * pkg_scout, pkg_t * pkg)
 {
-       int i;
-       int replaces_count = pkg->replaces_count;
-       abstract_pkg_t **replaces;
+       abstract_pkg_t **replaces = pkg_get_ptr(pkg, PKG_REPLACES);
 
-       if (pkg->replaces_count == 0)   // No replaces, it's surely a conflict
+       if (!replaces || !*replaces)
                return 0;
 
-       replaces = pkg->replaces;
-
-       for (i = 0; i < replaces_count; i++) {
-               if (strcmp(pkg_scout->name, pkg->replaces[i]->name) == 0) {     // Found
+       while (*replaces) {
+               if (strcmp(pkg_scout->name, (*replaces)->name) == 0) {  // Found
                        opkg_msg(DEBUG2, "Seems I've found a replace %s %s\n",
-                                pkg_scout->name, pkg->replaces[i]->name);
+                                pkg_scout->name, (*replaces)->name);
                        return 1;
                }
+               replaces++;
        }
-       return 0;
 
+       return 0;
 }
 
 pkg_vec_t *pkg_hash_fetch_conflicts(pkg_t * pkg)
 {
        pkg_vec_t *installed_conflicts, *test_vec;
-       compound_depend_t *conflicts;
+       compound_depend_t *conflicts, *conflict;
        depend_t **possible_satisfiers;
        depend_t *possible_satisfier;
-       int i, j, k;
-       int count;
+       int j, k;
        abstract_pkg_t *ab_pkg;
        pkg_t **pkg_scouts;
        pkg_t *pkg_scout;
@@ -364,17 +311,14 @@ pkg_vec_t *pkg_hash_fetch_conflicts(pkg_t * pkg)
                return (pkg_vec_t *) NULL;
        }
 
-       conflicts = pkg->conflicts;
+       conflicts = pkg_get_ptr(pkg, PKG_CONFLICTS);
        if (!conflicts) {
                return (pkg_vec_t *) NULL;
        }
        installed_conflicts = pkg_vec_alloc();
 
-       count = pkg->conflicts_count;
-
        /* foreach conflict */
-       for (i = 0; i < pkg->conflicts_count; i++) {
-
+       for (conflict = conflicts; conflict->type; conflict++ ) {
                possible_satisfiers = conflicts->possibilities;
 
                /* foreach possible satisfier */
@@ -398,21 +342,14 @@ pkg_vec_t *pkg_hash_fetch_conflicts(pkg_t * pkg)
                                                         "Internal error: pkg_scout=NULL\n");
                                                continue;
                                        }
-                                       if ((pkg_scout->state_status ==
-                                            SS_INSTALLED
-                                            || pkg_scout->state_want ==
-                                            SW_INSTALL)
-                                           &&
-                                           version_constraints_satisfied
-                                           (possible_satisfier, pkg_scout)
-                                           && !is_pkg_a_replaces(pkg_scout,
-                                                                 pkg)) {
-                                               if (!is_pkg_in_pkg_vec
-                                                   (installed_conflicts,
-                                                    pkg_scout)) {
-                                                       pkg_vec_insert
-                                                           (installed_conflicts,
-                                                            pkg_scout);
+                                       if ((pkg_scout->state_status == SS_INSTALLED
+                                                || pkg_scout->state_want == SW_INSTALL)
+                                               && version_constraints_satisfied(possible_satisfier,
+                                                       pkg_scout)
+                                               && !is_pkg_a_replaces(pkg_scout, pkg)) {
+                                               if (!is_pkg_in_pkg_vec(installed_conflicts,
+                                                       pkg_scout)) {
+                                                       pkg_vec_insert(installed_conflicts, pkg_scout);
                                                }
                                        }
                                }
@@ -441,7 +378,7 @@ int version_constraints_satisfied(depend_t * depends, pkg_t * pkg)
 
        comparison = pkg_compare_versions(pkg, temp);
 
-       free(temp->version);
+       pkg_deinit(temp);
        free(temp);
 
        if ((depends->constraint == EARLIER) && (comparison < 0))
@@ -485,45 +422,21 @@ int pkg_dependence_satisfiable(depend_t * depend)
        return 0;
 }
 
-int pkg_dependence_satisfied(depend_t * depend)
-{
-       abstract_pkg_t *apkg = depend->pkg;
-       abstract_pkg_vec_t *provider_apkgs = apkg->provided_by;
-       int n_providers = provider_apkgs->len;
-       abstract_pkg_t **apkgs = provider_apkgs->pkgs;
-       int i;
-       int n_pkgs;
-       int j;
-
-       for (i = 0; i < n_providers; i++) {
-               abstract_pkg_t *papkg = apkgs[i];
-               pkg_vec_t *pkg_vec = papkg->pkgs;
-               if (pkg_vec) {
-                       n_pkgs = pkg_vec->len;
-                       for (j = 0; j < n_pkgs; j++) {
-                               pkg_t *pkg = pkg_vec->pkgs[j];
-                               if (version_constraints_satisfied(depend, pkg)) {
-                                       if (pkg->state_status == SS_INSTALLED
-                                           || pkg->state_status == SS_UNPACKED)
-                                               return 1;
-                               }
-                       }
-               }
-       }
-       return 0;
-}
-
 static int is_pkg_in_pkg_vec(pkg_vec_t * vec, pkg_t * pkg)
 {
        int i;
+       char *arch1, *arch2;
        pkg_t **pkgs = vec->pkgs;
+       arch1 = pkg_get_architecture(pkg);
+
+       for (i = 0; i < vec->len; i++) {
+               arch2 = pkg_get_architecture(*(pkgs + i));
 
-       for (i = 0; i < vec->len; i++)
                if ((strcmp(pkg->name, (*(pkgs + i))->name) == 0)
                    && (pkg_compare_versions(pkg, *(pkgs + i)) == 0)
-                   && (strcmp(pkg->architecture, (*(pkgs + i))->architecture)
-                       == 0))
+                   && (strcmp(arch1, arch2) == 0))
                        return 1;
+       }
        return 0;
 }
 
@@ -533,17 +446,15 @@ static int is_pkg_in_pkg_vec(pkg_vec_t * vec, pkg_t * pkg)
  */
 int pkg_replaces(pkg_t * pkg, pkg_t * replacee)
 {
-       abstract_pkg_t **replaces = pkg->replaces;
-       int replaces_count = pkg->replaces_count;
-       int replacee_provides_count = replacee->provides_count;
-       int i, j;
-       for (i = 0; i < replaces_count; i++) {
-               abstract_pkg_t *abstract_replacee = replaces[i];
-               for (j = 0; j < replacee_provides_count; j++) {
-                       if (replacee->provides[j] == abstract_replacee)
+       abstract_pkg_t **replaces = pkg_get_ptr(pkg, PKG_REPLACES);
+       abstract_pkg_t **provides = pkg_get_ptr(replacee, PKG_PROVIDES);
+       abstract_pkg_t **r, **p;
+
+       for (r = replaces; r && *r; r++)
+               for (p = provides; p && *p; p++)
+                       if (*r == *p)
                                return 1;
-               }
-       }
+
        return 0;
 }
 
@@ -553,18 +464,14 @@ int pkg_replaces(pkg_t * pkg, pkg_t * replacee)
  */
 int pkg_conflicts_abstract(pkg_t * pkg, abstract_pkg_t * conflictee)
 {
-       compound_depend_t *conflicts = pkg->conflicts;
-       int conflicts_count = pkg->conflicts_count;
        int i, j;
-       for (i = 0; i < conflicts_count; i++) {
-               int possibility_count = conflicts[i].possibility_count;
-               struct depend **possibilities = conflicts[i].possibilities;
-               for (j = 0; j < possibility_count; j++) {
-                       if (possibilities[j]->pkg == conflictee) {
+       compound_depend_t *conflicts;
+
+       for (conflicts = pkg_get_ptr(pkg, PKG_CONFLICTS), i = 0; conflicts && conflicts[i].type; i++)
+               for (j = 0; j < conflicts[i].possibility_count; j++)
+                       if (conflicts[i].possibilities[j]->pkg == conflictee)
                                return 1;
-                       }
-               }
-       }
+
        return 0;
 }
 
@@ -574,27 +481,16 @@ int pkg_conflicts_abstract(pkg_t * pkg, abstract_pkg_t * conflictee)
  */
 int pkg_conflicts(pkg_t * pkg, pkg_t * conflictee)
 {
-       compound_depend_t *conflicts = pkg->conflicts;
-       int conflicts_count = pkg->conflicts_count;
-       abstract_pkg_t **conflictee_provides = conflictee->provides;
-       int conflictee_provides_count = conflictee->provides_count;
-       int i, j, k;
-       int possibility_count;
-       struct depend **possibilities;
-       abstract_pkg_t *possibility;
-
-       for (i = 0; i < conflicts_count; i++) {
-               possibility_count = conflicts[i].possibility_count;
-               possibilities = conflicts[i].possibilities;
-               for (j = 0; j < possibility_count; j++) {
-                       possibility = possibilities[j]->pkg;
-                       for (k = 0; k < conflictee_provides_count; k++) {
-                               if (possibility == conflictee_provides[k]) {
+       int i, j;
+       compound_depend_t *conflicts;
+       abstract_pkg_t **provider;
+
+       for (conflicts = pkg_get_ptr(pkg, PKG_CONFLICTS), i = 0; conflicts && conflicts[i].type; i++)
+               for (j = 0; j < conflicts[i].possibility_count; j++)
+                       for (provider = pkg_get_ptr(conflictee, PKG_PROVIDES); provider && *provider; provider++)
+                               if (conflicts[i].possibilities[j]->pkg == *provider)
                                        return 1;
-                               }
-                       }
-               }
-       }
+
        return 0;
 }
 
@@ -643,8 +539,176 @@ char **add_unresolved_dep(pkg_t * pkg, char **the_lost, int ref_ndx)
        return resized;
 }
 
+static void flag_related_packages(pkg_t *pkg, int state_flags)
+{
+       int i, j;
+       compound_depend_t *deps;
+
+       for (deps = pkg_get_ptr(pkg, PKG_DEPENDS), i = 0; deps && deps[i].type; i++)
+               for (j = 0; j < deps[i].possibility_count; j++) {
+                       if ((deps[i].possibilities[j]->pkg->state_flag & state_flags) != state_flags) {
+                               opkg_msg(DEBUG, "propagating pkg flag to dependent abpkg %s\n",
+                                        deps[i].possibilities[j]->pkg->name);
+                               deps[i].possibilities[j]->pkg->state_flag |= state_flags;
+                       }
+               }
+
+       for (deps = pkg_get_ptr(pkg, PKG_CONFLICTS), i = 0; deps && deps[i].type; i++)
+               for (j = 0; j < deps[i].possibility_count; j++) {
+                       if ((deps[i].possibilities[j]->pkg->state_flag & state_flags) != state_flags) {
+                               opkg_msg(DEBUG, "propagating pkg flag to conflicting abpkg %s\n",
+                                        deps[i].possibilities[j]->pkg->name);
+                               deps[i].possibilities[j]->pkg->state_flag |= state_flags;
+                       }
+               }
+}
+
+abstract_pkg_t **init_providelist(pkg_t *pkg, int *count)
+{
+       abstract_pkg_t *ab_pkg;
+       abstract_pkg_t **provides = pkg_get_ptr(pkg, PKG_PROVIDES);
+
+       if (!provides) {
+               provides = calloc(2, sizeof(abstract_pkg_t *));
+
+               if (!provides) {
+                       if (count)
+                               *count = 0;
+
+                       return NULL;
+               }
+
+               ab_pkg = ensure_abstract_pkg_by_name(pkg->name);
+
+               if (!ab_pkg->pkgs)
+                       ab_pkg->pkgs = pkg_vec_alloc();
+
+               if (!abstract_pkg_vec_contains(ab_pkg->provided_by, ab_pkg))
+                       abstract_pkg_vec_insert(ab_pkg->provided_by, ab_pkg);
+
+               provides[0] = ab_pkg;
+               provides[1] = NULL;
+
+               if (count)
+                       *count = 2;
+
+               pkg_set_ptr(pkg, PKG_PROVIDES, provides);
+       }
+       else if (count) {
+               for (*count = 1; *provides; provides++) {
+                       if (pkg->state_flag & SF_NEED_DETAIL) {
+                               if (!((*provides)->state_flag & SF_NEED_DETAIL)) {
+                                       opkg_msg(DEBUG, "propagating pkg flag to provided abpkg %s\n",
+                                                (*provides)->name);
+                                       (*provides)->state_flag |= SF_NEED_DETAIL;
+                               }
+                       }
+                       (*count)++;
+               }
+       }
+
+       flag_related_packages(pkg, SF_NEED_DETAIL);
+
+       return provides;
+}
+
+void parse_providelist(pkg_t *pkg, char *list)
+{
+       int count = 0;
+       char *item, *tok;
+       abstract_pkg_t *ab_pkg, *provided_abpkg, **tmp, **provides;
+
+       provides = init_providelist(pkg, &count);
+       ab_pkg = ensure_abstract_pkg_by_name(pkg->name);
+
+       if (!provides || !ab_pkg)
+               return;
+
+       for (item = strtok_r(list, ", ", &tok); item;
+            count++, item = strtok_r(NULL, ", ", &tok)) {
+               tmp = realloc(provides, sizeof(abstract_pkg_t *) * (count + 1));
+
+               if (!tmp)
+                       break;
+
+               provided_abpkg = ensure_abstract_pkg_by_name(item);
+
+               if (provided_abpkg->state_flag & SF_NEED_DETAIL) {
+                       if (!(ab_pkg->state_flag & SF_NEED_DETAIL)) {
+                               opkg_msg(DEBUG, "propagating provided abpkg flag to "
+                                               "provider abpkg %s\n", ab_pkg->name);
+                               ab_pkg->state_flag |= SF_NEED_DETAIL;
+                       }
+               }
+
+               if (!abstract_pkg_vec_contains(provided_abpkg->provided_by, ab_pkg))
+                       abstract_pkg_vec_insert(provided_abpkg->provided_by, ab_pkg);
+
+               provides = tmp;
+               provides[count - 1] = provided_abpkg;
+       }
+
+       provides[count - 1] = NULL;
+
+       pkg_set_ptr(pkg, PKG_PROVIDES, provides);
+}
+
+void parse_replacelist(pkg_t *pkg, char *list)
+{
+       int count;
+       char *item, *tok;
+       abstract_pkg_t *ab_pkg, *old_abpkg, **tmp, **replaces = NULL;
+
+       ab_pkg = ensure_abstract_pkg_by_name(pkg->name);
+
+       if (!ab_pkg->pkgs)
+               ab_pkg->pkgs = pkg_vec_alloc();
+
+       abstract_pkg_vec_insert(ab_pkg->provided_by, ab_pkg);
+
+       for (count = 1, item = strtok_r(list, ", ", &tok); item;
+            count++, item = strtok_r(NULL, ", ", &tok)) {
+               tmp = realloc(replaces, sizeof(abstract_pkg_t *) * (count + 1));
+
+               if (!tmp)
+                       break;
+
+               old_abpkg = ensure_abstract_pkg_by_name(item);
+
+               if (pkg->state_flag & SF_NEED_DETAIL) {
+                       if (!(old_abpkg->state_flag & SF_NEED_DETAIL)) {
+                               opkg_msg(DEBUG, "propagating pkg flag to replaced abpkg %s\n",
+                                        old_abpkg->name);
+                               old_abpkg->state_flag |= SF_NEED_DETAIL;
+                       }
+               }
+
+               if (!old_abpkg->replaced_by)
+                       old_abpkg->replaced_by = abstract_pkg_vec_alloc();
+
+               /* if a package pkg both replaces and conflicts old_abpkg,
+                * then add it to the replaced_by vector so that old_abpkg
+                * will be upgraded to ab_pkg automatically */
+               if (pkg_conflicts_abstract(pkg, old_abpkg)) {
+                       if (!abstract_pkg_vec_contains(old_abpkg->replaced_by, ab_pkg))
+                               abstract_pkg_vec_insert(old_abpkg->replaced_by, ab_pkg);
+               }
+
+               replaces = tmp;
+               replaces[count - 1] = old_abpkg;
+       }
+
+       if (!replaces)
+               return;
+
+       replaces[count - 1] = NULL;
+
+       pkg_set_ptr(pkg, PKG_REPLACES, replaces);
+}
+
 void buildProvides(abstract_pkg_t * ab_pkg, pkg_t * pkg)
 {
+#if 0
        int i;
 
        /* every pkg provides itself */
@@ -652,7 +716,6 @@ void buildProvides(abstract_pkg_t * ab_pkg, pkg_t * pkg)
        abstract_pkg_vec_insert(ab_pkg->provided_by, ab_pkg);
        pkg->provides = xcalloc(pkg->provides_count, sizeof(abstract_pkg_t *));
        pkg->provides[0] = ab_pkg;
-
        for (i = 1; i < pkg->provides_count; i++) {
                abstract_pkg_t *provided_abpkg =
                    ensure_abstract_pkg_by_name(pkg->provides_str[i - 1]);
@@ -664,12 +727,14 @@ void buildProvides(abstract_pkg_t * ab_pkg, pkg_t * pkg)
        }
        if (pkg->provides_str)
                free(pkg->provides_str);
+#endif
 }
 
 void buildConflicts(pkg_t * pkg)
 {
+       /*
        int i;
-       compound_depend_t *conflicts;
+       compound_depend_t *conflicts, *conflict;
 
        if (!pkg->conflicts_count)
                return;
@@ -684,10 +749,12 @@ void buildConflicts(pkg_t * pkg)
        }
        if (pkg->conflicts_str)
                free(pkg->conflicts_str);
+               */
 }
 
 void buildReplaces(abstract_pkg_t * ab_pkg, pkg_t * pkg)
 {
+#if 0
        int i;
 
        if (!pkg->replaces_count)
@@ -713,10 +780,60 @@ void buildReplaces(abstract_pkg_t * ab_pkg, pkg_t * pkg)
 
        if (pkg->replaces_str)
                free(pkg->replaces_str);
+#endif
+}
+
+void parse_deplist(pkg_t *pkg, enum depend_type type, char *list)
+{
+       int id, count;
+       char *item, *tok;
+       compound_depend_t *tmp, *deps;
+
+       switch (type)
+       {
+       case DEPEND:
+       case PREDEPEND:
+       case RECOMMEND:
+       case SUGGEST:
+       case GREEDY_DEPEND:
+               id = PKG_DEPENDS;
+               break;
+
+       case CONFLICTS:
+               id = PKG_CONFLICTS;
+               break;
+
+       default:
+               return;
+       }
+
+       deps = pkg_get_ptr(pkg, id);
+
+       for (tmp = deps, count = 1; tmp && tmp->type; tmp++)
+               count++;
+
+       for (item = strtok_r(list, ",", &tok); item; item = strtok_r(NULL, ",", &tok), count++) {
+               tmp = realloc(deps, sizeof(compound_depend_t) * (count + 1));
+
+               if (!tmp)
+                       break;
+
+               deps = tmp;
+
+               memset(deps + count - 1, 0, sizeof(compound_depend_t));
+               parseDepends(deps + count - 1, item, type);
+       }
+
+       if (!deps)
+               return;
+
+       memset(deps + count - 1, 0, sizeof(compound_depend_t));
+       pkg_set_ptr(pkg, id, deps);
 }
 
 void buildDepends(pkg_t * pkg)
 {
+#if 0
        unsigned int count;
        int i;
        compound_depend_t *depends;
@@ -763,6 +880,8 @@ void buildDepends(pkg_t * pkg)
        }
        if (pkg->suggests_str)
                free(pkg->suggests_str);
+
+#endif
 }
 
 const char *constraint_to_str(enum version_constraint c)
@@ -794,11 +913,19 @@ char *pkg_depend_str(pkg_t * pkg, int idx)
        int i;
        unsigned int len;
        char *str;
-       compound_depend_t *cdep;
+       compound_depend_t *cdep = NULL, *p;
        depend_t *dep;
 
+       for (i = 0, p = pkg_get_ptr(pkg, PKG_DEPENDS); p && p->type; i++, p++)
+               if (i == idx) {
+                       cdep = p;
+                       break;
+               }
+
+       if (!cdep)
+               return NULL;
+
        len = 0;
-       cdep = &pkg->depends[idx];
 
        /* calculate string length */
        for (i = 0; i < cdep->possibility_count; i++) {
@@ -842,16 +969,12 @@ char *pkg_depend_str(pkg_t * pkg, int idx)
 void buildDependedUponBy(pkg_t * pkg, abstract_pkg_t * ab_pkg)
 {
        compound_depend_t *depends;
-       int count, othercount;
-       int i, j;
+       int othercount;
+       int j;
        abstract_pkg_t *ab_depend;
        abstract_pkg_t **temp;
 
-       count = pkg->pre_depends_count +
-           pkg->depends_count + pkg->recommends_count + pkg->suggests_count;
-
-       for (i = 0; i < count; i++) {
-               depends = &pkg->depends[i];
+       for (depends = pkg_get_ptr(pkg, PKG_DEPENDS); depends && depends->type; depends++) {
                if (depends->type != PREDEPEND
                    && depends->type != DEPEND && depends->type != RECOMMEND)
                        continue;
@@ -892,99 +1015,79 @@ static depend_t *depend_init(void)
        return d;
 }
 
-static int parseDepends(compound_depend_t * compound_depend, char *depend_str)
+static int parseDepends(compound_depend_t * compound_depend, char *depend_str, enum depend_type type)
 {
-       char *pkg_name, buffer[2048];
-       unsigned int num_of_ors = 0;
        int i;
-       char *src, *dest;
-       depend_t **possibilities;
+       char *depend, *name, *vstr, *rest, *tok = NULL;
+       depend_t **possibilities = NULL, **tmp;
 
-       /* first count the number of ored possibilities for satisfying dependency */
-       src = depend_str;
-       while (*src)
-               if (*src++ == '|')
-                       num_of_ors++;
+       compound_depend->type = type;
 
-       compound_depend->type = DEPEND;
+       for (i = 0, depend = strtok_r(depend_str, "|", &tok); depend; i++, depend = strtok_r(NULL, "|", &tok)) {
+               name = strtok(depend, " ");
+               rest = strtok(NULL, "\n");
 
-       compound_depend->possibility_count = num_of_ors + 1;
-       possibilities = xcalloc((num_of_ors + 1), sizeof(depend_t *));
-       compound_depend->possibilities = possibilities;
+               tmp = realloc(possibilities, sizeof(tmp) * (i + 1));
 
-       src = depend_str;
-       for (i = 0; i < num_of_ors + 1; i++) {
+               if (!tmp)
+                       return -1;
+
+               possibilities = tmp;
                possibilities[i] = depend_init();
-               /* gobble up just the name first */
-               dest = buffer;
-               while (*src &&
-                      !isspace(*src) &&
-                      (*src != '(') && (*src != '*') && (*src != '|'))
-                       *dest++ = *src++;
-               *dest = '\0';
-               pkg_name = trim_xstrdup(buffer);
-
-               /* now look at possible version info */
-
-               /* skip to next chars */
-               if (isspace(*src))
-                       while (*src && isspace(*src))
-                               src++;
-
-               /* extract constraint and version */
-               if (*src == '(') {
-                       src++;
-                       if (!strncmp(src, "<<", 2)) {
+               possibilities[i]->pkg = ensure_abstract_pkg_by_name(name);
+
+               if (rest && *rest == '(') {
+                       vstr = strtok(rest + 1, ")");
+
+                       if (!strncmp(vstr, "<<", 2)) {
                                possibilities[i]->constraint = EARLIER;
-                               src += 2;
-                       } else if (!strncmp(src, "<=", 2)) {
+                               vstr += 2;
+                       } else if (!strncmp(vstr, "<=", 2)) {
                                possibilities[i]->constraint = EARLIER_EQUAL;
-                               src += 2;
-                       } else if (!strncmp(src, ">=", 2)) {
+                               vstr += 2;
+                       } else if (!strncmp(vstr, ">=", 2)) {
                                possibilities[i]->constraint = LATER_EQUAL;
-                               src += 2;
-                       } else if (!strncmp(src, ">>", 2)) {
+                               vstr += 2;
+                       } else if (!strncmp(vstr, ">>", 2)) {
                                possibilities[i]->constraint = LATER;
-                               src += 2;
-                       } else if (!strncmp(src, "=", 1)) {
+                               vstr += 2;
+                       } else if (!strncmp(vstr, "=", 1)) {
                                possibilities[i]->constraint = EQUAL;
-                               src++;
+                               vstr++;
                        }
                        /* should these be here to support deprecated designations; dpkg does */
-                       else if (!strncmp(src, "<", 1)) {
+                       else if (!strncmp(vstr, "<", 1)) {
                                possibilities[i]->constraint = EARLIER_EQUAL;
-                               src++;
-                       } else if (!strncmp(src, ">", 1)) {
+                               vstr++;
+                       } else if (!strncmp(vstr, ">", 1)) {
                                possibilities[i]->constraint = LATER_EQUAL;
-                               src++;
+                               vstr++;
                        }
 
-                       /* now we have any constraint, pass space to version string */
-                       while (isspace(*src))
-                               src++;
-
-                       /* this would be the version string */
-                       dest = buffer;
-                       while (*src && *src != ')')
-                               *dest++ = *src++;
-                       *dest = '\0';
-
-                       possibilities[i]->version = trim_xstrdup(buffer);
+                       possibilities[i]->version = trim_xstrdup(vstr);
+                       rest = strtok(NULL, " ");
+               }
+               else {
+                       rest = strtok(rest, " ");
                }
-               /* hook up the dependency to its abstract pkg */
-               possibilities[i]->pkg = ensure_abstract_pkg_by_name(pkg_name);
-
-               free(pkg_name);
 
-               /* now get past the ) and any possible | chars */
-               while (*src &&
-                      (isspace(*src) || (*src == ')') || (*src == '|')))
-                       src++;
-               if (*src == '*') {
+               if (rest && *rest == '*')
                        compound_depend->type = GREEDY_DEPEND;
-                       src++;
-               }
        }
 
+       compound_depend->possibility_count = i;
+       compound_depend->possibilities = possibilities;
+
        return 0;
 }
+
+compound_depend_t *pkg_get_depends(pkg_t *pkg, enum depend_type type)
+{
+       compound_depend_t *dep;
+
+       for (dep = pkg_get_ptr(pkg, PKG_DEPENDS); dep && dep->type; dep++)
+               if (type == UNSPEC || dep->type == type)
+                       return dep;
+
+       return NULL;
+}