Here is the Breaks patch against the most recent dpkg.  You must apply
the formatting diffs from #375711 first.

Ian.

diff -bB --exclude='*~' --exclude='*.orig' --exclude='*.rej' -ruN 
in/debian/dpkg-1.14.4/man/deb-control.5 construct/dpkg-1.14.4/man/deb-control.5
--- in/debian/dpkg-1.14.4/man/deb-control.5     2007-05-15 03:30:10.000000000 
+0100
+++ construct/dpkg-1.14.4/man/deb-control.5     2007-05-30 16:09:39.000000000 
+0100
@@ -136,6 +136,14 @@
 "<<" for less than, ">=" for greater than or equal to, "<=" for less than
 or equal to, and "=" for equal to.
 .TP
+.BR Breaks: " <package list>"
+Lists packages that this one breaks, for example by exposing bugs
+when the named packages rely on this one. The package maintenance
+software will not allow broken packages to be configured; generally
+the resolution is to upgrade the packages named in a
+.B Breaks
+field.
+.TP
 .BR Conflicts: " <package list>"
 Lists packages that conflict with this one, for example by containing
 files with the same names. The package maintenance software will not
diff -bB --exclude='*~' --exclude='*.orig' --exclude='*.rej' -ruN 
in/debian/dpkg-1.14.4/man/dpkg-query.1 construct/dpkg-1.14.4/man/dpkg-query.1
--- in/debian/dpkg-1.14.4/man/dpkg-query.1      2007-03-06 07:27:15.000000000 
+0000
+++ construct/dpkg-1.14.4/man/dpkg-query.1      2007-05-30 16:09:39.000000000 
+0100
@@ -103,6 +103,7 @@
     \fBConffiles\fP
     \fBConfig\-Version\fP
     \fBConflicts\fP
+    \fBBreaks\fP
     \fBDepends\fP
     \fBDescription\fP
     \fBEnhances\fP
diff -bB --exclude='*~' --exclude='*.orig' --exclude='*.rej' -ruN 
in/debian/dpkg-1.14.4/man/dpkg.1 construct/dpkg-1.14.4/man/dpkg.1
--- in/debian/dpkg-1.14.4/man/dpkg.1    2007-03-06 07:22:40.000000000 +0000
+++ construct/dpkg-1.14.4/man/dpkg.1    2007-05-30 16:09:39.000000000 +0100
@@ -371,6 +371,9 @@
 \fBdepends\-version\fP:
 Don't care about versions when checking dependencies.
 
+\fBbreaks\fP:
+Install, even if this would break another package.
+
 \fBconflicts\fP:
 Install, even if it conflicts with another package. This is dangerous,
 for it will usually cause overwriting of some files.
diff -bB --exclude='*~' --exclude='*.orig' --exclude='*.rej' -ruN 
in/debian/dpkg-1.14.4/scripts/controllib.pl 
construct/dpkg-1.14.4/scripts/controllib.pl
--- in/debian/dpkg-1.14.4/scripts/controllib.pl 2007-05-24 17:17:16.000000000 
+0100
+++ construct/dpkg-1.14.4/scripts/controllib.pl 2007-05-30 17:25:21.000000000 
+0100
@@ -29,7 +29,7 @@
 my $parsechangelog = 'dpkg-parsechangelog';
 
 our @pkg_dep_fields = qw(Pre-Depends Depends Recommends Suggests Enhances
-                         Conflicts Replaces Provides);
+                         Conflicts Breaks Replaces Provides);
 our @src_dep_fields = qw(Build-Depends Build-Depends-Indep
                          Build-Conflicts Build-Conflicts-Indep);
 
