FWIW, I just rebased Ian's patch and fixed the small conflict. It only
needs some further tweaking for the 0 => NULL changes in theory.

(But I did no tests by myself)

Cheers,
-- 
Raphaël Hertzog

Le best-seller français mis à jour pour Debian Etch :
http://www.ouaza.com/livre/admin-debian/
>From 01738a918c6ec921e93df16bddf86ef389008641 Mon Sep 17 00:00:00 2001
From: Ian Jackson <[EMAIL PROTECTED]>
Date: Tue, 30 Oct 2007 19:50:06 +0000
Subject: [PATCH] Check dependencies _on_ the package we're to upgrade.  Closes: #20471.

This ensures that the new package will (when it is configured)
satisfy the current setup.  We don't mind already-broken dependencies.

Some additional useful comments about dependencies in processarc.c.
---
 src/archives.c   |   49 +++++++++++++++++++++++++++++++++++++++++++++++
 src/archives.h   |    2 +
 src/depcon.c     |   17 +++++++++++----
 src/processarc.c |   56 +++++++++++++++++++++++++++++++++++++++++++++++------
 4 files changed, 112 insertions(+), 12 deletions(-)

diff --git a/src/archives.c b/src/archives.c
index 60ee2d5..c96cbc2 100644
--- a/src/archives.c
+++ b/src/archives.c
@@ -1059,6 +1059,55 @@ void check_conflict(struct dependency *dep, struct pkginfo *pkg,
   return;
 }
 
