From b301c0e71a5314bb4560111c6cf1602269f6f672 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Tue, 7 Aug 2007 05:52:46 +0300 Subject: [PATCH] Implement support for Breaks field. As a side effect, run the deconfiguration of each package to be deconfigured once, instead of once per each conflicting package being removed. --- ChangeLog | 37 ++++++++++++ debian/changelog | 5 ++ man/deb-control.5 | 8 +++ man/dpkg-query.1 | 1 + man/dpkg.1 | 3 + scripts/controllib.pl | 2 +- scripts/dpkg-genchanges.pl | 2 +- scripts/dpkg-source.pl | 2 +- src/archives.c | 112 ++++++++++++++++++++++++++++++++----- src/archives.h | 2 + src/cleanup.c | 12 ++-- src/configure.c | 4 +- src/depcon.c | 35 +++++++++--- src/help.c | 6 ++ src/main.c | 3 +- src/main.h | 7 ++- src/packages.c | 73 ++++++++++++++++++++++++ src/processarc.c | 39 ++++++------- 18 files changed, 298 insertions(+), 55 deletions(-) diff --git a/ChangeLog b/ChangeLog index 34e30384..87304163 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,40 @@ +2007-08-07 Ian Jackson + + * man/deb-control.5: Document Breaks field. + * man/dpkg-query.1: Document Breaks as a recognized field. + * man/dpkg.1: Add description of '--force-breaks'. + * scripts/controllib.pl (@pkg_dep_fields): Add 'Breaks'. + * scripts/dpkg-genchanges.pl: Ignore Breaks field. + * scripts/dpkg-source.pl: Likewise. + * src/archives.c (try_remove_can): Rename to ... + (try_deconfigure_can): ... this. Generalize dependency force check + by taking a function as argument. Store the possible package removal + which caused the deconfiguration in the xinfo member of the package + to be deconfigured. + (try_remove_can): New function. + (check_breaks): Likewise. + * src/archives.h (check_breaks): New prototype. + * src/cleanup.c (cu_prermdeconfigure): Handle case when argv[1] + might be 0, if deconfigure was due to Breaks. + * src/configure.c (deferred_configure): Call breakses_ok. + * src/depcon.c (depisok): Add Breaks support. + * src/help.c (force_breaks): New function. + * src/main.c (fc_breaks): New variable. + (forceinfo): Add 'breaks' as a supported option for '--force-...'. + * src/main.h (struct perpackagestate): Add xinfo member. + (fc_breaks): New variable definition. + (breakses_ok): New prototype. + (force_depends): Likewise. + * src/packages.c (breaks_check_one): New function. + (breaks_check_target): Likewise. + (breakses_ok): Likewise. + * src/processarc.c (process_archive): Check for Breaks dependencies, + instead of bailing out if field found. Distinguish between deconfigure + due to a removal due to Conflicts or Depends, and deconfigure due to + an installation due to Breaks. Run the deconfiguration of each + package to be deconfigured once, instead of once per each conflicting + package being removed. + 2007-07-31 Ian Jackson * src/archives.c (quote_filename): Change formatting to match the diff --git a/debian/changelog b/debian/changelog index 7a477547..638ba6d8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -17,6 +17,11 @@ dpkg (1.14.6) UNRELEASED; urgency=low * Move variables automatically modified at build time for the perl scripts to a new style perl module (Dpkg) and make all programs use it. * Switch 'dpkg-gettext.pl' to a new style perl module (Dpkg::Gettext). + * Implement support for Breaks field. Closes: #379140 + Thanks to Ian Jackson. + * Run the deconfiguration of each package to be deconfigured once, instead + of once per each conflicting package being removed. Closes: #378003 + Thanks to Ian Jackson. [ Updated scripts translations ] * French (Frédéric Bothamy, Christian Perrier). diff --git a/man/deb-control.5 b/man/deb-control.5 index 41613932..3cde45c7 100644 --- a/man/deb-control.5 +++ b/man/deb-control.5 @@ -136,6 +136,14 @@ by a hyphen). Accepted version relationships are ">>" for greater than, "<<" for less than, ">=" for greater than or equal to, "<=" for less than or equal to, and "=" for equal to. .TP +.BR Breaks: " " +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: " " Lists packages that conflict with this one, for example by containing files with the same names. The package maintenance software will not diff --git a/man/dpkg-query.1 b/man/dpkg-query.1 index e030d623..9f03411e 100644 --- a/man/dpkg-query.1 +++ b/man/dpkg-query.1 @@ -103,6 +103,7 @@ alignment will be used. The following \fIfield\fRs are recognised: \fBConffiles\fP \fBConfig\-Version\fP \fBConflicts\fP + \fBBreaks\fP \fBDepends\fP \fBDescription\fP \fBEnhances\fP diff --git a/man/dpkg.1 b/man/dpkg.1 index 6f8624e8..4d976498 100644 --- a/man/dpkg.1 +++ b/man/dpkg.1 @@ -372,6 +372,9 @@ Turn all dependency problems into warnings. \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 --git a/scripts/controllib.pl b/scripts/controllib.pl index 08cbd311..a94ff2bf 100755 --- a/scripts/controllib.pl +++ b/scripts/controllib.pl @@ -26,7 +26,7 @@ our %substvar; # - map with substitution variables 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 --git a/scripts/dpkg-genchanges.pl b/scripts/dpkg-genchanges.pl index 42564c9d..967eede4 100755 --- a/scripts/dpkg-genchanges.pl +++ b/scripts/dpkg-genchanges.pl @@ -251,7 +251,7 @@ for $_ (keys %fi) { } 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 --git a/scripts/dpkg-source.pl b/scripts/dpkg-source.pl index 1ed1213b..9706f23c 100755 --- a/scripts/dpkg-source.pl +++ b/scripts/dpkg-source.pl @@ -281,7 +281,7 @@ if ($opmode eq 'build') { $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 --git a/src/archives.c b/src/archives.c index 826cbf3d..b907d926 100644 --- a/src/archives.c +++ b/src/archives.c @@ -780,42 +780,124 @@ int tarobject(struct TarInfo *ti) { 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 (due to Conflicts+Depends removal!=0) + * installation of (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 --git a/src/archives.h b/src/archives.h index 60b3aae3..5696c198 100644 --- a/src/archives.h +++ b/src/archives.h @@ -65,6 +65,8 @@ int filesavespackage(struct fileinlist*, struct pkginfo*, 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 --git a/src/cleanup.c b/src/cleanup.c index d1996b16..6a96836f 100644 --- a/src/cleanup.c +++ b/src/cleanup.c @@ -120,7 +120,8 @@ void cu_prermupgrade(int argc, void **argv) { 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 ok_prermdeconfigure(int argc, void **argv) { 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 --git a/src/configure.c b/src/configure.c index 0df4582c..0615728a 100644 --- a/src/configure.c +++ b/src/configure.c @@ -108,7 +108,9 @@ void deferred_configure(struct pkginfo *pkg) { 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 --git a/src/depcon.c b/src/depcon.c index a54279cb..24f93aea 100644 --- a/src/depcon.c +++ b/src/depcon.c @@ -196,6 +196,10 @@ int depisok(struct dependency *dep, struct varbuf *whynot, * 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 @@ int depisok(struct dependency *dep, struct varbuf *whynot, 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 @@ int depisok(struct dependency *dep, struct varbuf *whynot, } } - 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 @@ int depisok(struct dependency *dep, struct varbuf *whynot, 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 @@ int depisok(struct dependency *dep, struct varbuf *whynot, 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 @@ int depisok(struct dependency *dep, struct varbuf *whynot, 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 --git a/src/help.c b/src/help.c index cacca11f..ba4a8455 100644 --- a/src/help.c +++ b/src/help.c @@ -152,6 +152,12 @@ int force_depends(struct deppossi *possi) { 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 --git a/src/main.c b/src/main.c index 29e4cc7d..28c4d5ae 100644 --- a/src/main.c +++ b/src/main.c @@ -154,7 +154,7 @@ unsigned long f_debug=0; /* 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 @@ static const struct forceinfo { { "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 --git a/src/main.h b/src/main.h index 0560c4c9..10110942 100644 --- a/src/main.h +++ b/src/main.h @@ -46,6 +46,7 @@ struct perpackagestate { 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 int f_autodeconf, f_largemem, f_nodebsig; 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 packages(const char *const *argv); 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_closedir(int argc, void **argv); 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 --git a/src/packages.c b/src/packages.c index 8e5a77b5..ebbd5a90 100644 --- a/src/packages.c +++ b/src/packages.c @@ -339,6 +339,79 @@ static int deppossi_ok_found(struct pkginfo *possdependee, } } +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 : ""); + + 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 --git a/src/processarc.c b/src/processarc.c index c22f623e..31f28e94 100644 --- a/src/processarc.c +++ b/src/processarc.c @@ -241,6 +241,10 @@ void process_archive(const char *filename) { /* 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 @@ void process_archive(const char *filename) { } } 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,14 @@ void process_archive(const char *filename) { 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, @@ -419,16 +415,21 @@ void process_archive(const char *filename) { push_cleanup(cu_prermdeconfigure,~ehflag_normaltidy, ok_prermdeconfigure,ehflag_normaltidy, 3,(void*)deconpil->pkg, - (void*)conflictor[i],(void*)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, -- 2.39.5