diff -bB --exclude='*~' --exclude='*.orig' --exclude='*.rej' -ruN 
in/debian/dpkg-1.14.4/scripts/dpkg-genchanges.pl 
construct/dpkg-1.14.4/scripts/dpkg-genchanges.pl
--- in/debian/dpkg-1.14.4/scripts/dpkg-genchanges.pl    2007-05-13 
05:06:13.000000000 +0100
+++ construct/dpkg-1.14.4/scripts/dpkg-genchanges.pl    2007-05-30 
17:28:29.000000000 +0100
@@ -255,7 +255,7 @@
                }
                push(@archvalues,$v) unless !$v || $archadded{$v}++;
            } elsif (m/^(Package|Essential|Pre-Depends|Depends|Provides)$/ ||
-                    
m/^(Recommends|Suggests|Enhances|Optional|Conflicts|Replaces)$/ ||
+                    
m/^(Recommends|Suggests|Enhances|Optional|Conflicts|Breaks|Replaces)$/ ||
                     m/^X[CS]+-/i) {
            } else {
                &unknown(_g("package's section of control info file"));
diff -bB --exclude='*~' --exclude='*.orig' --exclude='*.rej' -ruN 
in/debian/dpkg-1.14.4/scripts/dpkg-source.pl 
construct/dpkg-1.14.4/scripts/dpkg-source.pl
--- in/debian/dpkg-1.14.4/scripts/dpkg-source.pl        2007-05-23 
00:13:49.000000000 +0100
+++ construct/dpkg-1.14.4/scripts/dpkg-source.pl        2007-05-30 
17:22:15.000000000 +0100
@@ -284,7 +284,7 @@
                 $f{$_}= $v;
             } elsif (m/^(Package|Essential|Pre-Depends|Depends|Provides)$/i ||
                      m/^(Recommends|Suggests|Optional|Conflicts|Replaces)$/i ||
-                     m/^(Enhances|Description|Section|Priority)$/i ||
+                     m/^(Breaks|Enhances|Description|Section|Priority)$/i ||
                      m/^X[BC]+-/i) {
             } else {
                 &unknown(_g("package's section of control info file"));
diff -bB --exclude='*~' --exclude='*.orig' --exclude='*.rej' -ruN 
in/debian/dpkg-1.14.4/src/archives.c construct/dpkg-1.14.4/src/archives.c
--- in/debian/dpkg-1.14.4/src/archives.c        2007-03-21 21:20:28.000000000 
+0000
+++ construct/dpkg-1.14.4/src/archives.c        2007-05-30 16:09:39.000000000 
+0100
@@ -780,42 +822,124 @@
   return 0;
 }
 
-static int try_remove_can(struct deppossi *pdep,
-                          struct pkginfo *fixbyrm,
+static int try_deconfigure_can(int (*force_p)(struct deppossi*),
+                              struct pkginfo *pkg,
+                              struct deppossi *pdep,
+                              const char *action,
+                              struct pkginfo *removal,
                           const char *why) {
+  /* Also checks whether the pdep is forced, first, according to force_p.
+   * force_p may be 0 in which case nothing is considered forced.
+   *
+   * Action is a string describing the action which causes the
+   * deconfiguration:
+   *     removal of <package>         (due to Conflicts+Depends   removal!=0)
+   *     installation of <package>    (due to Breaks              removal==0)
+   *
+   * Return values:  2: forced (no deconfiguration needed, why is printed)
+   *                 1: deconfiguration queued ok (no message printed)
+   *                 0: not possible (why is printed)
+   */
   struct packageinlist *newdeconf;
   
-  if (force_depends(pdep)) {
+  if (force_p && force_p(pdep)) {
     fprintf(stderr, _("dpkg: warning - "
-            "ignoring dependency problem with removal of %s:\n%s"),
-            fixbyrm->name, why);
-    return 1;
+            "ignoring dependency problem with %s:\n%s"),
+            action, why);
+    return 2;
   } else if (f_autodeconf) {
-    if (pdep->up->up->installed.essential) {
+    if (pkg->installed.essential) {
       if (fc_removeessential) {
         fprintf(stderr, _("dpkg: warning - considering deconfiguration of 
essential\n"
-                " package %s, to enable removal of %s.\n"),
-                pdep->up->up->name,fixbyrm->name);
+                " package %s, to enable %s.\n"),
+                pkg->name, action);
       } else {
         fprintf(stderr, _("dpkg: no, %s is essential, will not deconfigure\n"
-                " it in order to enable removal of %s.\n"),
-                pdep->up->up->name,fixbyrm->name);
+                " it in order to enable %s.\n"),
+                pkg->name, action);
         return 0;
       }
     }
