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