]> Zhao Yanbai Git Server - minix.git/commitdiff
Workaround for circular dependency problem in pkgadd
authorErik van der Kouwe <erik@minix3.org>
Sat, 11 Dec 2010 18:20:31 +0000 (18:20 +0000)
committerErik van der Kouwe <erik@minix3.org>
Sat, 11 Dec 2010 18:20:31 +0000 (18:20 +0000)
commands/pkg_install/add/perform.c

index c56fdfba40e1081277181d4271f697274be91aa3..3f7e857957889fc5273c3057630f782728c5113f 100644 (file)
@@ -134,7 +134,12 @@ static const struct pkg_meta_desc {
        { 0, NULL, 0, 0 },
 };
 
-static int pkg_do(const char *, int, int);
+struct dependency_stack {
+       struct dependency_stack *prev;
+       const char *pkgpath;
+};
+
+static int pkg_do(const char *, int, int, struct dependency_stack *);
 
 static int
 mkdir_p(const char *path)
@@ -1092,7 +1097,7 @@ check_implicit_conflict(struct pkg_task *pkg)
 }
 
 static int
-check_dependencies(struct pkg_task *pkg)
+check_dependencies(struct pkg_task *pkg, struct dependency_stack *dependency_stack)
 {
        plist_t *p;
        char *best_installed;
@@ -1123,7 +1128,7 @@ check_dependencies(struct pkg_task *pkg)
                                    p->name);
                                continue;
                        }
-                       if (pkg_do(p->name, 1, 0)) {
+                       if (pkg_do(p->name, 1, 0, dependency_stack)) {
                                if (ForceDepends) {
                                        warnx("Can't install dependency %s, "
                                            "continuing", p->name);
@@ -1372,12 +1377,33 @@ check_license(struct pkg_task *pkg)
  * Install a single package.
  */
 static int
-pkg_do(const char *pkgpath, int mark_automatic, int top_level)
+pkg_do(const char *pkgpath, int mark_automatic, int top_level, 
+       struct dependency_stack *dependency_stack)
 {
        char *archive_name;
        int status, invalid_sig;
        struct pkg_task *pkg;
 
+       /* workaround 2010-12-10: prevent endless recursion for circular dependencies */
+       struct dependency_stack dependency_stack_top;
+
+       dependency_stack_top.prev = dependency_stack;
+       dependency_stack_top.pkgpath = pkgpath;
+
+       while (dependency_stack) {
+               if (strcmp(dependency_stack->pkgpath, pkgpath) == 0) {
+                       fprintf(stderr, "warning: ignoring circular dependency:\n");
+                       dependency_stack = &dependency_stack_top;
+                       while (dependency_stack) {
+                               fprintf(stderr, "- %s\n", dependency_stack->pkgpath);
+                               dependency_stack = dependency_stack->prev;
+                       }
+                       return 0;
+               }
+               dependency_stack = dependency_stack->prev;
+       }
+       /* end workaround */
+       
        pkg = xcalloc(1, sizeof(*pkg));
 
        status = -1;
@@ -1489,7 +1515,7 @@ pkg_do(const char *pkgpath, int mark_automatic, int top_level)
                        pkg->install_logdir_real = NULL;
                }
 
-               if (check_dependencies(pkg))
+               if (check_dependencies(pkg, &dependency_stack_top))
                        goto nuke_pkgdb;
        } else {
                /*
@@ -1497,7 +1523,7 @@ pkg_do(const char *pkgpath, int mark_automatic, int top_level)
                 * Install/update dependencies first and
                 * write the current package to disk afterwards.
                 */ 
-               if (check_dependencies(pkg))
+               if (check_dependencies(pkg, &dependency_stack_top))
                        goto clean_memory;
 
                if (write_meta_data(pkg))
@@ -1581,7 +1607,7 @@ pkg_perform(lpkg_head_t *pkgs)
        lpkg_t *lpp;
 
        while ((lpp = TAILQ_FIRST(pkgs)) != NULL) {
-               if (pkg_do(lpp->lp_name, Automatic, 1))
+               if (pkg_do(lpp->lp_name, Automatic, 1, NULL))
                        ++errors;
                TAILQ_REMOVE(pkgs, lpp, lp_link);
                free_lpkg(lpp);