-    pdep->up->up->clientdata->istobe= itb_deconfigure;
+    pkg->clientdata->istobe= itb_deconfigure;
     newdeconf= malloc(sizeof(struct packageinlist));
     newdeconf->next= deconfigure;
-    newdeconf->pkg= pdep->up->up;
+    newdeconf->pkg= pkg;
+    newdeconf->xinfo= removal;
     deconfigure= newdeconf;
     return 1;
   } else {
-    fprintf(stderr, _("dpkg: no, cannot remove %s (--auto-deconfigure will 
help):\n%s"),
-            fixbyrm->name, why);
+    fprintf(stderr, _("dpkg: no, cannot proceed with %s (--auto-deconfigure 
will help):\n%s"),
+            action, why);
     return 0;
   }
 }
 
+static int try_remove_can(struct deppossi *pdep,
+                          struct pkginfo *fixbyrm,
+                          const char *why) {
+  char action[512];
+  sprintf(action,_("removal of %.250s"),fixbyrm->name);
+  return try_deconfigure_can(force_depends, pdep->up->up, pdep,
+                            action, fixbyrm, why);
+}
+
+void check_breaks(struct dependency *dep, struct pkginfo *pkg,
+                 const char *pfilename) {
+  struct pkginfo *fixbydeconf;
+  struct varbuf why;
+  int ok;
+
+  varbufinit(&why);
+
+  fixbydeconf= 0;
+  if (depisok(dep, &why, &fixbydeconf, 0)) {
+    varbuffree(&why);
+    return;
+  }
+
+  varbufaddc(&why,0);
+  
+  if (fixbydeconf && f_autodeconf) {
+    char action[512];
+
+    ensure_package_clientdata(fixbydeconf);
+    assert(fixbydeconf->clientdata->istobe == itb_normal);
+
+    sprintf(action,_("installation of %.250s"),pkg->name);
+    fprintf(stderr, _("dpkg: considering deconfiguration of %s,"
+                     " which would be broken by %s ...\n"),
+           fixbydeconf->name, action);
+
+    ok= try_deconfigure_can(force_breaks, fixbydeconf, dep->list,
+                           action, 0, why.buf);
+    if (ok==1) {
+      fprintf(stderr, _("dpkg: yes, will deconfigure %s (broken by %s).\n"),
+             fixbydeconf->name, pkg->name);
+    }
+  } else {
+    fprintf(stderr, _("dpkg: regarding %s containing %s:\n%s"),
+           pfilename, pkg->name, why.buf);
+    ok= 0;
+  }
+  varbuffree(&why);
+  if (ok>0) return;
+  
+  if (force_breaks(dep->list)) {
+    fprintf(stderr, _("dpkg: warning - ignoring breakage,"
+                     " may proceed anyway !\n"));
+    return;
+  }
+
+  if (fixbydeconf && !f_autodeconf) {
+    ohshit(_("installing %.250s would break %.250s, and\n"
+ " deconfiguration is not permitted (--auto-deconfigure might help)"),
+          pkg->name, fixbydeconf->name);
+  } else {
+    ohshit(_("installing %.250s would break existing software"),
+          pkg->name);
+  }
+}
+
 void check_conflict(struct dependency *dep, struct pkginfo *pkg,
                     const char *pfilename) {
   struct pkginfo *fixbyrm;
diff -bB --exclude='*~' --exclude='*.orig' --exclude='*.rej' -ruN 
in/debian/dpkg-1.14.4/src/archives.h construct/dpkg-1.14.4/src/archives.h
--- in/debian/dpkg-1.14.4/src/archives.h        2006-06-19 02:22:03.000000000 
+0100
+++ construct/dpkg-1.14.4/src/archives.h        2007-05-30 16:09:39.000000000 
+0100
@@ -65,6 +65,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);
 
 struct fileinlist *addfiletolist(struct tarcontext *tc,
                                 struct filenamenode *namenode);