+static void cu_rdepends_istobe(int argc, void **argv) {
+  struct pkginfo *pkg= argv[0];
+  assert(pkg->clientdata->istobe == itb_normal);
+  pkg->clientdata->istobe= itb_installnew;
+}
+
+void check_rdepends(struct dependency *dep, struct pkginfo *pkg,
+                    const char *pfilename) {
+  static struct varbuf whynot;
+  int originally, afterwards;
+
+  /* Was this dependency previously satisfied ?  If not we don't worry
+   * if it's not going to be satisfied, either.  But we count it as
+   * having been previously satisfied even if it technically isn't
+   * because a satisfying package is only unpacked.  That avoids
+   * accidentally permanently breaking the dependency just because the
+   * satisfying package happens not to be configured for some reason
+   * (eg because you have just unpacked the good version but haven't
+   * yet configured it).
+   */
+  assert(pkg->clientdata->istobe == itb_installnew);
+  pkg->clientdata->istobe= itb_normal;
+  push_cleanup(cu_rdepends_istobe,~0, 0,0, 1,(void*)pkg);
+  originally= depisok(dep,&whynot,0,1);
+  pop_cleanup(ehflag_normaltidy);
+
+  if (!originally) {
+    varbufaddc(&whynot,0);
+    debug(dbg_depcon, "disregarding rdepends; dependency already"
+	  " broken:\n %s", whynot.buf);
+    return;
+  }
+
+  afterwards= depisok(dep,&whynot,0,1);
+  if (afterwards)
+    return;
+
+  varbufaddc(&whynot,0);
+  fprintf(stderr, _("dpkg: %s containing %s breaks existing dependency:\n%s"),
+	  pfilename, pkg->name, whynot.buf);
+  if (!(fc_depends ||
+	ignore_depends(dep->up) ||
+	ignore_depends(pkg))) {
+    ohshit(_("existing dependency problem - not installing %.250s"),pkg->name);
+    fprintf(stderr, _("dpkg: warning - ignoring"
+		      " existing dependency problem!\n"));
+  }
+}
+
 void cu_cidir(int argc, void **argv) {
   char *cidir= (char*)argv[0];
   char *cidirrest= (char*)argv[1];
diff --git a/src/archives.h b/src/archives.h
index 5696c19..2824f2e 100644
--- a/src/archives.h
+++ b/src/archives.h
@@ -67,6 +67,8 @@ void check_conflict(struct dependency *dep, struct pkginfo *pkg,
                     const char *pfilename);
 void check_breaks(struct dependency *dep, struct pkginfo *pkg,
                   const char *pfilename);
+void check_rdepends(struct dependency *dep, struct pkginfo *pkg,
+                    const char *pfilename);
 
 struct fileinlist *addfiletolist(struct tarcontext *tc,
 				 struct filenamenode *namenode);
diff --git a/src/depcon.c b/src/depcon.c
index 30e5936..4595326 100644
--- a/src/depcon.c
+++ b/src/depcon.c
@@ -341,12 +341,19 @@ int depisok(struct dependency *dep, struct varbuf *whynot,
           
           switch (provider->up->up->clientdata->istobe) {
           case itb_installnew:
-            /* 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
-             * information above.
+            /* The Provides field of the currently-installed version
+             * of the package we're trying to install doesn't really
+             * help, but we should at least mention it.  We dealt with
+             * the possibility that the to-be-installed version would
+             * help when we checked the available information, above.
              */
-            continue; 
+            sprintf(linebuf, _("  %.250s %.250s provides %.250s"
+			       " but is to be supplanted.\n"),
+		    provider->up->up->name,
+		    versiondescribe(&provider->up->up->installed.version,
+				    vdew_nonambig),
+		    possi->ed->name);
+            break;
           case itb_remove:
             sprintf(linebuf, _("  %.250s provides %.250s but is to be removed.\n"),
                     provider->up->up->name, possi->ed->name);
diff --git a/src/processarc.c b/src/processarc.c
index 1550414..b681958 100644
--- a/src/processarc.c
+++ b/src/processarc.c
@@ -65,7 +65,7 @@ void process_archive(const char *filename) {
   
   int c1, r, admindirlen, i, infodirlen, infodirbaseused, status;
   struct pkgiterator *it;
-  struct pkginfo *pkg, *otherpkg, *divpkg;
+  struct pkginfo *pkg, *otherpkg, *divpkg, *virtpkg;
   char *cidir, *cidirrest, *p;
   char *pfilenamebuf, conffilenamebuf[MAXCONFFILENAME];
   const char *pfilename, *newinfofilename, *failed;
@@ -238,15 +238,23 @@ void process_archive(const char *filename) {
   for (dsearch= pkg->available.depends; dsearch; dsearch= dsearch->next) {
     switch (dsearch->type) {
     case dep_conflicts:
-      /* Look for things we conflict with. */
+      /* Look for things we conflict with.
+       *    NEW --Conflicts--> SOMETHING
+       *    NEW --Conflicts--> VIRTUAL <--Provides-- SOMETHING
+       */
       check_conflict(dsearch, pkg, pfilename);
       break;
     case dep_breaks:
-      /* Look for things we break. */
+      /* Look for things we break.
+       *    NEW --Breaks--> SOMETHING
+       *    NEW --Breaks--> VIRTUAL <--Provides-- SOMETHING
+       */
       check_breaks(dsearch, pkg, pfilename);
       break;
     case dep_provides:
-      /* Look for things that conflict with what we provide. */
+      /* Look for things that conflict with what we provide.
+       *    NEW --Provides--> VIRTUAL <--Conflicts-- SOMETHING
+       */
       if (dsearch->list->ed->installed.valid) {
         for (psearch= dsearch->list->ed->installed.depended;
              psearch;
@@ -264,6 +272,9 @@ void process_archive(const char *filename) {
       /* Ignore these here. */
       break;
     case dep_predepends:
+      /*    NEW --Pre-Depends--> SOMETHING
+       *    NEW --Pre-Depends--> VIRTUAL <--Provides-- SOMETHING
+       */
       if (!depisok(dsearch, &depprobwhy, NULL, 1)) {
         varbufaddc(&depprobwhy,0);
         fprintf(stderr, _("dpkg: regarding %s containing %s, pre-dependency problem:\n%s"),
@@ -274,12 +285,43 @@ void process_archive(const char *filename) {
       }
     }
   }
-  /* Look for things that conflict with us. */
+
+  /* Look for things that conflict with us, or which depend on an
+   * already-installed version of us but which aren't satisfied by
+   * the new version. */
   for (psearch= pkg->installed.depended; psearch; psearch= psearch->nextrev) {
-    if (psearch->up->type != dep_conflicts) continue;
-    check_conflict(psearch->up, pkg, pfilename);
+    switch (psearch->up->type) {
+    case dep_conflicts:
+      /*  SOMETHING --Conflicts--> US  */
+      check_conflict(psearch->up, pkg, pfilename);
+      break;
+    case dep_depends:
+    case dep_predepends:
+      /*  SOMETHING --(Pre-)Depends--> US  */
+      check_rdepends(psearch->up, pkg, pfilename);
+      break;
+    case dep_provides:
+    case dep_suggests:
+    case dep_recommends:
+    case dep_replaces:
+    case dep_breaks:
+    case dep_enhances:
+      break;
+    }
   }
   
+  for (dsearch= pkg->installed.depends; dsearch; dsearch= dsearch->next) {
+    /*  OLD --Provides--> VIRTUAL <--(Pre-)Depends-- SOMETHING  */
+    if (dsearch->type != dep_provides) continue;
+    virtpkg= dsearch->list->ed;
+    for (psearch= virtpkg->installed.depended;
+	 psearch;
+	 psearch= psearch->nextrev) {
+      if (psearch->up->up == pkg) continue; /* reflexive via Provides */
+      check_rdepends(psearch->up, pkg, pfilename);
+    }
+  }
+
   ensure_allinstfiles_available();
   filesdbinit();
   
-- 
1.5.3.8

Reply via email to