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

Reply via email to