[PATCH] VIM: Automatically refresh folder screen
[notmuch-archives.git] / 11 / 4ef66ad0fc3188a8e5df2f8c306f86bfae9a6e
1 Return-Path: <amdragon@mit.edu>\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 1C8FC431FBF\r
6         for <notmuch@notmuchmail.org>; Fri,  4 Apr 2014 15:05:57 -0700 (PDT)\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
8 X-Spam-Flag: NO\r
9 X-Spam-Score: -0.7\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5\r
12         tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled\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 g1n8XGRddU0C for <notmuch@notmuchmail.org>;\r
16         Fri,  4 Apr 2014 15:05:52 -0700 (PDT)\r
17 Received: from dmz-mailsec-scanner-5.mit.edu (dmz-mailsec-scanner-5.mit.edu\r
18         [18.7.68.34])\r
19         by olra.theworths.org (Postfix) with ESMTP id EDD00431FAF\r
20         for <notmuch@notmuchmail.org>; Fri,  4 Apr 2014 15:05:51 -0700 (PDT)\r
21 X-AuditID: 12074422-f79186d00000135a-f4-533f2cbfda6f\r
22 Received: from mailhub-auth-3.mit.edu ( [18.9.21.43])\r
23         (using TLS with cipher AES256-SHA (256/256 bits))\r
24         (Client did not present a certificate)\r
25         by dmz-mailsec-scanner-5.mit.edu (Symantec Messaging Gateway) with SMTP\r
26         id C1.19.04954.FBC2F335; Fri,  4 Apr 2014 18:05:51 -0400 (EDT)\r
27 Received: from outgoing.mit.edu (outgoing-auth-1.mit.edu [18.9.28.11])\r
28         by mailhub-auth-3.mit.edu (8.13.8/8.9.2) with ESMTP id s34M5ndx014052; \r
29         Fri, 4 Apr 2014 18:05:50 -0400\r
30 Received: from awakening.csail.mit.edu (awakening.csail.mit.edu [18.26.4.91])\r
31         (authenticated bits=0)\r
32         (User authenticated as amdragon@ATHENA.MIT.EDU)\r
33         by outgoing.mit.edu (8.13.8/8.12.4) with ESMTP id s34M5mqO017034\r
34         (version=TLSv1/SSLv3 cipher=DHE-RSA-AES128-SHA bits=128 verify=NOT);\r
35         Fri, 4 Apr 2014 18:05:49 -0400\r
36 Received: from amthrax by awakening.csail.mit.edu with local (Exim 4.80)\r
37         (envelope-from <amdragon@mit.edu>)\r
38         id 1WWCFA-0004Ho-10; Fri, 04 Apr 2014 18:05:48 -0400\r
39 Date: Fri, 4 Apr 2014 18:05:47 -0400\r
40 From: Austin Clements <amdragon@MIT.EDU>\r
41 To: David Bremner <david@tethera.net>\r
42 Subject: Re: [Patch v6 1/6] dump: support gzipped and atomic output\r
43 Message-ID: <20140404220547.GB15472@mit.edu>\r
44 References: <1396554083-3892-1-git-send-email-david@tethera.net>\r
45         <1396554083-3892-2-git-send-email-david@tethera.net>\r
46 MIME-Version: 1.0\r
47 Content-Type: text/plain; charset=us-ascii\r
48 Content-Disposition: inline\r
49 In-Reply-To: <1396554083-3892-2-git-send-email-david@tethera.net>\r
50 User-Agent: Mutt/1.5.21 (2010-09-15)\r
51 X-Brightmail-Tracker:\r
52  H4sIAAAAAAAAA+NgFmpileLIzCtJLcpLzFFi42IR4hTV1t2vYx9scHa+hMWN1m5Gi+s3ZzI7\r
53         MHk8W3WL2WPLoffMAUxRXDYpqTmZZalF+nYJXBm7/kxlL1hWUPHkvHMD472wLkZODgkBE4nz\r
54         z7YzQdhiEhfurWfrYuTiEBKYzSRx7/g9RghnA6PEyweLoZxTTBITem+xQjhLGCUezz/G3MXI\r
55         wcEioCIx56YyyCg2AQ2JbfuXM4LYIgKqEle3TWYDsZkFpCW+/W4GWycs4Czx6dxpZhCbV0BH\r
56         4u+ra2A1QgLlEqdefGCHiAtKnJz5hAWiV0vixr+XTCCrQOYs/8cBEuYUcJR4/6YBbJUo0AVT\r
57         Tm5jm8AoNAtJ9ywk3bMQuhcwMq9ilE3JrdLNTczMKU5N1i1OTszLSy3SNdXLzSzRS00p3cQI\r
58         Cmp2F6UdjD8PKh1iFOBgVOLh7dhhFyzEmlhWXJl7iFGSg0lJlLdLwT5YiC8pP6UyI7E4I76o\r
59         NCe1+BCjBAezkgivjCpQjjclsbIqtSgfJiXNwaIkzvvW2ipYSCA9sSQ1OzW1ILUIJivDwaEk\r
60         wbtFG6hRsCg1PbUiLTOnBCHNxMEJMpwHaPhakBre4oLE3OLMdIj8KUZFKXHeLVpACQGQREZp\r
61         HlwvLOm8YhQHekWY9wRIOw8wYcF1vwIazAQ0uCHMDmRwSSJCSqqB0ZB9/8LvkdnvbQ+xKXz3\r
62         OTuRb07THAXe0k3iW87b373Z/Wj9W+u9x17+2Np8i5dPryHodffZO2lcHOvKQtJmfti0ZNrn\r
63         79+bcmVtVA/7MF33urf09kmpoNrzDleir/u+LbI/PPNgvFmdwaEn5z9va7ZNesuld3yxkPXX\r
64         wrf2Tge/HPZ3b37WXq/EUpyRaKjFXFScCACNihoBFQMAAA==\r
65 Cc: notmuch@notmuchmail.org\r
66 X-BeenThere: notmuch@notmuchmail.org\r
67 X-Mailman-Version: 2.1.13\r
68 Precedence: list\r
69 List-Id: "Use and development of the notmuch mail system."\r
70         <notmuch.notmuchmail.org>\r
71 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
72         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
73 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
74 List-Post: <mailto:notmuch@notmuchmail.org>\r
75 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
76 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
77         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
78 X-List-Received-Date: Fri, 04 Apr 2014 22:05:57 -0000\r
79 \r
80 Quoth David Bremner on Apr 03 at  4:41 pm:\r
81 > The main goal is to support gzipped output for future internal\r
82 > calls (e.g. from notmuch-new) to notmuch_database_dump.\r
83\r
84 > The additional dependency is not very heavy since xapian already pulls\r
85 > in zlib.\r
86\r
87 > We want the dump to be "atomic", in the sense that after running the\r
88 > dump file is either present and complete, or not present.  This avoids\r
89 > certain classes of mishaps involving overwriting a good backup with a\r
90 > bad or partial one.\r
91 > ---\r
92 >  INSTALL                   | 20 ++++++++--\r
93 >  Makefile.local            |  2 +-\r
94 >  configure                 | 28 ++++++++++++--\r
95 >  doc/man1/notmuch-dump.rst |  3 ++\r
96 >  notmuch-client.h          |  4 +-\r
97 >  notmuch-dump.c            | 95 +++++++++++++++++++++++++++++++++++++----------\r
98 >  test/T240-dump-restore.sh | 12 ++++++\r
99 >  7 files changed, 136 insertions(+), 28 deletions(-)\r
100\r
101 > diff --git a/INSTALL b/INSTALL\r
102 > index 690b0ef..b543c50 100644\r
103 > --- a/INSTALL\r
104 > +++ b/INSTALL\r
105 > @@ -20,8 +20,8 @@ configure stage.\r
106 >  \r
107 >  Dependencies\r
108 >  ------------\r
109 > -Notmuch depends on three libraries: Xapian, GMime 2.4 or 2.6, and\r
110 > -Talloc which are each described below:\r
111 > +Notmuch depends on four libraries: Xapian, GMime 2.4 or 2.6,\r
112 > +Talloc, and zlib which are each described below:\r
113 >  \r
114 >       Xapian\r
115 >       ------\r
116 > @@ -60,6 +60,18 @@ Talloc which are each described below:\r
117 >  \r
118 >       Talloc is available from http://talloc.samba.org/\r
119 >  \r
120 > +     zlib\r
121 > +     ----\r
122 > +\r
123 > +     zlib is an extremely popular compression library. It is used\r
124 > +     by Xapian, so if you installed that you will already have\r
125 > +     zlib. You may need to install the zlib headers separately.\r
126 > +\r
127 > +     Notmuch needs the transparent write feature of zlib introduced\r
128 > +     in version 1.2.5.2 (Dec. 2011).\r
129 > +\r
130 > +     zlib is available from http://zlib.net\r
131 > +\r
132 >  Building Documentation\r
133 >  ----------------------\r
134 >  \r
135 > @@ -79,11 +91,11 @@ dependencies with a simple simple command line. For example:\r
136 >  \r
137 >    For Debian and similar:\r
138 >  \r
139 > -        sudo apt-get install libxapian-dev libgmime-2.6-dev libtalloc-dev python-sphinx\r
140 > +        sudo apt-get install libxapian-dev libgmime-2.6-dev libtalloc-dev zlib1g-dev python-sphinx\r
141 >  \r
142 >    For Fedora and similar:\r
143 >  \r
144 > -     sudo yum install xapian-core-devel gmime-devel libtalloc-devel python-sphinx\r
145 > +     sudo yum install xapian-core-devel gmime-devel libtalloc-devel zlib-devel python-sphinx\r
146 >  \r
147 >  On other systems, a similar command can be used, but the details of\r
148 >  the package names may be different.\r
149 > diff --git a/Makefile.local b/Makefile.local\r
150 > index cb7b106..e5a20a7 100644\r
151 > --- a/Makefile.local\r
152 > +++ b/Makefile.local\r
153 > @@ -41,7 +41,7 @@ PV_FILE=bindings/python/notmuch/version.py\r
154 >  # Smash together user's values with our extra values\r
155 >  FINAL_CFLAGS = -DNOTMUCH_VERSION=$(VERSION) $(CPPFLAGS) $(CFLAGS) $(WARN_CFLAGS) $(extra_cflags) $(CONFIGURE_CFLAGS)\r
156 >  FINAL_CXXFLAGS = $(CPPFLAGS) $(CXXFLAGS) $(WARN_CXXFLAGS) $(extra_cflags) $(extra_cxxflags) $(CONFIGURE_CXXFLAGS)\r
157 > -FINAL_NOTMUCH_LDFLAGS = $(LDFLAGS) -Lutil -lutil -Llib -lnotmuch $(AS_NEEDED_LDFLAGS) $(GMIME_LDFLAGS) $(TALLOC_LDFLAGS)\r
158 > +FINAL_NOTMUCH_LDFLAGS = $(LDFLAGS) -Lutil -lutil -Llib -lnotmuch $(AS_NEEDED_LDFLAGS) $(GMIME_LDFLAGS) $(TALLOC_LDFLAGS) $(ZLIB_LDFLAGS)\r
159 >  FINAL_NOTMUCH_LINKER = CC\r
160 >  ifneq ($(LINKER_RESOLVES_LIBRARY_DEPENDENCIES),1)\r
161 >  FINAL_NOTMUCH_LDFLAGS += $(CONFIGURE_LDFLAGS)\r
162 > diff --git a/configure b/configure\r
163 > index 1d430b9..1d624f7 100755\r
164 > --- a/configure\r
165 > +++ b/configure\r
166 > @@ -340,6 +340,18 @@ else\r
167 >      errors=$((errors + 1))\r
168 >  fi\r
169 >  \r
170 > +printf "Checking for zlib (>= 1.2.5.2)... "\r
171 > +have_zlib=0\r
172 > +if pkg-config --atleast-version=1.2.5.2 zlib; then\r
173 > +    printf "Yes.\n"\r
174 > +    have_zlib=1\r
175 > +    zlib_cflags=$(pkg-config --cflags zlib)\r
176 > +    zlib_ldflags=$(pkg-config --libs zlib)\r
177 > +else\r
178 > +    printf "No.\n"\r
179 > +    errors=$((errors + 1))\r
180 > +fi\r
181 > +\r
182 >  printf "Checking for talloc development files... "\r
183 >  if pkg-config --exists talloc; then\r
184 >      printf "Yes.\n"\r
185 > @@ -496,6 +508,11 @@ EOF\r
186 >       echo "  Xapian library (including development files such as headers)"\r
187 >       echo "  http://xapian.org/"\r
188 >      fi\r
189 > +    if [ $have_zlib -eq 0 ]; then\r
190 > +     echo "  zlib library (including development files such as headers)"\r
191 > +     echo "  http://zlib.net/"\r
192 > +     echo\r
193 > +    fi\r
194 >      if [ $have_gmime -eq 0 ]; then\r
195 >       echo "  Either GMime 2.4 library" $GMIME_24_VERSION_CTR "or GMime 2.6 library" $GMIME_26_VERSION_CTR\r
196 >       echo "  (including development files such as headers)"\r
197 > @@ -519,11 +536,11 @@ case a simple command will install everything you need. For example:\r
198 >  \r
199 >  On Debian and similar systems:\r
200 >  \r
201 > -     sudo apt-get install libxapian-dev libgmime-2.6-dev libtalloc-dev\r
202 > +     sudo apt-get install libxapian-dev libgmime-2.6-dev libtalloc-dev zlib1g-dev\r
203 >  \r
204 >  Or on Fedora and similar systems:\r
205 >  \r
206 > -     sudo yum install xapian-core-devel gmime-devel libtalloc-devel\r
207 > +     sudo yum install xapian-core-devel gmime-devel libtalloc-devel zlib-devel\r
208 >  \r
209 >  On other systems, similar commands can be used, but the details of the\r
210 >  package names may be different.\r
211 > @@ -844,6 +861,10 @@ XAPIAN_LDFLAGS = ${xapian_ldflags}\r
212 >  GMIME_CFLAGS = ${gmime_cflags}\r
213 >  GMIME_LDFLAGS = ${gmime_ldflags}\r
214 >  \r
215 > +# Flags needed to compile and link against zlib\r
216 > +ZLIB_CFLAGS = ${zlib_cflags}\r
217 > +ZLIB_LDFLAGS = ${zlib_ldflags}\r
218 > +\r
219 >  # Flags needed to compile and link against talloc\r
220 >  TALLOC_CFLAGS = ${talloc_cflags}\r
221 >  TALLOC_LDFLAGS = ${talloc_ldflags}\r
222 > @@ -882,6 +903,7 @@ CONFIGURE_CFLAGS = -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS)      \\\r
223 >                  -DUTIL_BYTE_ORDER=\$(UTIL_BYTE_ORDER)\r
224 >  \r
225 >  CONFIGURE_CXXFLAGS = -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS)    \\\r
226 > +                  \$(ZLIB_CFLAGS)                                     \\\r
227 >                    \$(TALLOC_CFLAGS) -DHAVE_VALGRIND=\$(HAVE_VALGRIND) \\\r
228 >                    \$(VALGRIND_CFLAGS) \$(XAPIAN_CXXFLAGS)             \\\r
229 >                    -DHAVE_STRCASESTR=\$(HAVE_STRCASESTR)               \\\r
230 > @@ -892,5 +914,5 @@ CONFIGURE_CXXFLAGS = -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS)    \\\r
231 >                    -DHAVE_XAPIAN_COMPACT=\$(HAVE_XAPIAN_COMPACT)       \\\r
232 >                    -DUTIL_BYTE_ORDER=\$(UTIL_BYTE_ORDER)\r
233 >  \r
234 > -CONFIGURE_LDFLAGS =  \$(GMIME_LDFLAGS) \$(TALLOC_LDFLAGS) \$(XAPIAN_LDFLAGS)\r
235 > +CONFIGURE_LDFLAGS =  \$(GMIME_LDFLAGS) \$(TALLOC_LDFLAGS) \$(ZLIB_LDFLAGS) \$(XAPIAN_LDFLAGS)\r
236 >  EOF\r
237 > diff --git a/doc/man1/notmuch-dump.rst b/doc/man1/notmuch-dump.rst\r
238 > index 17d1da5..d94cb4f 100644\r
239 > --- a/doc/man1/notmuch-dump.rst\r
240 > +++ b/doc/man1/notmuch-dump.rst\r
241 > @@ -19,6 +19,9 @@ recreated from the messages themselves. The output of notmuch dump is\r
242 >  therefore the only critical thing to backup (and much more friendly to\r
243 >  incremental backup than the native database files.)\r
244 >  \r
245 > +``--gzip``\r
246 > +    Compress the output in a format compatible with **gzip(1)**.\r
247 > +\r
248 >  ``--format=(sup|batch-tag)``\r
249 >      Notmuch restore supports two plain text dump formats, both with one\r
250 >      message-id per line, followed by a list of tags.\r
251 > diff --git a/notmuch-client.h b/notmuch-client.h\r
252 > index d110648..e1efbe0 100644\r
253 > --- a/notmuch-client.h\r
254 > +++ b/notmuch-client.h\r
255 > @@ -450,7 +450,9 @@ typedef enum dump_formats {\r
256 >  int\r
257 >  notmuch_database_dump (notmuch_database_t *notmuch,\r
258 >                      const char *output_file_name,\r
259 > -                    const char *query_str, dump_format_t output_format);\r
260 > +                    const char *query_str,\r
261 > +                    dump_format_t output_format,\r
262 > +                    notmuch_bool_t gzip_output);\r
263 >  \r
264 >  #include "command-line-arguments.h"\r
265 >  #endif\r
266 > diff --git a/notmuch-dump.c b/notmuch-dump.c\r
267 > index 21702d7..2a7252a 100644\r
268 > --- a/notmuch-dump.c\r
269 > +++ b/notmuch-dump.c\r
270 > @@ -21,9 +21,11 @@\r
271 >  #include "notmuch-client.h"\r
272 >  #include "hex-escape.h"\r
273 >  #include "string-util.h"\r
274 > +#include <zlib.h>\r
275 > +\r
276 >  \r
277 >  static int\r
278 > -database_dump_file (notmuch_database_t *notmuch, FILE *output,\r
279 > +database_dump_file (notmuch_database_t *notmuch, gzFile output,\r
280 >                   const char *query_str, int output_format)\r
281 >  {\r
282 >      notmuch_query_t *query;\r
283 > @@ -69,7 +71,7 @@ database_dump_file (notmuch_database_t *notmuch, FILE *output,\r
284 >       }\r
285 >  \r
286 >       if (output_format == DUMP_FORMAT_SUP) {\r
287 > -         fprintf (output, "%s (", message_id);\r
288 > +         gzprintf (output, "%s (", message_id);\r
289 >       }\r
290 >  \r
291 >       for (tags = notmuch_message_get_tags (message);\r
292 > @@ -78,12 +80,12 @@ database_dump_file (notmuch_database_t *notmuch, FILE *output,\r
293 >           const char *tag_str = notmuch_tags_get (tags);\r
294 >  \r
295 >           if (! first)\r
296 > -             fputs (" ", output);\r
297 > +             gzputs (output, " ");\r
298 >  \r
299 >           first = 0;\r
300 >  \r
301 >           if (output_format == DUMP_FORMAT_SUP) {\r
302 > -             fputs (tag_str, output);\r
303 > +             gzputs (output, tag_str);\r
304 >           } else {\r
305 >               if (hex_encode (notmuch, tag_str,\r
306 >                               &buffer, &buffer_size) != HEX_SUCCESS) {\r
307 > @@ -91,12 +93,12 @@ database_dump_file (notmuch_database_t *notmuch, FILE *output,\r
308 >                            tag_str);\r
309 >                   return EXIT_FAILURE;\r
310 >               }\r
311 > -             fprintf (output, "+%s", buffer);\r
312 > +             gzprintf (output, "+%s", buffer);\r
313 >           }\r
314 >       }\r
315 >  \r
316 >       if (output_format == DUMP_FORMAT_SUP) {\r
317 > -         fputs (")\n", output);\r
318 > +         gzputs (output, ")\n");\r
319 >       } else {\r
320 >           if (make_boolean_term (notmuch, "id", message_id,\r
321 >                                  &buffer, &buffer_size)) {\r
322 > @@ -104,7 +106,7 @@ database_dump_file (notmuch_database_t *notmuch, FILE *output,\r
323 >                            message_id, strerror (errno));\r
324 >                   return EXIT_FAILURE;\r
325 >           }\r
326 > -         fprintf (output, " -- %s\n", buffer);\r
327 > +         gzprintf (output, " -- %s\n", buffer);\r
328 >       }\r
329 >  \r
330 >       notmuch_message_destroy (message);\r
331 > @@ -121,24 +123,77 @@ database_dump_file (notmuch_database_t *notmuch, FILE *output,\r
332 >  int\r
333 >  notmuch_database_dump (notmuch_database_t *notmuch,\r
334 >                      const char *output_file_name,\r
335 > -                    const char *query_str, dump_format_t output_format)\r
336 > +                    const char *query_str,\r
337 > +                    dump_format_t output_format,\r
338 > +                    notmuch_bool_t gzip_output)\r
339 >  {\r
340 > -    FILE *output = stdout;\r
341 > -    int ret;\r
342 > +    gzFile output;\r
343 \r
344 This should to gzclose_w output on all error paths.  The easiest way\r
345 to do that it probably to\r
346   gzFile output = NULL;\r
347 here and ...\r
348 \r
349 > +    const char *mode = gzip_output ? "w9" : "wT";\r
350 > +    const char *name_for_error = output_file_name ? output_file_name : "stdout";\r
351 > +\r
352 > +    char *tempname = NULL;\r
353 > +    int outfd = -1;\r
354 > +\r
355 > +    int ret = -1;\r
356 >  \r
357 >      if (output_file_name) {\r
358 > -     output = fopen (output_file_name, "w");\r
359 > -     if (output == NULL) {\r
360 > -         fprintf (stderr, "Error opening %s for writing: %s\n",\r
361 > -                  output_file_name, strerror (errno));\r
362 > -         return EXIT_FAILURE;\r
363 > -     }\r
364 > +     tempname = talloc_asprintf (notmuch, "%s.XXXXXX", output_file_name);\r
365 > +     outfd = mkstemp (tempname);\r
366 > +    } else {\r
367 > +     outfd = dup (STDOUT_FILENO);\r
368 > +    }\r
369 > +\r
370 > +    if (outfd < 0) {\r
371 > +     fprintf (stderr, "Bad output file %s\n", name_for_error);\r
372 > +     goto DONE;\r
373 > +    }\r
374 > +\r
375 > +    output = gzdopen (outfd, mode);\r
376 > +\r
377 > +    if (output == NULL) {\r
378 > +     fprintf (stderr, "Error opening %s for (gzip) writing: %s\n",\r
379 > +              name_for_error, strerror (errno));\r
380 > +     if (close (outfd))\r
381 > +         fprintf (stderr, "Error closing %s during shutdown: %s\n",\r
382 > +              name_for_error, strerror (errno));\r
383 > +     goto DONE;\r
384 >      }\r
385 >  \r
386 >      ret = database_dump_file (notmuch, output, query_str, output_format);\r
387 > +    if (ret) goto DONE;\r
388 >  \r
389 > -    if (output != stdout)\r
390 > -     fclose (output);\r
391 > +    ret = gzflush (output, Z_FINISH);\r
392 > +    if (ret) {\r
393 > +     fprintf (stderr, "Error flushing output: %s\n", gzerror (output, NULL));\r
394 > +     goto DONE;\r
395 > +    }\r
396 > +\r
397 > +    if (output_file_name) {\r
398 > +     ret = fdatasync (outfd);\r
399 > +     if (ret) {\r
400 > +         fprintf (stderr, "Error syncing %s to disk: %s\n",\r
401 > +                  name_for_error, strerror (errno));\r
402 > +         goto DONE;\r
403 > +     }\r
404 > +    }\r
405 > +\r
406 > +    if (gzclose_w (output) != Z_OK) {\r
407 > +     ret = EXIT_FAILURE;\r
408 > +     goto DONE;\r
409 > +    }\r
410 \r
411 ... output = NULL; here, and ...\r
412 \r
413 > +\r
414 > +    if (output_file_name) {\r
415 > +     ret = rename (tempname, output_file_name);\r
416 > +     if (ret) {\r
417 > +         fprintf (stderr, "Error renaming %s to %s: %s\n",\r
418 > +                  tempname, output_file_name, strerror (errno));\r
419 > +         goto DONE;\r
420 > +     }\r
421 > +\r
422 > +    }\r
423 > + DONE:\r
424 \r
425 ...\r
426 if (output)\r
427   gzclose_w (output);\r
428 here.\r
429 \r
430 > +    if (ret != EXIT_SUCCESS && output_file_name)\r
431 > +     (void) unlink (tempname);\r
432 >  \r
433 >      return ret;\r
434 >  }\r
435 > @@ -158,6 +213,7 @@ notmuch_dump_command (notmuch_config_t *config, int argc, char *argv[])\r
436 >      int opt_index;\r
437 >  \r
438 >      int output_format = DUMP_FORMAT_BATCH_TAG;\r
439 > +    notmuch_bool_t gzip_output = 0;\r
440 >  \r
441 >      notmuch_opt_desc_t options[] = {\r
442 >       { NOTMUCH_OPT_KEYWORD, &output_format, "format", 'f',\r
443 > @@ -165,6 +221,7 @@ notmuch_dump_command (notmuch_config_t *config, int argc, char *argv[])\r
444 >                                 { "batch-tag", DUMP_FORMAT_BATCH_TAG },\r
445 >                                 { 0, 0 } } },\r
446 >       { NOTMUCH_OPT_STRING, &output_file_name, "output", 'o', 0  },\r
447 > +     { NOTMUCH_OPT_BOOLEAN, &gzip_output, "gzip", 'z', 0 },\r
448 >       { 0, 0, 0, 0, 0 }\r
449 >      };\r
450 >  \r
451 > @@ -181,7 +238,7 @@ notmuch_dump_command (notmuch_config_t *config, int argc, char *argv[])\r
452 >      }\r
453 >  \r
454 >      ret = notmuch_database_dump (notmuch, output_file_name, query_str,\r
455 > -                              output_format);\r
456 > +                              output_format, gzip_output);\r
457 >  \r
458 >      notmuch_database_destroy (notmuch);\r
459 >  \r
460 > diff --git a/test/T240-dump-restore.sh b/test/T240-dump-restore.sh\r
461 > index 0004438..d79aca8 100755\r
462 > --- a/test/T240-dump-restore.sh\r
463 > +++ b/test/T240-dump-restore.sh\r
464 > @@ -68,6 +68,18 @@ test_begin_subtest "dump --output=outfile --"\r
465 >  notmuch dump --output=dump-1-arg-dash.actual --\r
466 >  test_expect_equal_file dump.expected dump-1-arg-dash.actual\r
467 >  \r
468 > +# gzipped output\r
469 > +\r
470 > +test_begin_subtest "dump --gzip"\r
471 > +notmuch dump --gzip > dump-gzip.gz\r
472 > +gunzip dump-gzip.gz\r
473 > +test_expect_equal_file dump.expected dump-gzip\r
474 > +\r
475 > +test_begin_subtest "dump --gzip --output=outfile"\r
476 > +notmuch dump --gzip --output=dump-gzip-outfile.gz\r
477 > +gunzip dump-gzip-outfile.gz\r
478 > +test_expect_equal_file dump.expected dump-gzip-outfile\r
479 > +\r
480 >  # Note, we assume all messages from cworth have a message-id\r
481 >  # containing cworth.org\r
482 >  \r