make razor_set_update not loop forever on unsatisfiable dependencies
authorDan Winship <danw@gnome.org>
Thu, 21 Feb 2008 19:58:39 +0000 (14:58 -0500)
committerDan Winship <danw@gnome.org>
Thu, 21 Feb 2008 19:58:39 +0000 (14:58 -0500)
this is mostly a dead-end, as to get the next test working i need to
rewrite the code as suggested in the comment above razor_set_revalidate

razor.c
test-driver.c

diff --git a/razor.c b/razor.c
index 598f3a7..ed9bdc3 100644 (file)
--- a/razor.c
+++ b/razor.c
@@ -1740,7 +1740,8 @@ razor_set_satisfy(struct razor_set *set, struct array *unsatisfied,
        upool = upstream->string_pool.data;
        package_pool = &upstream->package_pool;
 
-       for (u = unsatisfied->data; u < end; u++) {
+       u = unsatisfied->data;
+       while (u < end) {
                r = requires + *u;
 
                while (p < pend &&
@@ -1752,18 +1753,23 @@ razor_set_satisfy(struct razor_set *set, struct array *unsatisfied,
                while (p + 1 < pend && p->name == (p + 1)->name && p->type == (p + 1)->type)
                        p++;
 
-               if (p == pend ||
-                   strcmp(&pool[r->name], &upool[p->name]) != 0 ||
-                   versioncmp(&pool[r->version], &upool[p->version]) > 0) {
-                       /* Do we need to track unsatisfiable requires
-                        * as we go, or should we just do a
-                        * razor_set_validate() at the end? */
-               } else {
+               if (p != pend &&
+                   p->type == RAZOR_PROPERTY_PROVIDES &&
+                   strcmp(&pool[r->name], &upool[p->name]) == 0 &&
+                   versioncmp(&pool[r->version], &upool[p->version]) <= 0) {
                        pkg = array_add(list, sizeof *pkg);
                        /* We just pull in the first package that provides */
                        *pkg = list_first(&p->packages, package_pool)->data;
+
+                       /* Remove this from the unsatisfied list */
+                       memmove (u, u + 1, end - (u + 1));
+                       end--;
+               } else {
+                       /* Leave this in the unsatisfied list */
+                       u++;
                }
-       }       
+       }
+       unsatisfied->size = (void *)end - unsatisfied->data;
 }
 
 static void
@@ -1816,12 +1822,50 @@ find_all_packages(struct razor_set *set,
        }
 }
 
+/* FIXME: this is all wrong anyway; we should recompute the new_unsatisfied
+ * set as we add and remove packages...
+ */
+static void
+razor_set_revalidate(struct razor_set *orig_set,
+                    struct array *orig_unsatisfied,
+                    struct razor_set *new_set,
+                    struct array *new_unsatisfied)
+{
+       uint32_t *nu, *nuend, *ou, *ouend;
+       struct razor_property *new_props, *orig_props;
+       char *new_pool, *orig_pool;
+
+       razor_set_validate(new_set, new_unsatisfied);
+
+       ouend = orig_unsatisfied->data + orig_unsatisfied->size;
+       nuend = new_unsatisfied->data + new_unsatisfied->size;
+       new_props = new_set->properties.data;
+       orig_props = orig_set->properties.data;
+       new_pool = new_set->string_pool.data;
+       orig_pool = orig_set->string_pool.data;
+
+       for (nu = new_unsatisfied->data; nu < nuend; nu++) {
+               for (ou = orig_unsatisfied->data; ou < ouend; ou++) {
+                       if (!strcmp (&new_pool[new_props[*nu].name],
+                                    &orig_pool[orig_props[*ou].name]) &&
+                           new_props[*nu].relation == orig_props[*ou].relation &&
+                           !strcmp (&new_pool[new_props[*nu].version],
+                                    &orig_pool[orig_props[*ou].version])) {
+                               *(nu--) = *(--nuend);
+                               break;
+                       }
+               }
+       }
+
+       new_unsatisfied->size = (void *)nuend - new_unsatisfied->data;
+}
+
 struct razor_set *
 razor_set_update(struct razor_set *set, struct razor_set *upstream,
                 int count, const char **packages)
 {
        struct razor_set *new;
-       struct array list, unsatisfied;
+       struct array list, unsatisfied_before, unsatisfied;
 
        array_init(&list);
        if (count > 0)
@@ -1829,20 +1873,35 @@ razor_set_update(struct razor_set *set, struct razor_set *upstream,
        else
                find_all_packages(set, upstream, &list);
 
+       array_init(&unsatisfied_before);
+       razor_set_validate(set, &unsatisfied_before);
+
        while (list.size > 0) {
                new = razor_set_add(set, upstream, &list);
                array_release(&list);
-               razor_set_destroy(set);
-               set = new;
 
                array_init(&unsatisfied);
-               razor_set_validate(new, &unsatisfied);
+               razor_set_revalidate(set, &unsatisfied_before,
+                                    new, &unsatisfied);
+
                array_init(&list);
                razor_set_satisfy(new, &unsatisfied, upstream, &list);
-               array_release(&unsatisfied);
+
+               if (unsatisfied.size) {
+                       /* FIXME: need to return this list */
+                       array_release(&unsatisfied);
+                       razor_set_destroy(new);
+                       razor_set_destroy(set);
+                       set = NULL;
+                       break;
+               }
+
+               razor_set_destroy(set);
+               set = new;
        }
 
        array_release(&list);
+       array_release(&unsatisfied_before);
 
        return set;
 }
@@ -1856,9 +1915,6 @@ razor_set_remove_internal(struct razor_set *set, struct array *list,
        struct razor_package *pkgs;
        int pkg_count, remove_count, p, r;
        struct array unsatisfied_before;
-       uint32_t *u, *uend, *ub, *ubend;
-       struct razor_property *props, *propsb;
-       char *pool, *poolb;
 
        array_init(&unsatisfied_before);
        razor_set_validate(set, &unsatisfied_before);
@@ -1883,29 +1939,10 @@ razor_set_remove_internal(struct razor_set *set, struct array *list,
 
        new = razor_merger_finish(merger);
 
-       razor_set_validate(new, unsatisfied);
-
-       ubend = unsatisfied_before.data + unsatisfied_before.size;
-       uend = unsatisfied->data + unsatisfied->size;
-       props = new->properties.data;
-       propsb = set->properties.data;
-       pool = new->string_pool.data;
-       poolb = set->string_pool.data;
-
-       for (u = unsatisfied->data; u < uend; u++) {
-               for (ub = unsatisfied_before.data; ub < ubend; ub++) {
-                       if (!strcmp (&pool[props[*u].name],
-                                    &poolb[propsb[*ub].name]) &&
-                           props[*u].relation == propsb[*ub].relation &&
-                           !strcmp (&pool[props[*u].version],
-                                    &poolb[propsb[*ub].version])) {
-                               *(u--) = *(--uend);
-                               break;
-                       }
-               }
-       }
+       razor_set_revalidate(set, &unsatisfied_before,
+                            new, unsatisfied);
+       array_release(&unsatisfied_before);
 
-       unsatisfied->size = (void *)uend - unsatisfied->data;
        return new;
 }
 
index 64f3504..03ca7ec 100644 (file)
@@ -60,6 +60,7 @@ struct test_context {
        int n_install_pkgs, n_remove_pkgs;
 
        int in_result, result_errors;
+       int in_unsatisfiable;
 };
 
 static void
@@ -181,6 +182,9 @@ start_property(struct test_context *ctx, enum razor_property_type type, const ch
        const char *name = NULL, *rel_str = NULL, *version = NULL;
        enum razor_version_relation rel;
 
+       if (ctx->in_unsatisfiable)
+               return;
+
        get_atts(atts, "name", &name, "rel", &rel_str, "version", &version, NULL);
        if (name == NULL) {
                fprintf(stderr, "  no name specified for property\n");
@@ -209,13 +213,17 @@ start_transaction(struct test_context *ctx, const char **atts)
 static void
 end_transaction(struct test_context *ctx)
 {
-       ctx->system_set = razor_set_update(ctx->system_set,
-                                          ctx->repo_set,
-                                          ctx->n_install_pkgs,
-                                          (const char **)ctx->install_pkgs);
-       ctx->system_set = razor_set_remove(ctx->system_set,
-                                          ctx->n_remove_pkgs,
-                                          (const char **)ctx->remove_pkgs);
+       if (ctx->n_install_pkgs) {
+               ctx->system_set = razor_set_update(ctx->system_set,
+                                                  ctx->repo_set,
+                                                  ctx->n_install_pkgs,
+                                                  (const char **)ctx->install_pkgs);
+       }
+       if (ctx->n_remove_pkgs && ctx->system_set) {
+               ctx->system_set = razor_set_remove(ctx->system_set,
+                                                  ctx->n_remove_pkgs,
+                                                  (const char **)ctx->remove_pkgs);
+       }
 
        while (ctx->n_install_pkgs--)
                free(ctx->install_pkgs[ctx->n_install_pkgs]);
@@ -279,27 +287,34 @@ end_result(struct test_context *ctx)
 {
        ctx->in_result = 0;
 
-       if (ctx->system_set && ctx->result_set) {
+       if (ctx->result_set) {
+               if (!ctx->system_set)
+                       ctx->system_set = razor_set_create();
                ctx->result_errors = 0;
                razor_set_diff(ctx->system_set, ctx->result_set,
                               diff_callback, ctx);
                if (ctx->result_errors)
                        exit(1);
        }
-
 }
 
 static void
-start_unsatisfied(struct test_context *ctx, const char **atts)
+start_unsatisfiable(struct test_context *ctx, const char **atts)
 {
+       if (ctx->system_set) {
+               fprintf(stderr, "Expected to fail, but didn't\n");
+               exit(1);
+       }
+
        /* FIXME */
-       fprintf(stderr, "Can't handle <unsatisfied>\n");
-       exit(1);
+       fprintf(stderr, "  Not actually checking <unsatisfiable>\n");
+       ctx->in_unsatisfiable = 1;
 }
 
 static void
-end_unsatisfied(struct test_context *ctx)
+end_unsatisfiable(struct test_context *ctx)
 {
+       ctx->in_unsatisfiable = 0;
 }
 
 static void
@@ -323,8 +338,8 @@ start_test_element(void *data, const char *element, const char **atts)
                start_remove(ctx, atts);
        } else if (strcmp(element, "result") == 0) {
                start_result(ctx, atts);
-       } else if (strcmp(element, "unsatisfied") == 0) {
-               start_unsatisfied(ctx, atts);
+       } else if (strcmp(element, "unsatisfiable") == 0) {
+               start_unsatisfiable(ctx, atts);
        } else if (strcmp(element, "package") == 0) {
                start_package(ctx, atts);
        } else if (strcmp(element, "requires") == 0) {
@@ -356,8 +371,8 @@ end_test_element (void *data, const char *element)
                end_transaction(ctx);
        } else if (strcmp(element, "result") == 0) {
                end_result(ctx);
-       } else if (strcmp(element, "unsatisfied") == 0) {
-               end_unsatisfied(ctx);
+       } else if (strcmp(element, "unsatisfiable") == 0) {
+               end_unsatisfiable(ctx);
        }
 }