In 2009 it seems I attached the wrong file to my email. Here is the right file.
diff -r --exclude=Makefile --exclude=available --exclude=status --exclude='*~' --exclude='config.*' --exclude='*.in' -u orig/dpkg-1.14.25/src/depcon.c edit/dpkg-1.14.25/src/depcon.c --- orig/dpkg-1.14.25/src/depcon.c 2009-02-01 06:19:02.000000000 +0000 +++ edit/dpkg-1.14.25/src/depcon.c 2009-07-30 15:44:22.000000000 +0100 @@ -270,13 +270,16 @@ case itb_deconfigure: sprintf(linebuf,_(" %.250s is to be deconfigured.\n"),possi->ed->name); break; - case itb_installnew: + case itb_preinstall: + if (dep->type == dep_predepends) goto like_itb_normal; + case itb_installnew: /* fall through */ if (versionsatisfied(&possi->ed->available,possi)) return 1; sprintf(linebuf,_(" %.250s is to be installed, but is version %.250s.\n"), possi->ed->name, versiondescribe(&possi->ed->available.version,vdew_nonambig)); break; - case itb_normal: case itb_preinstall: + case itb_normal: + like_itb_normal: switch (possi->ed->status) { case stat_installed: case stat_triggerspending: @@ -345,7 +348,9 @@ if (provider->up->type != dep_provides) continue; switch (provider->up->up->clientdata->istobe) { - case itb_installnew: + case itb_preinstall: + if (dep->type == dep_predepends) goto like_itb_normal_provider; + case itb_installnew: /* fall through */ /* Don't pay any attention to the Provides field of the * currently-installed version of the package we're trying * to install. We dealt with that by using the available @@ -360,7 +365,8 @@ sprintf(linebuf, _(" %.250s provides %.250s but is to be deconfigured.\n"), provider->up->up->name, possi->ed->name); break; - case itb_normal: case itb_preinstall: + case itb_normal: + like_itb_normal_provider: if (provider->up->up->status == stat_installed) return 1; sprintf(linebuf, _(" %.250s provides %.250s but is %s.\n"), provider->up->up->name, possi->ed->name, Binary files orig/dpkg-1.14.25/src/depcon.o and edit/dpkg-1.14.25/src/depcon.o differ Binary files orig/dpkg-1.14.25/src/dpkg and edit/dpkg-1.14.25/src/dpkg differ diff -r --exclude=Makefile --exclude=available --exclude=status --exclude='*~' --exclude='config.*' --exclude='*.in' -u orig/dpkg-1.14.25/src/enquiry.c edit/dpkg-1.14.25/src/enquiry.c --- orig/dpkg-1.14.25/src/enquiry.c 2009-02-01 06:19:02.000000000 +0000 +++ edit/dpkg-1.14.25/src/enquiry.c 2009-07-30 15:44:41.000000000 +0100 @@ -301,28 +301,67 @@ assertversion(argv,&epochversion,"1.4.1.19"); } +static void predepfail(struct varbuf *vb, struct pkginfo *startpkg, + struct dependency *dep, const char *problem) + NONRETURNING; +static void predepfail(struct varbuf *vb, struct pkginfo *startpkg, + struct dependency *dep, const char *problem) { + varbufreset(vb); + describedepcon(vb,dep); + varbufaddc(vb,0); + fprintf(stderr, _("dpkg: problem with pre-dependency: %s\n %s\n"), + problem, vb->buf); + ohshit(_("cannot satisfy pre-dependencies for %.250s" + " (wanted due to %.250s)"), + dep->up->name, startpkg->name); +} + +int predepsearch_recurse(FILE *output, struct varbuf *vb, + struct pkginfo *startpkg, + struct dependency *dep, int depth); + void predeppackage(const char *const *argv) { - /* Print a single package which: - * (a) is the target of one or more relevant predependencies. - * (b) has itself no unsatisfied pre-dependencies. - * If such a package is present output is the Packages file entry, - * which can be massaged as appropriate. + /* + * Prints one or more packages whose installation will make progress + * towards the satisfaction of relevant predependencies. If several + * packages are printed, at least some of them are involved in a + * dependency cycle. + * + * If such package(s) exist, our output is their Packages file entries, + * which can be massaged as appropriate. + * * Exit status: - * 0 = a package printed, OK - * 1 = no suitable package available - * 2 = error + * 0 = at least one package printed, OK + * 1 = nothing needs to be done + * 2 = error (may occur after some output has alread been produced) + * + * Specifically: + * 1. Find a package which is to be installed but which + * has an unsatisfied predependency. + * Then recursively: + * 2. Try to satisfy that predependency, by + * (a) finding a package which is to be installed and + * will satisfy it; + * (b) checking whether that package's dependencies (pre- + * or normal) are satisfied, and if so printing this + * package; otherwise + * (c) recursively trying to satisfy the unsatisfied dependency + * checking for cycles. */ static struct varbuf vb; struct pkgiterator *it; - struct pkginfo *pkg = NULL, *startpkg, *trypkg; + struct pkginfo *pkg = NULL; struct dependency *dep; - struct deppossi *possi, *provider; + FILE *output; if (*argv) badusage(_("--predep-package does not take any argument")); modstatdb_init(admindir,msdbrw_readonly); - clear_istobes(); /* We use clientdata->istobe to detect loops */ + clear_istobes(); + + output= tmpfile(); + if (!output) ohshite(_("create tmp file for predep output")); for (it = iterpkgstart(), dep = NULL; !dep && (pkg=iterpkgnext(it)); @@ -341,53 +380,100 @@ } if (!dep) exit(1); /* Not found */ assert(pkg); - startpkg= pkg; + + debug(dbg_general,"found unsatisfied predependency for %s",pkg->name); + + /* For depisok, packages with itb_preinstall satisfy Depends but not + * Pre-Depends; and their dependencies must themselves be satisfied. + * That way we avoid relying on any other Pre-Depends being + * prospectively satisfied while we are still trying to satisfy the + * one at hand. */ pkg->clientdata->istobe= itb_preinstall; + predepsearch_recurse(output,&vb,pkg,dep,0); + + long upto= ftell(output); if (upto < 0) ohshite(_("ftell predep output")); + if (fseek(output,0,SEEK_SET)==-1) + ohshite(_("rewind predep output for output")); + + while (upto-- > 0) { + int c= getc(output); + if (c==EOF) { assert(ferror(output)); ohshite(_("read predep output")); } + putchar(c); + } + if (ferror(stdout) || fflush(stdout)) werr("stdout"); +} + +int predepsearch_recurse(FILE *output, struct varbuf *vb, + struct pkginfo *startpkg, + struct dependency *dep, int depth) { /* OK, we have found an unsatisfied predependency. * Now go and find the first thing we need to install, as a first step * towards satisfying it. + * + * Returns 1 to mean `we did a predependency, just return'. */ - do { - /* We search for a package which would satisfy dep, and put it in pkg */ - for (possi = dep->list, pkg = NULL; - !pkg && possi; - possi=possi->next) { - trypkg= possi->ed; - if (!trypkg->available.valid) continue; - if (trypkg->files && versionsatisfied(&trypkg->available,possi)) { - if (trypkg->clientdata->istobe == itb_normal) { pkg= trypkg; break; } - } - if (possi->verrel != dvr_none) continue; - for (provider=possi->ed->available.depended; - !pkg && provider; - provider=provider->next) { - if (provider->up->type != dep_provides) continue; - trypkg= provider->up->up; - if (!trypkg->available.valid || !trypkg->files) continue; - if (trypkg->clientdata->istobe == itb_normal) { pkg= trypkg; break; } - } - } - if (!pkg) { - varbufreset(&vb); - describedepcon(&vb,dep); - varbufaddc(&vb,0); - fprintf(stderr, _("dpkg: cannot see how to satisfy pre-dependency:\n %s\n"),vb.buf); - ohshit(_("cannot satisfy pre-dependencies for %.250s (wanted due to %.250s)"), - dep->up->name,startpkg->name); + struct deppossi *possi, *provider; + struct pkginfo *pkg, *trypkg; + + if (++depth > 20) + predepfail(vb,startpkg,dep,_("probable dependency cycle")); + + varbufreset(vb); + describedepcon(vb,dep); + varbufaddc(vb,0); + debug(dbg_depcon,"try to satisfy %s",vb->buf); + + /* We search for a package which would satisfy dep, and put it in pkg */ + for (possi = dep->list, pkg = NULL; + !pkg && possi; + possi=possi->next) { + trypkg= possi->ed; + if (!trypkg->available.valid) continue; + if (trypkg->files && versionsatisfied(&trypkg->available,possi)) { + if (trypkg->clientdata->istobe == itb_normal) { pkg= trypkg; break; } } - pkg->clientdata->istobe= itb_preinstall; - for (dep= pkg->available.depends; dep; dep= dep->next) { - if (dep->type != dep_predepends) continue; - if (depisok(dep, &vb, NULL, 1)) - continue; - break; /* This will leave dep non-NULL, and so exit the loop. */ + if (possi->verrel != dvr_none) continue; + for (provider=possi->ed->available.depended; + !pkg && provider; + provider=provider->next) { + if (provider->up->type != dep_provides) continue; + trypkg= provider->up->up; + if (!trypkg->available.valid || !trypkg->files) continue; + if (trypkg->clientdata->istobe == itb_normal) { pkg= trypkg; break; } } - } while (dep); + } + if (!pkg) + predepfail(vb,startpkg,dep,_("no suitable package")); - /* OK, we've found it - pkg has no unsatisfied pre-dependencies ! */ - writerecord(stdout,"<stdout>",pkg,&pkg->available); - if (fflush(stdout)) werr("stdout"); + debug(dbg_depcon,"satisfy with %s",pkg->name); + + /* So we hope to install pkg. But are its dependencies satisfied? */ + pkg->clientdata->istobe= itb_preinstall; + + for (dep= pkg->available.depends; dep; dep= dep->next) { + if (!(dep->type == dep_predepends || dep->type == dep_depends)) continue; + if (depisok(dep, vb, NULL, 1)) + continue; + + if (dep->type == dep_predepends) { + debug(dbg_depcon,"pre-dependency, restarting"); + if (fseek(output,0,SEEK_SET)==-1) + ohshite(_("failed to rewind predep output")); + clear_istobes(); + pkg->clientdata->istobe= itb_installnew; + } + int r= predepsearch_recurse(output,vb,startpkg,dep,depth); + if (r || dep->type == dep_predepends) + return 1; + } + + /* OK, we've succeeded and our plan involves this package */ + writerecord(output,"predep output temporary file",pkg,&pkg->available); + putc('\n',output); + if (ferror(output)) werr("predep temporary file"); + + return 0; } void printarch(const char *const *argv) { Binary files orig/dpkg-1.14.25/src/enquiry.o and edit/dpkg-1.14.25/src/enquiry.o differ Only in edit/dpkg-1.14.25/src: x.gdb Only in edit/dpkg-1.14.25: t