1 Return-Path: <bremner@tesseract.cs.unb.ca>
\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 arlo.cworth.org (Postfix) with ESMTP id C4ABD6DE190D
\r
6 for <notmuch@notmuchmail.org>; Fri, 14 Aug 2015 09:49:31 -0700 (PDT)
\r
7 X-Virus-Scanned: Debian amavisd-new at cworth.org
\r
11 X-Spam-Status: No, score=0.134 tagged_above=-999 required=5 tests=[AWL=0.124,
\r
12 T_HEADER_FROM_DIFFERENT_DOMAINS=0.01] autolearn=disabled
\r
13 Received: from arlo.cworth.org ([127.0.0.1])
\r
14 by localhost (arlo.cworth.org [127.0.0.1]) (amavisd-new, port 10024)
\r
15 with ESMTP id XichQvwJyqfN for <notmuch@notmuchmail.org>;
\r
16 Fri, 14 Aug 2015 09:49:30 -0700 (PDT)
\r
17 Received: from gitolite.debian.net (gitolite.debian.net [87.98.215.224])
\r
18 by arlo.cworth.org (Postfix) with ESMTPS id F099F6DE18FD
\r
19 for <notmuch@notmuchmail.org>; Fri, 14 Aug 2015 09:49:29 -0700 (PDT)
\r
20 Received: from remotemail by gitolite.debian.net with local (Exim 4.80)
\r
21 (envelope-from <bremner@tesseract.cs.unb.ca>)
\r
22 id 1ZQI9v-0003eC-OJ; Fri, 14 Aug 2015 16:48:47 +0000
\r
23 Received: (nullmailer pid 15758 invoked by uid 1000); Fri, 14 Aug 2015
\r
25 From: David Bremner <david@tethera.net>
\r
26 To: notmuch@notmuchmail.org
\r
27 Subject: [PATCH 4/5] cli: add global option "--uuid"
\r
28 Date: Fri, 14 Aug 2015 18:47:57 +0200
\r
29 Message-Id: <1439570878-15165-5-git-send-email-david@tethera.net>
\r
30 X-Mailer: git-send-email 2.5.0
\r
31 In-Reply-To: <1439570878-15165-1-git-send-email-david@tethera.net>
\r
32 References: <1439570878-15165-1-git-send-email-david@tethera.net>
\r
33 X-BeenThere: notmuch@notmuchmail.org
\r
34 X-Mailman-Version: 2.1.18
\r
36 List-Id: "Use and development of the notmuch mail system."
\r
37 <notmuch.notmuchmail.org>
\r
38 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,
\r
39 <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>
\r
40 List-Archive: <http://notmuchmail.org/pipermail/notmuch/>
\r
41 List-Post: <mailto:notmuch@notmuchmail.org>
\r
42 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>
\r
43 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,
\r
44 <mailto:notmuch-request@notmuchmail.org?subject=subscribe>
\r
45 X-List-Received-Date: Fri, 14 Aug 2015 16:49:31 -0000
\r
47 The function notmuch_exit_if_unmatched_db_uuid is split from
\r
48 notmuch_process_shared_options because it needs an open notmuch
\r
51 There are two exceptional cases in uuid handling.
\r
53 1) notmuch config and notmuch setup don't currently open the database,
\r
54 so it doesn't make sense to check the UUID.
\r
56 2) notmuch compact opens the database inside the library, so we either
\r
57 need to open the database just to check uuid, or change the API.
\r
59 doc/man1/notmuch.rst | 11 +++++++++--
\r
60 notmuch-client.h | 4 ++++
\r
61 notmuch-compact.c | 5 +++++
\r
62 notmuch-config.c | 4 ++++
\r
63 notmuch-count.c | 2 ++
\r
64 notmuch-dump.c | 2 ++
\r
65 notmuch-insert.c | 2 ++
\r
66 notmuch-new.c | 3 ++-
\r
67 notmuch-reply.c | 2 ++
\r
68 notmuch-restore.c | 2 ++
\r
69 notmuch-search.c | 2 ++
\r
70 notmuch-setup.c | 4 ++++
\r
71 notmuch-show.c | 2 ++
\r
72 notmuch-tag.c | 2 ++
\r
73 notmuch.c | 18 ++++++++++++++++++
\r
74 test/T570-revision-tracking.sh | 27 +++++++++++++++++++++++++++
\r
75 test/random-corpus.c | 2 ++
\r
76 17 files changed, 91 insertions(+), 3 deletions(-)
\r
78 diff --git a/doc/man1/notmuch.rst b/doc/man1/notmuch.rst
\r
79 index 0401c91..3acfbdb 100644
\r
80 --- a/doc/man1/notmuch.rst
\r
81 +++ b/doc/man1/notmuch.rst
\r
82 @@ -51,9 +51,16 @@ Supported global options for ``notmuch`` include
\r
83 Specify the configuration file to use. This overrides any
\r
84 configuration file specified by ${NOTMUCH\_CONFIG}.
\r
87 + Enforce that the database UUID (a unique identifier which
\r
88 + persists until e.g. the database is compacted)
\r
89 + is HEX; exit with an error if it is not. This is useful to
\r
90 + detect rollover in modification counts on messages. You can
\r
91 + find this UUID using e.g. ``notmuch count --lastmod``
\r
93 All global options except ``--config`` can also be specified after the
\r
94 -command. For example, ``notmuch subcommand --version`` is equivalent to
\r
95 -``notmuch --version subcommand``.
\r
96 +command. For example, ``notmuch subcommand --uuid=HEX`` is
\r
97 +equivalent to ``notmuch --uuid=HEX subcommand``.
\r
101 diff --git a/notmuch-client.h b/notmuch-client.h
\r
102 index 78680aa..4a4f86c 100644
\r
103 --- a/notmuch-client.h
\r
104 +++ b/notmuch-client.h
\r
105 @@ -466,7 +466,11 @@ notmuch_database_dump (notmuch_database_t *notmuch,
\r
106 notmuch_bool_t gzip_output);
\r
108 #include "command-line-arguments.h"
\r
110 +extern char *notmuch_requested_db_uuid;
\r
111 extern const notmuch_opt_desc_t notmuch_shared_options [];
\r
112 +void notmuch_exit_if_unmatched_db_uuid (notmuch_database_t *notmuch);
\r
114 void notmuch_process_shared_options (const char* subcommand_name);
\r
115 int notmuch_minimal_options (const char* subcommand_name,
\r
116 int argc, char **argv);
\r
117 diff --git a/notmuch-compact.c b/notmuch-compact.c
\r
118 index 5be551d..9373721 100644
\r
119 --- a/notmuch-compact.c
\r
120 +++ b/notmuch-compact.c
\r
121 @@ -46,6 +46,11 @@ notmuch_compact_command (notmuch_config_t *config, int argc, char *argv[])
\r
123 return EXIT_FAILURE;
\r
125 + if (notmuch_requested_db_uuid) {
\r
126 + fprintf (stderr, "Error: --uuid not implemented for compact\n");
\r
127 + return EXIT_FAILURE;
\r
130 notmuch_process_shared_options (argv[0]);
\r
133 diff --git a/notmuch-config.c b/notmuch-config.c
\r
134 index 9348278..d252bb2 100644
\r
135 --- a/notmuch-config.c
\r
136 +++ b/notmuch-config.c
\r
137 @@ -878,6 +878,10 @@ notmuch_config_command (notmuch_config_t *config, int argc, char *argv[])
\r
139 return EXIT_FAILURE;
\r
141 + if (notmuch_requested_db_uuid)
\r
142 + fprintf (stderr, "Warning: ignoring --uuid=%s\n",
\r
143 + notmuch_requested_db_uuid);
\r
145 /* skip at least subcommand argument */
\r
148 diff --git a/notmuch-count.c b/notmuch-count.c
\r
149 index 182710a..f26e726 100644
\r
150 --- a/notmuch-count.c
\r
151 +++ b/notmuch-count.c
\r
152 @@ -189,6 +189,8 @@ notmuch_count_command (notmuch_config_t *config, int argc, char *argv[])
\r
153 NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
\r
154 return EXIT_FAILURE;
\r
156 + notmuch_exit_if_unmatched_db_uuid (notmuch);
\r
158 query_str = query_string_from_args (config, argc-opt_index, argv+opt_index);
\r
159 if (query_str == NULL) {
\r
160 fprintf (stderr, "Out of memory.\n");
\r
161 diff --git a/notmuch-dump.c b/notmuch-dump.c
\r
162 index fab22bd..24fc2f2 100644
\r
163 --- a/notmuch-dump.c
\r
164 +++ b/notmuch-dump.c
\r
165 @@ -215,6 +215,8 @@ notmuch_dump_command (notmuch_config_t *config, int argc, char *argv[])
\r
166 NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much))
\r
167 return EXIT_FAILURE;
\r
169 + notmuch_exit_if_unmatched_db_uuid (notmuch);
\r
171 char *output_file_name = NULL;
\r
174 diff --git a/notmuch-insert.c b/notmuch-insert.c
\r
175 index c277d62..5205c17 100644
\r
176 --- a/notmuch-insert.c
\r
177 +++ b/notmuch-insert.c
\r
178 @@ -536,6 +536,8 @@ notmuch_insert_command (notmuch_config_t *config, int argc, char *argv[])
\r
179 NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much))
\r
180 return EXIT_FAILURE;
\r
182 + notmuch_exit_if_unmatched_db_uuid (notmuch);
\r
184 /* Write the message to the Maildir new directory. */
\r
185 newpath = maildir_write_new (config, STDIN_FILENO, maildir);
\r
187 diff --git a/notmuch-new.c b/notmuch-new.c
\r
188 index ee786a3..514e06a 100644
\r
189 --- a/notmuch-new.c
\r
190 +++ b/notmuch-new.c
\r
191 @@ -1009,10 +1009,11 @@ notmuch_new_command (notmuch_config_t *config, int argc, char *argv[])
\r
192 fputs (status_string, stderr);
\r
193 free (status_string);
\r
196 return EXIT_FAILURE;
\r
199 + notmuch_exit_if_unmatched_db_uuid (notmuch);
\r
201 if (notmuch_database_needs_upgrade (notmuch)) {
\r
202 time_t now = time (NULL);
\r
203 struct tm *gm_time = gmtime (&now);
\r
204 diff --git a/notmuch-reply.c b/notmuch-reply.c
\r
205 index 4464741..7c5c28f 100644
\r
206 --- a/notmuch-reply.c
\r
207 +++ b/notmuch-reply.c
\r
208 @@ -831,6 +831,8 @@ notmuch_reply_command (notmuch_config_t *config, int argc, char *argv[])
\r
209 NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
\r
210 return EXIT_FAILURE;
\r
212 + notmuch_exit_if_unmatched_db_uuid (notmuch);
\r
214 query = notmuch_query_create (notmuch, query_string);
\r
215 if (query == NULL) {
\r
216 fprintf (stderr, "Out of memory\n");
\r
217 diff --git a/notmuch-restore.c b/notmuch-restore.c
\r
218 index 2a534dc..9abc64f 100644
\r
219 --- a/notmuch-restore.c
\r
220 +++ b/notmuch-restore.c
\r
221 @@ -165,6 +165,8 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[])
\r
224 notmuch_process_shared_options (argv[0]);
\r
225 + notmuch_exit_if_unmatched_db_uuid (notmuch);
\r
227 name_for_error = input_file_name ? input_file_name : "stdin";
\r
230 diff --git a/notmuch-search.c b/notmuch-search.c
\r
231 index b89a17e..3076c3f 100644
\r
232 --- a/notmuch-search.c
\r
233 +++ b/notmuch-search.c
\r
234 @@ -583,6 +583,8 @@ _notmuch_search_prepare (search_context_t *ctx, notmuch_config_t *config, int ar
\r
235 return EXIT_FAILURE;
\r
238 + notmuch_exit_if_unmatched_db_uuid (ctx->notmuch);
\r
240 query_str = query_string_from_args (ctx->notmuch, argc, argv);
\r
241 if (query_str == NULL) {
\r
242 fprintf (stderr, "Out of memory.\n");
\r
243 diff --git a/notmuch-setup.c b/notmuch-setup.c
\r
244 index 7dd5822..9aaf928 100644
\r
245 --- a/notmuch-setup.c
\r
246 +++ b/notmuch-setup.c
\r
247 @@ -148,6 +148,10 @@ notmuch_setup_command (notmuch_config_t *config,
\r
248 if (notmuch_minimal_options ("setup", argc, argv) < 0)
\r
249 return EXIT_FAILURE;
\r
251 + if (notmuch_requested_db_uuid)
\r
252 + fprintf (stderr, "Warning: ignoring --uuid=%s\n",
\r
253 + notmuch_requested_db_uuid);
\r
255 if (notmuch_config_is_new (config))
\r
256 welcome_message_pre_setup ();
\r
258 diff --git a/notmuch-show.c b/notmuch-show.c
\r
259 index b80933a..6ef3308 100644
\r
260 --- a/notmuch-show.c
\r
261 +++ b/notmuch-show.c
\r
262 @@ -1213,6 +1213,8 @@ notmuch_show_command (notmuch_config_t *config, int argc, char *argv[])
\r
263 NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
\r
264 return EXIT_FAILURE;
\r
266 + notmuch_exit_if_unmatched_db_uuid (notmuch);
\r
268 query = notmuch_query_create (notmuch, query_string);
\r
269 if (query == NULL) {
\r
270 fprintf (stderr, "Out of memory\n");
\r
271 diff --git a/notmuch-tag.c b/notmuch-tag.c
\r
272 index 38d99aa..7ae98f6 100644
\r
273 --- a/notmuch-tag.c
\r
274 +++ b/notmuch-tag.c
\r
275 @@ -261,6 +261,8 @@ notmuch_tag_command (notmuch_config_t *config, int argc, char *argv[])
\r
276 NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much))
\r
277 return EXIT_FAILURE;
\r
279 + notmuch_exit_if_unmatched_db_uuid (notmuch);
\r
281 if (notmuch_config_get_maildir_synchronize_flags (config))
\r
282 tag_flags |= TAG_FLAG_MAILDIR_SYNC;
\r
284 diff --git a/notmuch.c b/notmuch.c
\r
285 index 9580c3f..ce6c575 100644
\r
288 @@ -47,10 +47,12 @@ static int
\r
289 _help_for (const char *topic);
\r
291 static notmuch_bool_t print_version = FALSE, print_help = FALSE;
\r
292 +char *notmuch_requested_db_uuid = NULL;
\r
294 const notmuch_opt_desc_t notmuch_shared_options [] = {
\r
295 { NOTMUCH_OPT_BOOLEAN, &print_version, "version", 'v', 0 },
\r
296 { NOTMUCH_OPT_BOOLEAN, &print_help, "help", 'h', 0 },
\r
297 + { NOTMUCH_OPT_STRING, ¬much_requested_db_uuid, "uuid", 'u', 0 },
\r
301 @@ -218,6 +220,22 @@ be supported in the future.\n", notmuch_format_version);
\r
306 +notmuch_exit_if_unmatched_db_uuid (notmuch_database_t *notmuch)
\r
308 + const char *uuid = NULL;
\r
310 + if (!notmuch_requested_db_uuid)
\r
312 + IGNORE_RESULT (notmuch_database_get_revision (notmuch, &uuid));
\r
314 + if (strcmp (notmuch_requested_db_uuid, uuid) != 0){
\r
315 + fprintf (stderr, "Error: requested database revision %s does not match %s\n",
\r
316 + notmuch_requested_db_uuid, uuid);
\r
322 exec_man (const char *page)
\r
324 diff --git a/test/T570-revision-tracking.sh b/test/T570-revision-tracking.sh
\r
325 index 4fff689..20b44cb 100755
\r
326 --- a/test/T570-revision-tracking.sh
\r
327 +++ b/test/T570-revision-tracking.sh
\r
328 @@ -46,4 +46,31 @@ notmuch tag +a-random-tag-8743632 '*'
\r
329 after=$(notmuch count --lastmod '*' | cut -f3)
\r
330 result=$(($before < $after))
\r
331 test_expect_equal 1 ${result}
\r
333 +notmuch count --lastmod '*' | cut -f2 > UUID
\r
335 +test_expect_success 'search succeeds with correct uuid' \
\r
336 + "notmuch search --uuid=$(cat UUID) '*'"
\r
338 +test_expect_success 'uuid works as global option ' \
\r
339 + "notmuch --uuid=$(cat UUID) search '*'"
\r
341 +test_expect_code 1 'uuid works as global option II' \
\r
342 + "notmuch --uuid=this-is-no-uuid search '*'"
\r
344 +test_expect_code 1 'search fails with incorrect uuid' \
\r
345 + "notmuch search --uuid=this-is-no-uuid '*'"
\r
347 +test_expect_success 'show succeeds with correct uuid' \
\r
348 + "notmuch show --uuid=$(cat UUID) '*'"
\r
350 +test_expect_code 1 'show fails with incorrect uuid' \
\r
351 + "notmuch show --uuid=this-is-no-uuid '*'"
\r
353 +test_expect_success 'tag succeeds with correct uuid' \
\r
354 + "notmuch tag --uuid=$(cat UUID) +test '*'"
\r
356 +test_expect_code 1 'tag fails with incorrect uuid' \
\r
357 + "notmuch tag --uuid=this-is-no-uuid '*' +test2"
\r
360 diff --git a/test/random-corpus.c b/test/random-corpus.c
\r
361 index b377eb4..d74271d 100644
\r
362 --- a/test/random-corpus.c
\r
363 +++ b/test/random-corpus.c
\r
364 @@ -119,6 +119,8 @@ const notmuch_opt_desc_t notmuch_shared_options[] = {
\r
368 +char *notmuch_requested_db_uuid = NULL;
\r
371 notmuch_process_shared_options (unused (const char *dummy))
\r