The branch, master has been updated
via 85849a460dbedc4e9464725c7d317bedc76049df (commit)
via 36c7e5ae5ccdc10fac5b5d42ecf9206181c941c1 (commit)
via b301c0e71a5314bb4560111c6cf1602269f6f672 (commit)
via b31f79e7ef0e8b958442fbb55d08c11b404812ad (commit)
from 5789109124b8b3fb230248d0ca50cf2e92b9abd7 (commit)
- Log -----------------------------------------------------------------
commit 85849a460dbedc4e9464725c7d317bedc76049df
Author: Guillem Jover <[EMAIL PROTECTED]>
Date: Tue Aug 7 06:29:39 2007 +0300
Tighten dependencies between dpkg and dpkg-dev due to the modularization.
commit 36c7e5ae5ccdc10fac5b5d42ecf9206181c941c1
Author: Guillem Jover <[EMAIL PROTECTED]>
Date: Tue Aug 7 06:22:19 2007 +0300
Fix pattern matching in dpkg-query -l and -W.
Do not segfault when the result from a 'dpkg-query -l' is bigger than
the total number of current packages, and do not produce repeated
results with overlapping patterns on 'dpkg-query -W'.
commit b301c0e71a5314bb4560111c6cf1602269f6f672
Author: Ian Jackson <[EMAIL PROTECTED]>
Date: Tue Aug 7 05:52:46 2007 +0300
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.
commit b31f79e7ef0e8b958442fbb55d08c11b404812ad
Author: Ian Jackson <[EMAIL PROTECTED]>
Date: Tue Jul 31 04:17:02 2007 +0300
Change formatting to match the rest of the file.
-----------------------------------------------------------------------
Summary of changes:
ChangeLog | 52 +++++++++++++
debian/changelog | 10 +++
debian/control | 4 +-
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 | 176 ++++++++++++++++++++++++++++++++------------
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 +++++-----
src/query.c | 82 +++++++++++++--------
20 files changed, 404 insertions(+), 119 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index ab2de9f..cde65a7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,55 @@
+2007-08-07 Guillem Jover <[EMAIL PROTECTED]>
+
+ * src/query.c (listpackages): Instead of allocating an additional
+ packages array with room for the the current amount of packages,
+ sort the existing one, and print the packages matching the pattern,
+ which fixes segfaults when the resulting array was bigger than the
+ current amount of packages.
+ (showpackages): For each package show it only once it matches any
+ of the patterns, so we avoid duplicated results.
+
+2007-08-07 Ian Jackson <[EMAIL PROTECTED]>
+
+ * 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 <[EMAIL PROTECTED]>
+
+ * src/archives.c (quote_filename): Change formatting to match the
+ rest of the file (tab -> 2 spaces).
+
2007-07-25 Guillem Jover <[EMAIL PROTECTED]>
* scripts/changelog/debian.pl: Switch from 'dpkg-gettext.pl' to
diff --git a/debian/changelog b/debian/changelog
index 7a47754..6d8af60 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -17,6 +17,16 @@ 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.
+ * Do not segfault when the result from a 'dpkg-query -l' is bigger than
+ the total number of current packages, and do not produce repeated
+ results with overlapping patterns on 'dpkg-query -W'. Closes: #428427
+ * Tightening dpkg-dev versioned Depends to dpkg 1.14.6, and dpkg Conflicts
+ against << dpkg-dev 1.14.6, where the perl modularization started.
[ Updated scripts translations ]
* French (Frédéric Bothamy, Christian Perrier).
diff --git a/debian/control b/debian/control
index 6a114e5..bb150b7 100644
--- a/debian/control
+++ b/debian/control
@@ -15,7 +15,7 @@ Architecture: any
Essential: yes
Pre-Depends: ${shlibs:Depends}, coreutils (>= 5.93-1)
Conflicts: sysvinit (<< 2.82-1), dpkg-iasearch (<< 0.11), dpkg-static,
- dpkg-dev (<< 1.14.0)
+ dpkg-dev (<< 1.14.6)
Replaces: dpkg-doc-ja, dpkg-static, manpages-de (<= 0.4-3),
manpages-pl (<= 20051117-1)
Suggests: apt, lzma
@@ -30,7 +30,7 @@ Package: dpkg-dev
Section: utils
Priority: optional
Architecture: all
-Depends: dpkg (>= 1.14.0), perl5, perl-modules, cpio (>= 2.4.2-2),
+Depends: dpkg (>= 1.14.6), perl5, perl-modules, cpio (>= 2.4.2-2),
patch (>= 2.2-1), make, binutils
Recommends: gcc | c-compiler, bzip2
Suggests: gnupg, debian-keyring
diff --git a/man/deb-control.5 b/man/deb-control.5
index 4161393..3cde45c 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: " <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 --git a/man/dpkg-query.1 b/man/dpkg-query.1
index e030d62..9f03411 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 6f8624e..4d97649 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 08cbd31..a94ff2b 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 42564c9..967eede 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 1ed1213..9706f23 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 38e2b56..b907d92 100644
--- a/src/archives.c
+++ b/src/archives.c
@@ -81,39 +81,39 @@ int cflict_index = 0;
static char *
quote_filename(char *buf, int size, char *s)
{
- char *r = buf;
- while (size > 0) {
- switch (*s) {
- case '\0':
- *buf = '\0';
- return r;
- case '\\':
- *buf++ = '\\';
- *buf++ = '\\';
- size -= 2;
- break;
- default:
- if (((*s)&0x80) == 0) {
- *buf++ = *s++;
- --size;
- } else {
- if (size > 4) {
- sprintf(buf, "\\%03o",
- *(unsigned char *)s);
- size -= 4;
- buf += 4;
- s++;
- } else {
- /* buffer full */
- *buf = '\0'; /* XXX */
- return r;
- }
- }
- }
- }
- *buf = '\0'; /* XXX */
- return r;
+ char *r = buf;
+ while (size > 0) {
+ switch (*s) {
+ case '\0':
+ *buf = '\0';
+ return r;
+ case '\\':
+ *buf++ = '\\';
+ *buf++ = '\\';
+ size -= 2;
+ break;
+ default:
+ if (((*s) & 0x80) == 0) {
+ *buf++ = *s++;
+ --size;
+ } else {
+ if (size > 4) {
+ sprintf(buf, "\\%03o", *(unsigned char *)s);
+ size -= 4;
+ buf += 4;
+ s++;
+ } else {
+ /* buffer full */
+ *buf = '\0'; /* XXX */
+ return r;
+ }
+ }
+ }
+ }
+ *buf = '\0'; /* XXX */
+
+ return r;
}
/* special routine to handle partial reads from the tarfile */
@@ -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 <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 --git a/src/archives.h b/src/archives.h
index 60b3aae..5696c19 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 d1996b1..6a96836 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 0df4582..0615728 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 a54279c..24f93ae 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 cacca11..ba4a845 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 29e4cc7..28c4d5a 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 0560c4c..1011094 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 8e5a77b..ebbd5a9 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 : "<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 --git a/src/processarc.c b/src/processarc.c
index c22f623..31f28e9 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,
diff --git a/src/query.c b/src/query.c
index 1addb08..ff8d94b 100644
--- a/src/query.c
+++ b/src/query.c
@@ -183,9 +183,8 @@ Desired=Unknown/Install/Remove/Purge/Hold\n\
void listpackages(const char *const *argv) {
struct pkgiterator *it;
struct pkginfo *pkg;
- struct pkginfo **pkgl, **pkgf;
- const char *thisarg;
- int np, nf, i, head, found;
+ struct pkginfo **pkgl;
+ int np, i, head;
modstatdb_init(admindir,msdbrw_readonly);
@@ -199,33 +198,43 @@ void listpackages(const char *const *argv) {
iterpkgend(it);
assert(i==np);
- pkgf= m_malloc(sizeof(struct pkginfo*)*np); nf=0;
+ qsort(pkgl, np, sizeof(struct pkginfo*), pkglistqsortcmp);
+ head = 0;
+
if (!*argv) {
for (i=0; i<np; i++) {
pkg= pkgl[i];
if (pkg->status == stat_notinstalled) continue;
- pkgf[nf++] = pkg;
+ list1package(pkg, &head, pkgl, np);
}
} else {
- while ((thisarg= *argv++)) {
- found= 0;
- for (i=0; i<np; i++) {
- pkg= pkgl[i];
- if (fnmatch(thisarg,pkg->name,0)) continue;
- pkgf[nf++] = pkg; found++;
+ int argc, ip, *found;
+
+ for (argc = 0; argv[argc]; argc++);
+ found = m_malloc(sizeof(int) * argc);
+ memset(found, 0, sizeof(int) * argc);
+
+ for (i = 0; i < np; i++) {
+ pkg = pkgl[i];
+ for (ip = 0; ip < argc; ip++) {
+ if (!fnmatch(argv[ip], pkg->name, 0)) {
+ list1package(pkg, &head, pkgl, np);
+ found[ip]++;
+ break;
+ }
}
- if (!found) {
- fprintf(stderr,_("No packages found matching %s.\n"),thisarg);
- nerrs++;
+ }
+
+ /* FIXME: we might get non-matching messages for sub-patterns specified
+ * after their super-patterns, due to us skipping on first match. */
+ for (ip = 0; ip < argc; ip++) {
+ if (!found[ip]) {
+ fprintf(stderr, _("No packages found matching %s.\n"), argv[ip]);
+ nerrs++;
}
}
}
- qsort(pkgf,nf,sizeof(struct pkginfo*),pkglistqsortcmp);
- head=0;
- for (i=0; i<nf; i++)
- list1package(pkgf[i],&head,pkgf,nf);
-
if (ferror(stdout)) werr("stdout");
if (ferror(stderr)) werr("stderr");
modstatdb_shutdown();
@@ -412,8 +421,7 @@ void showpackages(const char *const *argv) {
struct pkgiterator *it;
struct pkginfo *pkg;
struct pkginfo **pkgl;
- const char *thisarg;
- int np, i, found;
+ int np, i;
struct lstitem* fmt = parseformat(showformat);
if (!fmt) {
@@ -442,19 +450,33 @@ void showpackages(const char *const *argv) {
show1package(fmt,pkg);
}
} else {
- while ((thisarg= *argv++)) {
- found= 0;
- for (i=0; i<np; i++) {
- pkg= pkgl[i];
- if (fnmatch(thisarg,pkg->name,0)) continue;
- show1package(fmt,pkg); found++;
+ int argc, ip, *found;
+
+ for (argc = 0; argv[argc]; argc++);
+ found = m_malloc(sizeof(int) * argc);
+ memset(found, 0, sizeof(int) * argc);
+
+ for (i = 0; i < np; i++) {
+ pkg = pkgl[i];
+ for (ip = 0; ip < argc; ip++) {
+ if (!fnmatch(argv[ip], pkg->name, 0)) {
+ show1package(fmt, pkg);
+ found[ip]++;
+ break;
+ }
}
- if (!found) {
- fprintf(stderr,_("No packages found matching %s.\n"),thisarg);
- nerrs++;
+ }
+
+ /* FIXME: we might get non-matching messages for sub-patterns specified
+ * after their super-patterns, due to us skipping on first match. */
+ for (ip = 0; ip < argc; ip++) {
+ if (!found[ip]) {
+ fprintf(stderr, _("No packages found matching %s.\n"), argv[ip]);
+ nerrs++;
}
}
}
+
if (ferror(stdout)) werr("stdout");
if (ferror(stderr)) werr("stderr");
freeformat(fmt);
--
dpkg's main repository
--
To UNSUBSCRIBE, email to [EMAIL PROTECTED]
with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]