libopkg: avoid aggregating multiple identical providers
[oweals/opkg-lede.git] / libopkg / pkg_depends.c
index a12b313127fb84dc801cfd8098cf3c5d40505373..38ac1b6cbc14fe9160105f14cb8b24dbc00a730b 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);
@@ -639,6 +639,30 @@ 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;
@@ -659,7 +683,8 @@ abstract_pkg_t **init_providelist(pkg_t *pkg, int *count)
                if (!ab_pkg->pkgs)
                        ab_pkg->pkgs = pkg_vec_alloc();
 
-               abstract_pkg_vec_insert(ab_pkg->provided_by, ab_pkg);
+               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;
@@ -670,10 +695,20 @@ abstract_pkg_t **init_providelist(pkg_t *pkg, int *count)
                pkg_set_ptr(pkg, PKG_PROVIDES, provides);
        }
        else if (count) {
-               for (*count = 1; *provides; provides++)
+               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;
 }
 
@@ -698,7 +733,8 @@ void parse_providelist(pkg_t *pkg, char *list)
 
                provided_abpkg = ensure_abstract_pkg_by_name(item);
 
-               abstract_pkg_vec_insert(provided_abpkg->provided_by, ab_pkg);
+               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;
@@ -732,6 +768,14 @@ void parse_replacelist(pkg_t *pkg, char *list)
 
                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();
 
@@ -868,9 +912,7 @@ void parse_deplist(pkg_t *pkg, enum depend_type type, char *list)
                deps = tmp;
 
                memset(deps + count - 1, 0, sizeof(compound_depend_t));
-               parseDepends(deps + count - 1, item);
-
-               deps[count - 1].type = type;
+               parseDepends(deps + count - 1, item, type);
        }
 
        if (!deps)
@@ -1064,13 +1106,13 @@ 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)
 {
        int i;
        char *depend, *name, *vstr, *rest, *tok = NULL;
        depend_t **possibilities = NULL, **tmp;
 
-       compound_depend->type = DEPEND;
+       compound_depend->type = type;
 
        for (i = 0, depend = strtok_r(depend_str, "|", &tok); depend; i++, depend = strtok_r(NULL, "|", &tok)) {
                name = strtok(depend, " ");