Hello Raphael, Raphael Hertzog [2010-05-19 14:24 +0200]: > Hi, > > On Wed, 19 May 2010, Martin Pitt wrote: > > 0001-Add-two-new-dpkg-options-exclude-and-include.patch is against > > curent git head, converts the former filter.d/ logic into new options > > --include and --exclude, and adds those to --help and the manpage. Did > > I miss any other place where this should be documented? > > No, I think you covered everything relevant. > > > > - new corresponding non-regression tests in pkg-tests.git > > > > In 0001-Add-filtering-test-cases.patch. > > Can you push that to some public git repository so that we can pull from > it? "git am 0001-Add-filtering-test-cases.patch" won't do? Sure, once folks are satisfied with the patch I can put the branch somewhere. > We tend to use a pseudo-header "Based-on-patch-by: ". Fixed. > We try to avoid using `' and prefer '' for new content. I see. Fixed. > For new files we use 8 char indentation with a hard tab. Ah, seems I looked at the wrong files then, sorry. Fixed. > There's m_strdup() now, please use that. Done. New patch attached. Thanks, Martin -- Martin Pitt | http://www.piware.de Ubuntu Developer (www.ubuntu.com) | Debian Developer (www.debian.org)
From 004d9ef04dd284d2a308846ab35dcfe4ed8d998b Mon Sep 17 00:00:00 2001
From: Martin Pitt <martin.pitt@ubuntu.com>
Date: Wed, 19 May 2010 12:41:28 +0200
Subject: [PATCH] Add two new dpkg options --exclude and --include
This provides support for filtering files on package installation. This allows
embedded systems to skip /usr/share/doc, manpages, etc.
Based-on-patch-by: Tollef Fog Heen <tfheen@err.no>
---
debian/changelog | 5 ++
man/dpkg.1 | 22 +++++++++
src/Makefile.am | 1 +
src/archives.c | 10 ++++
src/filters.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/filters.h | 31 +++++++++++++
src/main.c | 11 +++++
7 files changed, 210 insertions(+), 0 deletions(-)
create mode 100644 src/filters.c
create mode 100644 src/filters.h
diff --git a/debian/changelog b/debian/changelog
index 0fe4ddb..c1388f1 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -29,6 +29,11 @@ dpkg (1.15.8) UNRELEASED; urgency=low
* Russian (Yuri Kozlov). Closes: #579149
* Swedish (Peter Krefting).
+ [ Martin Pitt ]
+ * Add two new dpkg options --exclude and --include for filtering files on
+ package installation. This allows embedded systems to skip
+ /usr/share/doc, manpages, etc. Based on work from Tollef Fog Heen, thanks!
+
-- Guillem Jover <guillem@debian.org> Wed, 21 Apr 2010 04:40:12 +0200
dpkg (1.15.7.2) unstable; urgency=low
diff --git a/man/dpkg.1 b/man/dpkg.1
index cbac662..d08e6ab 100644
--- a/man/dpkg.1
+++ b/man/dpkg.1
@@ -568,6 +568,28 @@ may leave packages in the improper \fBtriggers\-awaited\fP and
.TP
\fB\-\-triggers\fP
Cancels a previous \fB\-\-no\-triggers\fP.
+.TP
+\fB\-\-exclude=\fP\fIpattern\fP
+Do not install files which match a shell pattern. '*' matches any sequence of
+characters, including the empty string and also '/'.
+For example, '/usr/*/READ*' matches '/usr/share/doc/mypackage/README'\fP.
+As usual, '?' matches any single character (again, including '/').
+
+This option be specified multiple times, and interleaved with
+\fB\-\-include\fP options. Both are processed in the given order, with the last
+rule that matches a file name making the decision.
+.TP
+\fB\-\-include=\fP\fIpattern\fP
+Re-include a pattern after a previous \fB\-\-exclude\fP. This can be used to
+remove all files except some particular ones; a typical case is:
+
+.B \-\-exclude=/usr/share/doc/* \-\-include=/usr/share/doc/*/copyright
+
+to remove all documentation files except the copyright files.
+
+This option be specified multiple times, and interleaved with
+\fB\-\-include\fP options. Both are processed in the given order, with the last
+rule that matches a file name making the decision.
.
.SH FILES
.TP
diff --git a/src/Makefile.am b/src/Makefile.am
index ddde846..d6fdfd2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -26,6 +26,7 @@ dpkg_SOURCES = \
enquiry.c \
errors.c \
filesdb.c filesdb.h \
+ filters.c filters.h \
divertdb.c \
statdb.c \
help.c \
diff --git a/src/archives.c b/src/archives.c
index b0a0fd1..33dd349 100644
--- a/src/archives.c
+++ b/src/archives.c
@@ -57,6 +57,7 @@
#include "filesdb.h"
#include "main.h"
#include "archives.h"
+#include "filters.h"
#define MAXCONFLICTORS 20
@@ -427,6 +428,15 @@ int tarobject(struct TarInfo *ti) {
nifd->namenode->divert && nifd->namenode->divert->useinstead
? nifd->namenode->divert->useinstead->name : "<none>");
+ if (filter_should_skip(ti)) {
+ struct filenamenode *fnn = findnamenode(ti->Name, 0);
+
+ fnn->flags &= ~fnnf_new_inarchive;
+ tarfile_skip_one_forward(ti, oldnifd, nifd);
+
+ return 0;
+ }
+
if (nifd->namenode->divert && nifd->namenode->divert->camefrom) {
divpkg= nifd->namenode->divert->pkg;
diff --git a/src/filters.c b/src/filters.c
new file mode 100644
index 0000000..9c9123a
--- /dev/null
+++ b/src/filters.c
@@ -0,0 +1,130 @@
+/*
+ * dpkg - main program for package management
+ * filters.c - filtering routines for excluding bits of packages
+ *
+ * Copyright (C) 2007,2008 Tollef Fog Heen <tfheen@err.no>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#include <dpkg/i18n.h>
+
+#include <fnmatch.h>
+
+#include <dpkg/dpkg.h>
+#include <dpkg/dpkg-db.h>
+
+#include "main.h"
+#include "filesdb.h"
+#include "filters.h"
+
+struct filterlist {
+ int positive;
+ char *glob;
+ struct filterlist *next;
+};
+
+static struct filterlist *filters = NULL;
+static struct filterlist **filtertail = &filters;
+
+void add_filter(const char* glob, int positive)
+{
+ struct filterlist *filter;
+
+ filter = m_malloc(sizeof(struct filterlist));
+ memset(filter, 0, sizeof(struct filterlist));
+
+ filter->positive = positive;
+ filter->glob = m_strdup(glob);
+ if (!filter->glob)
+ ohshite(_("error allocating memory for filter entry"));
+
+ debug(dbg_general, "adding %s filter for '%s'\n",
+ positive ? "include" : "exclude", glob);
+
+ *filtertail = filter;
+ filtertail = &filter->next;
+}
+
+static int do_filter_should_skip(struct TarInfo *ti)
+{
+ int remove = 0;
+ struct filterlist *f;
+
+ /* Last match wins. */
+ for (f = filters; f != NULL; f = f->next) {
+ debug(dbg_eachfile, "tarobject comparing '%s' and '%s'",
+ &ti->Name[1], f->glob);
+
+ if (fnmatch(f->glob, &ti->Name[1], 0) == 0) {
+ if (f->positive == 0) {
+ remove = 1;
+ debug(dbg_eachfile, "do_filter removing %s",
+ ti->Name);
+ } else {
+ remove = 0;
+ debug(dbg_eachfile, "do_filter including %s",
+ ti->Name);
+ }
+ }
+ }
+
+ /* We need to keep directories if a glob excludes them, but a more specific
+ * include glob brings back files; this will probably create more directories
+ * than necessary, but better err on the side of caution than failing with
+ * "no such file or directory" (which would leave the package in a very bad
+ * state). */
+ if (remove && ti->Type == Directory) {
+ char* pos;
+ int cmplen;
+
+ debug(dbg_eachfile,
+ "tarobject seeing if '%s' needs to be reincluded",
+ &ti->Name[1]);
+
+ for (f = filters; f != NULL; f = f->next) {
+ if (f->positive == 0)
+ continue;
+
+ /* calculate the offset of the first * or ? char in the glob */
+ cmplen = strlen(f->glob);
+ pos = strchr(f->glob, '*');
+ if (pos)
+ cmplen = pos - f->glob;
+ pos = strchr(f->glob, '?');
+ if (pos && (pos - f->glob) < cmplen)
+ cmplen = pos - f->glob;
+
+ if (strncmp(&ti->Name[1], f->glob, cmplen) == 0) {
+ remove = 0;
+ debug(dbg_eachfile, "tarobject reincluding %s",
+ ti->Name);
+ }
+ }
+ }
+
+ return remove;
+}
+
+int filter_should_skip(struct TarInfo *ti)
+{
+ if (filters)
+ return do_filter_should_skip(ti);
+ else
+ return 0;
+}
+
diff --git a/src/filters.h b/src/filters.h
new file mode 100644
index 0000000..00730a0
--- /dev/null
+++ b/src/filters.h
@@ -0,0 +1,31 @@
+/*
+ * dpkg - main program for package management
+ * filters.h - external definitions for filter handling
+ *
+ * Copyright (C) 2007,2008 Tollef Fog Heen <tfheen@err.no>
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2,
+ * or (at your option) any later version.
+ *
+ * This is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef DPKG_FILTERS_H
+#define DPKG_FILTERS_H
+
+#include <dpkg/tarfn.h>
+
+void add_filter(const char* glob, int positive);
+int filter_should_skip(struct TarInfo *ti);
+
+#endif
+
diff --git a/src/main.c b/src/main.c
index b902406..932eb25 100644
--- a/src/main.c
+++ b/src/main.c
@@ -49,6 +49,7 @@
#include "main.h"
#include "filesdb.h"
+#include "filters.h"
static void DPKG_ATTR_NORET
printversion(const struct cmdinfo *ci, const char *value)
@@ -139,6 +140,10 @@ usage(const struct cmdinfo *ci, const char *value)
" --no-force-...|--refuse-...\n"
" Stop when problems encountered.\n"
" --abort-after <n> Abort after encountering <n> errors.\n"
+" --exclude <pattern> Do not install files which match a shell pattern.\n"
+" --include <pattern> Re-include a pattern after a previous --exclude.\n"
+" --exclude and --include can be specified multiple\n"
+" times and are processed in order.\n"
"\n"), ADMINDIR);
printf(_(
@@ -255,6 +260,10 @@ static void setdebug(const struct cmdinfo *cpi, const char *value) {
if (value == endp || *endp) badusage(_("--debug requires an octal argument"));
}
+static void setfilter(const struct cmdinfo *cpi, const char *value) {
+ add_filter(value, cpi->arg);
+}
+
static void setroot(const struct cmdinfo *cip, const char *value) {
char *p;
instdir= value;
@@ -517,6 +526,8 @@ static const struct cmdinfo cmdinfos[]= {
{ "refuse", 0, 2, NULL, NULL, setforce, 0 },
{ "no-force", 0, 2, NULL, NULL, setforce, 0 },
{ "debug", 'D', 1, NULL, NULL, setdebug, 0 },
+ { "exclude", 0, 1, NULL, NULL, setfilter, 0 },
+ { "include", 0, 1, NULL, NULL, setfilter, 1 },
{ "help", 'h', 0, NULL, NULL, usage, 0 },
{ "version", 0, 0, NULL, NULL, printversion, 0 },
ACTIONBACKEND( "build", 'b', BACKEND),
--
1.7.0.4
Attachment:
signature.asc
Description: Digital signature