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