1 Return-Path: <bremner@tethera.net>
\r
2 X-Original-To: notmuch@notmuchmail.org
\r
3 Delivered-To: notmuch@notmuchmail.org
\r
4 Received: from localhost (localhost [127.0.0.1])
\r
5 by olra.theworths.org (Postfix) with ESMTP id 1C79C431FBD
\r
6 for <notmuch@notmuchmail.org>; Sat, 29 Mar 2014 06:46:46 -0700 (PDT)
\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org
\r
11 X-Spam-Status: No, score=0 tagged_above=-999 required=5 tests=[none]
\r
13 Received: from olra.theworths.org ([127.0.0.1])
\r
14 by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)
\r
15 with ESMTP id hglS1tXUu2UB for <notmuch@notmuchmail.org>;
\r
16 Sat, 29 Mar 2014 06:46:38 -0700 (PDT)
\r
17 Received: from yantan.tethera.net (yantan.tethera.net [199.188.72.155])
\r
18 (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits))
\r
19 (No client certificate requested)
\r
20 by olra.theworths.org (Postfix) with ESMTPS id 7AC74431FBC
\r
21 for <notmuch@notmuchmail.org>; Sat, 29 Mar 2014 06:46:38 -0700 (PDT)
\r
22 Received: from remotemail by yantan.tethera.net with local (Exim 4.80)
\r
23 (envelope-from <bremner@tethera.net>)
\r
24 id 1WTtag-0006uK-Rs; Sat, 29 Mar 2014 10:46:30 -0300
\r
25 Received: (nullmailer pid 8942 invoked by uid 1000); Sat, 29 Mar 2014
\r
27 From: David Bremner <david@tethera.net>
\r
28 To: notmuch@notmuchmail.org
\r
29 Subject: [PATCH] dump: support gzipped output
\r
30 Date: Sat, 29 Mar 2014 10:46:25 -0300
\r
31 Message-Id: <1396100785-8744-1-git-send-email-david@tethera.net>
\r
32 X-Mailer: git-send-email 1.9.0
\r
33 In-Reply-To: <1396056046-2247-1-git-send-email-david@tethera.net>
\r
34 References: <1396056046-2247-1-git-send-email-david@tethera.net>
\r
35 X-BeenThere: notmuch@notmuchmail.org
\r
36 X-Mailman-Version: 2.1.13
\r
38 List-Id: "Use and development of the notmuch mail system."
\r
39 <notmuch.notmuchmail.org>
\r
40 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,
\r
41 <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>
\r
42 List-Archive: <http://notmuchmail.org/pipermail/notmuch>
\r
43 List-Post: <mailto:notmuch@notmuchmail.org>
\r
44 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>
\r
45 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,
\r
46 <mailto:notmuch-request@notmuchmail.org?subject=subscribe>
\r
47 X-List-Received-Date: Sat, 29 Mar 2014 13:46:46 -0000
\r
49 The main goal is to support gzipped output for future internal
\r
50 calls (e.g. from notmuch-new) to notmuch_database_dump.
\r
52 The additional dependency is not very heavy since xapian already pulls
\r
56 I had a quick look at supporting gzipped input for restore; I think it
\r
57 just requires an implementation of getline that uses gzgetc or gzgets;
\r
58 the decompression can be completely transparent to the user based on
\r
61 INSTALL | 17 ++++++++++----
\r
62 Makefile.local | 2 +-
\r
63 configure | 23 ++++++++++++++++---
\r
64 doc/man1/notmuch-dump.rst | 3 +++
\r
65 notmuch-client.h | 4 +++-
\r
66 notmuch-dump.c | 57 ++++++++++++++++++++++++++++++-----------------
\r
67 test/T240-dump-restore.sh | 12 ++++++++++
\r
68 7 files changed, 89 insertions(+), 29 deletions(-)
\r
70 diff --git a/INSTALL b/INSTALL
\r
71 index 690b0ef..2754e52 100644
\r
74 @@ -20,8 +20,8 @@ configure stage.
\r
78 -Notmuch depends on three libraries: Xapian, GMime 2.4 or 2.6, and
\r
79 -Talloc which are each described below:
\r
80 +Notmuch depends on four libraries: Xapian, GMime 2.4 or 2.6,
\r
81 +Talloc, and zlib which are each described below:
\r
85 @@ -60,6 +60,15 @@ Talloc which are each described below:
\r
87 Talloc is available from http://talloc.samba.org/
\r
92 + zlib is an extremely popular compression library. It is used
\r
93 + by Xapian, so if you installed that you will already have
\r
94 + zlib. You may need to install the zlib headers seperately.
\r
96 + zlib is available from http://zlib.net
\r
98 Building Documentation
\r
99 ----------------------
\r
101 @@ -79,11 +88,11 @@ dependencies with a simple simple command line. For example:
\r
103 For Debian and similar:
\r
105 - sudo apt-get install libxapian-dev libgmime-2.6-dev libtalloc-dev python-sphinx
\r
106 + sudo apt-get install libxapian-dev libgmime-2.6-dev libtalloc-dev zlib1g-dev python-sphinx
\r
108 For Fedora and similar:
\r
110 - sudo yum install xapian-core-devel gmime-devel libtalloc-devel python-sphinx
\r
111 + sudo yum install xapian-core-devel gmime-devel libtalloc-devel zlib-devel python-sphinx
\r
113 On other systems, a similar command can be used, but the details of
\r
114 the package names may be different.
\r
115 diff --git a/Makefile.local b/Makefile.local
\r
116 index cb7b106..e5a20a7 100644
\r
117 --- a/Makefile.local
\r
118 +++ b/Makefile.local
\r
119 @@ -41,7 +41,7 @@ PV_FILE=bindings/python/notmuch/version.py
\r
120 # Smash together user's values with our extra values
\r
121 FINAL_CFLAGS = -DNOTMUCH_VERSION=$(VERSION) $(CPPFLAGS) $(CFLAGS) $(WARN_CFLAGS) $(extra_cflags) $(CONFIGURE_CFLAGS)
\r
122 FINAL_CXXFLAGS = $(CPPFLAGS) $(CXXFLAGS) $(WARN_CXXFLAGS) $(extra_cflags) $(extra_cxxflags) $(CONFIGURE_CXXFLAGS)
\r
123 -FINAL_NOTMUCH_LDFLAGS = $(LDFLAGS) -Lutil -lutil -Llib -lnotmuch $(AS_NEEDED_LDFLAGS) $(GMIME_LDFLAGS) $(TALLOC_LDFLAGS)
\r
124 +FINAL_NOTMUCH_LDFLAGS = $(LDFLAGS) -Lutil -lutil -Llib -lnotmuch $(AS_NEEDED_LDFLAGS) $(GMIME_LDFLAGS) $(TALLOC_LDFLAGS) $(ZLIB_LDFLAGS)
\r
125 FINAL_NOTMUCH_LINKER = CC
\r
126 ifneq ($(LINKER_RESOLVES_LIBRARY_DEPENDENCIES),1)
\r
127 FINAL_NOTMUCH_LDFLAGS += $(CONFIGURE_LDFLAGS)
\r
128 diff --git a/configure b/configure
\r
129 index 1d430b9..89bb3f3 100755
\r
132 @@ -340,6 +340,18 @@ else
\r
133 errors=$((errors + 1))
\r
136 +printf "Checking for zlib development files... "
\r
138 +if pkg-config --exists zlib; then
\r
141 + zlib_cflags=$(pkg-config --cflags zlib)
\r
142 + zlib_ldflags=$(pkg-config --libs zlib)
\r
145 + errors=$((errors + 1))
\r
148 printf "Checking for talloc development files... "
\r
149 if pkg-config --exists talloc; then
\r
151 @@ -519,11 +531,11 @@ case a simple command will install everything you need. For example:
\r
153 On Debian and similar systems:
\r
155 - sudo apt-get install libxapian-dev libgmime-2.6-dev libtalloc-dev
\r
156 + sudo apt-get install libxapian-dev libgmime-2.6-dev libtalloc-dev zlib1g-dev
\r
158 Or on Fedora and similar systems:
\r
160 - sudo yum install xapian-core-devel gmime-devel libtalloc-devel
\r
161 + sudo yum install xapian-core-devel gmime-devel libtalloc-devel zlib-devel
\r
163 On other systems, similar commands can be used, but the details of the
\r
164 package names may be different.
\r
165 @@ -844,6 +856,10 @@ XAPIAN_LDFLAGS = ${xapian_ldflags}
\r
166 GMIME_CFLAGS = ${gmime_cflags}
\r
167 GMIME_LDFLAGS = ${gmime_ldflags}
\r
169 +# Flags needed to compile and link against zlib
\r
170 +ZLIB_CFLAGS = ${zlib_cflags}
\r
171 +ZLIB_LDFLAGS = ${zlib_ldflags}
\r
173 # Flags needed to compile and link against talloc
\r
174 TALLOC_CFLAGS = ${talloc_cflags}
\r
175 TALLOC_LDFLAGS = ${talloc_ldflags}
\r
176 @@ -882,6 +898,7 @@ CONFIGURE_CFLAGS = -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS) \\
\r
177 -DUTIL_BYTE_ORDER=\$(UTIL_BYTE_ORDER)
\r
179 CONFIGURE_CXXFLAGS = -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS) \\
\r
180 + \$(ZLIB_CFLAGS) \\
\r
181 \$(TALLOC_CFLAGS) -DHAVE_VALGRIND=\$(HAVE_VALGRIND) \\
\r
182 \$(VALGRIND_CFLAGS) \$(XAPIAN_CXXFLAGS) \\
\r
183 -DHAVE_STRCASESTR=\$(HAVE_STRCASESTR) \\
\r
184 @@ -892,5 +909,5 @@ CONFIGURE_CXXFLAGS = -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS) \\
\r
185 -DHAVE_XAPIAN_COMPACT=\$(HAVE_XAPIAN_COMPACT) \\
\r
186 -DUTIL_BYTE_ORDER=\$(UTIL_BYTE_ORDER)
\r
188 -CONFIGURE_LDFLAGS = \$(GMIME_LDFLAGS) \$(TALLOC_LDFLAGS) \$(XAPIAN_LDFLAGS)
\r
189 +CONFIGURE_LDFLAGS = \$(GMIME_LDFLAGS) \$(TALLOC_LDFLAGS) \$(ZLIB_LDFLAGS) \$(XAPIAN_LDFLAGS)
\r
191 diff --git a/doc/man1/notmuch-dump.rst b/doc/man1/notmuch-dump.rst
\r
192 index 17d1da5..d94cb4f 100644
\r
193 --- a/doc/man1/notmuch-dump.rst
\r
194 +++ b/doc/man1/notmuch-dump.rst
\r
195 @@ -19,6 +19,9 @@ recreated from the messages themselves. The output of notmuch dump is
\r
196 therefore the only critical thing to backup (and much more friendly to
\r
197 incremental backup than the native database files.)
\r
200 + Compress the output in a format compatible with **gzip(1)**.
\r
202 ``--format=(sup|batch-tag)``
\r
203 Notmuch restore supports two plain text dump formats, both with one
\r
204 message-id per line, followed by a list of tags.
\r
205 diff --git a/notmuch-client.h b/notmuch-client.h
\r
206 index d110648..e1efbe0 100644
\r
207 --- a/notmuch-client.h
\r
208 +++ b/notmuch-client.h
\r
209 @@ -450,7 +450,9 @@ typedef enum dump_formats {
\r
211 notmuch_database_dump (notmuch_database_t *notmuch,
\r
212 const char *output_file_name,
\r
213 - const char *query_str, dump_format_t output_format);
\r
214 + const char *query_str,
\r
215 + dump_format_t output_format,
\r
216 + notmuch_bool_t gzip_output);
\r
218 #include "command-line-arguments.h"
\r
220 diff --git a/notmuch-dump.c b/notmuch-dump.c
\r
221 index 21702d7..128a37d 100644
\r
222 --- a/notmuch-dump.c
\r
223 +++ b/notmuch-dump.c
\r
224 @@ -21,10 +21,12 @@
\r
225 #include "notmuch-client.h"
\r
226 #include "hex-escape.h"
\r
227 #include "string-util.h"
\r
232 -database_dump_file (notmuch_database_t *notmuch, FILE *output,
\r
233 - const char *query_str, int output_format)
\r
234 +database_dump_file (notmuch_database_t *notmuch, gzFile output,
\r
235 + const char *query_str, int output_format)
\r
237 notmuch_query_t *query;
\r
238 notmuch_messages_t *messages;
\r
239 @@ -69,7 +71,7 @@ database_dump_file (notmuch_database_t *notmuch, FILE *output,
\r
242 if (output_format == DUMP_FORMAT_SUP) {
\r
243 - fprintf (output, "%s (", message_id);
\r
244 + gzprintf (output, "%s (", message_id);
\r
247 for (tags = notmuch_message_get_tags (message);
\r
248 @@ -78,12 +80,12 @@ database_dump_file (notmuch_database_t *notmuch, FILE *output,
\r
249 const char *tag_str = notmuch_tags_get (tags);
\r
252 - fputs (" ", output);
\r
253 + gzputs (output, " ");
\r
257 if (output_format == DUMP_FORMAT_SUP) {
\r
258 - fputs (tag_str, output);
\r
259 + gzputs (output, tag_str);
\r
261 if (hex_encode (notmuch, tag_str,
\r
262 &buffer, &buffer_size) != HEX_SUCCESS) {
\r
263 @@ -91,12 +93,12 @@ database_dump_file (notmuch_database_t *notmuch, FILE *output,
\r
265 return EXIT_FAILURE;
\r
267 - fprintf (output, "+%s", buffer);
\r
268 + gzprintf (output, "+%s", buffer);
\r
272 if (output_format == DUMP_FORMAT_SUP) {
\r
273 - fputs (")\n", output);
\r
274 + gzputs (output, ")\n");
\r
276 if (make_boolean_term (notmuch, "id", message_id,
\r
277 &buffer, &buffer_size)) {
\r
278 @@ -104,7 +106,7 @@ database_dump_file (notmuch_database_t *notmuch, FILE *output,
\r
279 message_id, strerror (errno));
\r
280 return EXIT_FAILURE;
\r
282 - fprintf (output, " -- %s\n", buffer);
\r
283 + gzprintf (output, " -- %s\n", buffer);
\r
286 notmuch_message_destroy (message);
\r
287 @@ -121,24 +123,37 @@ database_dump_file (notmuch_database_t *notmuch, FILE *output,
\r
289 notmuch_database_dump (notmuch_database_t *notmuch,
\r
290 const char *output_file_name,
\r
291 - const char *query_str, dump_format_t output_format)
\r
292 + const char *query_str,
\r
293 + dump_format_t output_format,
\r
294 + notmuch_bool_t gzip_output)
\r
296 - FILE *output = stdout;
\r
298 + const char *mode = gzip_output ? "w9" : "wT";
\r
302 - if (output_file_name) {
\r
303 - output = fopen (output_file_name, "w");
\r
304 - if (output == NULL) {
\r
305 - fprintf (stderr, "Error opening %s for writing: %s\n",
\r
306 - output_file_name, strerror (errno));
\r
307 - return EXIT_FAILURE;
\r
309 + if (output_file_name)
\r
310 + output = gzopen (output_file_name, mode);
\r
312 + output = gzdopen (fileno (stdout), mode);
\r
314 + if (output == NULL) {
\r
315 + fprintf (stderr, "Error opening %s for (gzip) writing: %s\n",
\r
316 + output_file_name || "stdout", strerror (errno));
\r
317 + return EXIT_FAILURE;
\r
320 ret = database_dump_file (notmuch, output, query_str, output_format);
\r
322 - if (output != stdout)
\r
324 + /* unlike stdio, zlib needs explicit flushing */
\r
325 + if (gzflush (output, Z_FINISH)) {
\r
326 + fprintf (stderr, "Error flushing output: %s\n",
\r
327 + gzerror (output, NULL));
\r
328 + return EXIT_FAILURE;
\r
331 + if (output_file_name)
\r
332 + gzclose_w (output);
\r
336 @@ -158,6 +173,7 @@ notmuch_dump_command (notmuch_config_t *config, int argc, char *argv[])
\r
339 int output_format = DUMP_FORMAT_BATCH_TAG;
\r
340 + notmuch_bool_t gzip_output = 0;
\r
342 notmuch_opt_desc_t options[] = {
\r
343 { NOTMUCH_OPT_KEYWORD, &output_format, "format", 'f',
\r
344 @@ -165,6 +181,7 @@ notmuch_dump_command (notmuch_config_t *config, int argc, char *argv[])
\r
345 { "batch-tag", DUMP_FORMAT_BATCH_TAG },
\r
347 { NOTMUCH_OPT_STRING, &output_file_name, "output", 'o', 0 },
\r
348 + { NOTMUCH_OPT_BOOLEAN, &gzip_output, "gzip", 'z', 0 },
\r
352 @@ -181,7 +198,7 @@ notmuch_dump_command (notmuch_config_t *config, int argc, char *argv[])
\r
355 ret = notmuch_database_dump (notmuch, output_file_name, query_str,
\r
357 + output_format, gzip_output);
\r
359 notmuch_database_destroy (notmuch);
\r
361 diff --git a/test/T240-dump-restore.sh b/test/T240-dump-restore.sh
\r
362 index 0004438..d79aca8 100755
\r
363 --- a/test/T240-dump-restore.sh
\r
364 +++ b/test/T240-dump-restore.sh
\r
365 @@ -68,6 +68,18 @@ test_begin_subtest "dump --output=outfile --"
\r
366 notmuch dump --output=dump-1-arg-dash.actual --
\r
367 test_expect_equal_file dump.expected dump-1-arg-dash.actual
\r
371 +test_begin_subtest "dump --gzip"
\r
372 +notmuch dump --gzip > dump-gzip.gz
\r
373 +gunzip dump-gzip.gz
\r
374 +test_expect_equal_file dump.expected dump-gzip
\r
376 +test_begin_subtest "dump --gzip --output=outfile"
\r
377 +notmuch dump --gzip --output=dump-gzip-outfile.gz
\r
378 +gunzip dump-gzip-outfile.gz
\r
379 +test_expect_equal_file dump.expected dump-gzip-outfile
\r
381 # Note, we assume all messages from cworth have a message-id
\r
382 # containing cworth.org
\r