diff -bB --exclude='*~' --exclude='*.orig' --exclude='*.rej' -ruN 
in/debian/dpkg-1.14.4/src/cleanup.c construct/dpkg-1.14.4/src/cleanup.c
--- in/debian/dpkg-1.14.4/src/cleanup.c 2006-06-19 02:22:03.000000000 +0100
+++ construct/dpkg-1.14.4/src/cleanup.c 2007-05-30 16:09:39.000000000 +0100
@@ -120,7 +120,8 @@
 
 void ok_prermdeconfigure(int argc, void **argv) {
   struct pkginfo *deconf= (struct pkginfo*)argv[0];
-  /* also has conflictor in argv[1] and infavour in argv[2] */
+  /* also has conflictor in argv[1] and infavour in argv[2].
+   * conflictor may be 0 if deconfigure was due to Breaks */
   
   if (cipaction->arg == act_install)
     add_to_queue(deconf);
@@ -128,16 +129,17 @@
 
 void cu_prermdeconfigure(int argc, void **argv) {
   struct pkginfo *deconf= (struct pkginfo*)argv[0];
-  struct pkginfo *conflictor= (struct pkginfo*)argv[1];
+  struct pkginfo *conflictor= (struct pkginfo*)argv[1]; /* may be 0 */
   struct pkginfo *infavour= (struct pkginfo*)argv[2];
 
   maintainer_script_installed(deconf,POSTINSTFILE,"post-installation",
                               "abort-deconfigure", "in-favour", infavour->name,
                               versiondescribe(&infavour->available.version,
                                               vdew_nonambig),
-                              "removing", conflictor->name,
-                              versiondescribe(&conflictor->installed.version,
-                                              vdew_nonambig),
+                              conflictor ? "removing" : (char*)0,
+                             conflictor ? conflictor->name : (char*)0,
+                              conflictor ? 
versiondescribe(&conflictor->installed.version,
+                                              vdew_nonambig) : (char*)0,
                               (char*)0);
   deconf->status= stat_installed;
   modstatdb_note(deconf);
diff -bB --exclude='*~' --exclude='*.orig' --exclude='*.rej' -ruN 
in/debian/dpkg-1.14.4/src/configure.c construct/dpkg-1.14.4/src/configure.c
--- in/debian/dpkg-1.14.4/src/configure.c       2007-03-21 21:22:08.000000000 
+0000
+++ construct/dpkg-1.14.4/src/configure.c       2007-05-30 19:18:00.000000000 
+0100
@@ -108,7 +108,9 @@
                pkg->clientdata->istobe= itb_installnew;
                add_to_queue(pkg);
                return;
-       } else if (ok == 0) {
+  }
+  ok= breakses_ok(pkg,&aemsgs) ? ok : 0;
+  if (ok == 0) {
                sincenothing= 0;
                varbufaddc(&aemsgs,0);
                fprintf(stderr,
diff -bB --exclude='*~' --exclude='*.orig' --exclude='*.rej' -ruN 
in/debian/dpkg-1.14.4/src/depcon.c construct/dpkg-1.14.4/src/depcon.c
--- in/debian/dpkg-1.14.4/src/depcon.c  2007-02-04 14:52:46.000000000 +0000
+++ construct/dpkg-1.14.4/src/depcon.c  2007-05-30 16:09:39.000000000 +0100
@@ -196,6 +196,10 @@
    * before a package is unpacked, when it is sufficient for the package
    * to be unpacked provided that both the unpacked and previously-configured
    * versions are acceptable.
+   * On 0 return (`not OK'), *canfixbyremove refers to a package which
+   * if removed (dep_conflicts) or deconfigured (dep_breaks) will fix
+   * the problem.  Caller may pass 0 for canfixbyremove and need not
+   * initialise *canfixbyremove.
    */
   struct deppossi *possi;
   struct deppossi *provider;
@@ -213,6 +217,8 @@
         dep->type == dep_recommends || dep->type == dep_suggests ||
         dep->type == dep_enhances);
   
+  if (canfixbyremove) *canfixbyremove= 0;
+
   /* The dependency is always OK if we're trying to remove the depend*ing*
    * package.
    */
@@ -380,12 +386,11 @@
       }
     }
 
-    if (canfixbyremove) *canfixbyremove= 0;
     return 0;
 
   } else {
     
-    /* It's a conflict.  There's only one main alternative,
+    /* It's conflicts or breaks.  There's only one main alternative,
      * but we also have to consider Providers.  We return `0' as soon
      * as we find something that matches the conflict, and only describe
      * it then.  If we get to the end without finding anything we return `1'.
@@ -395,9 +400,10 @@
     nconflicts= 0;
 
     if (possi->ed != possi->up->up) {
-      /* If the package conflicts with itself it must mean that it conflicts
-       * with other packages which provide the same virtual name.  We therefore
-       * don't look at the real package and go on to the virtual ones.
+      /* If the package conflicts with or breaks itself it must mean
+       * other packages which provide the same virtual name.  We
+       * therefore don't look at the real package and go on to the
+       * virtual ones.
        */
       
       switch (possi->ed->clientdata->istobe) {
@@ -413,11 +419,17 @@
         nconflicts++;
         *canfixbyremove= possi->ed;
         break;
-      case itb_normal: case itb_deconfigure: case itb_preinstall:
+      case itb_deconfigure:
+       if (dep->type == dep_breaks) break; /* already deconfiguring this */
+       /* fall through */
+      case itb_normal: case itb_preinstall:
         switch (possi->ed->status) {
         case stat_notinstalled: case stat_configfiles:
           break;
-        default:
+       case stat_halfinstalled: case stat_unpacked:
+       case stat_halfconfigured: 
+         if (dep->type == dep_breaks) break; /* no problem */
+        case stat_installed:
           if (!versionsatisfied(&possi->ed->installed, possi)) break;
           sprintf(linebuf, _("  %.250s (version %.250s) is %s.\n"),
                   possi->ed->name,
@@ -470,11 +482,16 @@
           continue; 
         case itb_remove:
           continue;
-        case itb_normal: case itb_deconfigure: case itb_preinstall:
+       case itb_deconfigure:
+         if (dep->type == dep_breaks) continue; /* already deconfiguring */
+        case itb_normal: case itb_preinstall:
           switch (provider->up->up->status) {
           case stat_notinstalled: case stat_configfiles:
             continue;
-          default:
+         case stat_halfinstalled: case stat_unpacked:
+         case stat_halfconfigured: 
+           if (dep->type == dep_breaks) break; /* no problem */
+          case stat_installed:
             sprintf(linebuf, _("  %.250s provides %.250s and is %s.\n"),
                     provider->up->up->name, possi->ed->name,
                     gettext(statusstrings[provider->up->up->status]));
diff -bB --exclude='*~' --exclude='*.orig' --exclude='*.rej' -ruN 
in/debian/dpkg-1.14.4/src/help.c construct/dpkg-1.14.4/src/help.c
--- in/debian/dpkg-1.14.4/src/help.c    2007-01-12 00:01:37.000000000 +0000
+++ construct/dpkg-1.14.4/src/help.c    2007-05-30 16:09:39.000000000 +0100
@@ -152,6 +152,12 @@
          ignore_depends(possi->up->up);
 }
 
+int force_breaks(struct deppossi *possi) {
+  return fc_breaks ||
+         ignore_depends(possi->ed) ||
+         ignore_depends(possi->up->up);
+}
+
 int force_conflicts(struct deppossi *possi) {
   return fc_conflicts;
 }
diff -bB --exclude='*~' --exclude='*.orig' --exclude='*.rej' -ruN 
in/debian/dpkg-1.14.4/src/main.c construct/dpkg-1.14.4/src/main.c
--- in/debian/dpkg-1.14.4/src/main.c    2006-06-19 02:22:03.000000000 +0100
+++ construct/dpkg-1.14.4/src/main.c    2007-05-30 16:09:39.000000000 +0100
@@ -154,7 +154,7 @@
 /* Change fc_overwrite to 1 to enable force-overwrite by default */
 int fc_downgrade=1, fc_configureany=0, fc_hold=0, fc_removereinstreq=0, 
fc_overwrite=0;
 int fc_removeessential=0, fc_conflicts=0, fc_depends=0, fc_dependsversion=0;
-int fc_badpath=0, fc_overwritediverted=0, fc_architecture=0;
+int fc_breaks=0, fc_badpath=0, fc_overwritediverted=0, fc_architecture=0;
 int fc_nonroot=0, fc_overwritedir=0, fc_conff_new=0, fc_conff_miss=0;
 int fc_conff_old=0, fc_conff_def=0;
 int fc_badverify = 0;
@@ -180,6 +180,7 @@
   { "confmiss",            &fc_conff_miss               },
   { "depends",             &fc_depends                  },
   { "depends-version",     &fc_dependsversion           },
+  { "breaks",              &fc_breaks                   },
   { "bad-path",            &fc_badpath                  },
   { "not-root",            &fc_nonroot                  },
   { "overwrite",           &fc_overwrite                },
diff -bB --exclude='*~' --exclude='*.orig' --exclude='*.rej' -ruN 
in/debian/dpkg-1.14.4/src/main.h construct/dpkg-1.14.4/src/main.h
--- in/debian/dpkg-1.14.4/src/main.h    2006-06-19 02:22:03.000000000 +0100
+++ construct/dpkg-1.14.4/src/main.h    2007-05-30 16:09:39.000000000 +0100
@@ -46,6 +46,7 @@
 struct packageinlist {
   struct packageinlist *next;
   struct pkginfo *pkg;
+  void *xinfo;
 };
 
 enum action { act_unset, act_install, act_unpack, act_avail, act_configure,
@@ -86,7 +87,7 @@
 extern unsigned long f_debug;
 extern int fc_downgrade, fc_configureany, fc_hold, fc_removereinstreq, 
fc_overwrite;
 extern int fc_removeessential, fc_conflicts, fc_depends, fc_dependsversion;
-extern int fc_badpath, fc_overwritediverted, fc_architecture;
+extern int fc_breaks, fc_badpath, fc_overwritediverted, fc_architecture;
 extern int fc_nonroot, fc_overwritedir, fc_conff_new, fc_conff_miss;
 extern int fc_conff_old, fc_conff_def;
 extern int fc_badverify;
@@ -150,7 +151,8 @@
 void removal_bulk(struct pkginfo *pkg);
 int conffderef(struct pkginfo *pkg, struct varbuf *result, const char *in);
 int dependencies_ok(struct pkginfo *pkg, struct pkginfo *removing,
-                    struct varbuf *aemsgs);
+                    struct varbuf *aemsgs); /* checks [Pre]-Depends only */
+int breakses_ok(struct pkginfo *pkg, struct varbuf *aemsgs);
 
 void deferred_remove(struct pkginfo *pkg);
 void deferred_configure(struct pkginfo *pkg);
@@ -177,6 +179,7 @@
 void cu_closefd(int argc, void **argv);
 
 int ignore_depends(struct pkginfo *pkg);
+int force_breaks(struct deppossi *possi);
 int force_depends(struct deppossi *possi);
 int force_conff_new(struct deppossi *possi);
 int force_conff_miss(struct deppossi *possi);
diff -bB --exclude='*~' --exclude='*.orig' --exclude='*.rej' -ruN 
in/debian/dpkg-1.14.4/src/packages.c construct/dpkg-1.14.4/src/packages.c
--- in/debian/dpkg-1.14.4/src/packages.c        2006-06-29 01:25:43.000000000 
+0100
+++ construct/dpkg-1.14.4/src/packages.c        2007-05-30 16:09:39.000000000 
+0100
@@ -339,6 +339,82 @@
   }
 }
 
+static void breaks_check_one(struct varbuf *aemsgs, int *ok,
+                            struct deppossi *breaks,
+                            struct pkginfo *broken,
+                            struct pkginfo *breaker,
+                            struct pkginfo *virtbroken) {
+  struct varbuf depmsg;
+                 
+  debug(dbg_depcondetail,"      checking breaker %s virtbroken %s",
+       breaker->name, virtbroken ? virtbroken->name : "<none>");
+
+  if (breaker->status == stat_notinstalled ||
+      breaker->status == stat_configfiles) return;
+  if (broken == breaker) return;
+  if (!versionsatisfied(&broken->installed, breaks)) return;
+  if (ignore_depends(breaker)) return;
+  if (virtbroken && ignore_depends(virtbroken)) return;
+
+  varbufinit(&depmsg);
+  varbufdependency(&depmsg, breaks->up);
+  varbufaddc(&depmsg, 0);
+  varbufprintf(aemsgs, _(" %s (%s) breaks %s and is %s.\n"),
+              breaker->name, 
+              versiondescribe(&breaker->installed.version,
+                              vdew_nonambig),
+              depmsg.buf,
+              gettext(statusstrings[breaker->status]));
+  varbuffree(&depmsg);
+  
+  if (virtbroken) {
+    varbufprintf(aemsgs, _("  %s (%s) provides %s.\n"),
+                broken->name,
+                versiondescribe(&broken->installed.version,
+                                vdew_nonambig),
+                virtbroken->name);
+  } else if (breaks->verrel != dvr_none) {
+    varbufprintf(aemsgs, _("  Version of %s to be configured is %s.\n"),
+                broken->name,
+                versiondescribe(&broken->installed.version,
+                                vdew_nonambig));
+    if (fc_dependsversion) return;
+  }
+  if (force_breaks(breaks)) return;
+  *ok= 0;
+}  
+
+void breaks_check_target(struct varbuf *aemsgs, int *ok,
+                        struct pkginfo *broken,
+                        struct pkginfo *target,
+                        struct pkginfo *virtbroken) {
+  struct deppossi *possi;
+  
+  for (possi= target->installed.depended; possi; possi= possi->nextrev) {
+    if (possi->up->type != dep_breaks) continue;
+    if (virtbroken && possi->verrel != dvr_none) continue;
+    breaks_check_one(aemsgs,ok, possi,broken,possi->up->up,virtbroken);
+  }
+}
+
+int breakses_ok(struct pkginfo *pkg, struct varbuf *aemsgs) {
+  struct dependency *dep;
+  struct pkginfo *virtbroken;
+  int ok= 2;
+
+  debug(dbg_depcon,"    checking Breaks");
+
+  breaks_check_target(aemsgs,&ok, pkg,pkg,0);
+
+  for (dep= pkg->installed.depends; dep; dep= dep->next) {
+    if (dep->type != dep_provides) continue;
+    virtbroken= dep->list->ed;
+    debug(dbg_depcondetail,"     checking virtbroken %s", virtbroken->name);
+    breaks_check_target(aemsgs,&ok, pkg,virtbroken,virtbroken);
+  }
+  return ok;
+}
+
 int dependencies_ok(struct pkginfo *pkg, struct pkginfo *removing,
                     struct varbuf *aemsgs) {
   int ok, matched, found, thisf, interestingwarnings;
diff -bB --exclude='*~' --exclude='*.orig' --exclude='*.rej' -ruN 
in/debian/dpkg-1.14.4/src/processarc.c construct/dpkg-1.14.4/src/processarc.c
--- in/debian/dpkg-1.14.4/src/processarc.c      2007-04-19 02:24:11.000000000 
+0100
+++ construct/dpkg-1.14.4/src/processarc.c      2007-05-30 16:09:39.000000000 
+0100
@@ -241,6 +241,10 @@
       /* Look for things we conflict with. */
       check_conflict(dsearch, pkg, pfilename);
       break;
+    case dep_breaks:
+      /* Look for things we break. */
+      check_breaks(dsearch, pkg, pfilename);
+      break;
     case dep_provides:
       /* Look for things that conflict with what we provide. */
       if (dsearch->list->ed->installed.valid) {
@@ -252,16 +256,6 @@
         }
       }
       break;
-    case dep_breaks:
-      fprintf(stderr, _("dpkg: regarding %s containing %s:\n"
-                       " package uses Breaks; not supported in this dpkg\n"),
-             pfilename, pkg->name);
-      if (!force_depends(dsearch->list))
-       ohshit(_("unsupported dependency problem - not installing %.250s"),
-              pkg->name);
-      fprintf(stderr, _("dpkg: warning - ignoring Breaks !\n"));
-      /* FIXME: implement Breaks */
-      break;
     case dep_suggests:
     case dep_recommends:
     case dep_depends:
@@ -404,12 +398,13 @@
     modstatdb_note(pkg);
   }
 
-  for (i = 0 ; i < cflict_index ; i++) {
-    if (!(conflictor[i]->status == stat_halfconfigured ||
-         conflictor[i]->status == stat_installed)) continue;
     for (deconpil= deconfigure; deconpil; deconpil= deconpil->next) {
-      printf(_("De-configuring %s, so that we can remove %s ...\n"),
-             deconpil->pkg->name, conflictor[i]->name);
+    struct pkginfo *removing= deconpil->xinfo;
+    
+    printf(removing ?
+          _("De-configuring %s, to allow removal of %s ...\n") :
+          _("De-configuring %s ...\n"),
+          deconpil->pkg->name, removing ? removing->name : 0);
       deconpil->pkg->status= stat_halfconfigured;
       modstatdb_note(deconpil->pkg);
       /* This means that we *either* go and run postinst abort-deconfigure,
@@ -418,17 +413,21 @@
        */
       push_cleanup(cu_prermdeconfigure,~ehflag_normaltidy,
                    ok_prermdeconfigure,ehflag_normaltidy,
-                   3,(void*)deconpil->pkg,
-                  (void*)conflictor[i],(void*)pkg);
+                3,(void*)deconpil->pkg,(void*)removing,(void*)pkg);
       maintainer_script_installed(deconpil->pkg, PRERMFILE, "pre-removal",
                                   "deconfigure", "in-favour", pkg->name,
                                   versiondescribe(&pkg->available.version,
                                                   vdew_nonambig),
-                                  "removing", conflictor[i]->name,
-                                  
versiondescribe(&conflictor[i]->installed.version,
-                                                  vdew_nonambig),
+                               removing ? "removing" : (char*)0,
+                               removing ? removing->name : (char*)0,
+                               removing ? 
versiondescribe(&removing->installed.version,
+                                               vdew_nonambig) : (char*)0,
                                   (char*)0);
     }
+
+  for (i = 0 ; i < cflict_index ; i++) {
+    if (!(conflictor[i]->status == stat_halfconfigured ||
+         conflictor[i]->status == stat_installed)) continue;
     conflictor[i]->status= stat_halfconfigured;
     modstatdb_note(conflictor[i]);
     push_cleanup(cu_prerminfavour,~ehflag_normaltidy, 0,0,

Reply via email to