{ 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)
}
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;
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);
* 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;
pkg->install_logdir_real = NULL;
}
- if (check_dependencies(pkg))
+ if (check_dependencies(pkg, &dependency_stack_top))
goto nuke_pkgdb;
} else {
/*
* 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))
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);