On Wed, 31 Oct 2007, Ian Jackson wrote: > Raphael Hertzog writes ("Bug#20471: patch to check rdepends on unpack"): > > Please either attach a copy of the patch or use git.debian.org so that we > > can browse the changes via gitweb. > > It's now at > http://git.debian.org/?p=users/iwj/dpkg.git > git://git.debian.org/git/users/iwj/dpkg.git > etc. as the branch > bug20471
It doesn't seem to depend on your trigger branch so it would have been better applied on the official master branch. (Also as long as it's a single commit it doesn't matter much) I just did that locally and attached is the corresponding patch (created by git-format-patch for easy inclusion). I adjusted the commit log, the changelog and fixed some trailing spaces (that the pre-commit hook forbid me to commit). Cheers, -- Raphaël Hertzog Premier livre français sur Debian GNU/Linux : http://www.ouaza.com/livre/admin-debian/
>From 17b87fa14197059c72d3e61e277e349dfd048f49 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. --- debian/changelog | 6 +++++ src/archives.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++ src/archives.h | 2 + src/depcon.c | 17 +++++++++++---- src/processarc.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++------ 5 files changed, 118 insertions(+), 12 deletions(-) diff --git a/debian/changelog b/debian/changelog index 8b78abb..31b8ccb 100644 --- a/debian/changelog +++ b/debian/changelog @@ -68,6 +68,12 @@ dpkg (1.14.8) UNRELEASED; urgency=low * Swedish (Peter Karlsson). * German added (Helge Kreutzmann). Closes: #448353 + [ Ian Jackson ] + * 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. + -- Raphael Hertzog <[EMAIL PROTECTED]> Mon, 08 Oct 2007 20:49:51 +0200 dpkg (1.14.8~newshlib) experimental; urgency=low diff --git a/src/archives.c b/src/archives.c index df21d27..2a79b53 100644 --- a/src/archives.c +++ b/src/archives.c @@ -1055,6 +1055,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 5f7f285..a8496b9 100644 --- a/src/depcon.c +++ b/src/depcon.c @@ -340,12 +340,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 cb69504..27c96f3 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,0,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.4