Return-Path: X-Original-To: notmuch@notmuchmail.org Delivered-To: notmuch@notmuchmail.org Received: from localhost (localhost [127.0.0.1]) by arlo.cworth.org (Postfix) with ESMTP id C4ABD6DE190D for ; Fri, 14 Aug 2015 09:49:31 -0700 (PDT) X-Virus-Scanned: Debian amavisd-new at cworth.org X-Spam-Flag: NO X-Spam-Score: 0.134 X-Spam-Level: X-Spam-Status: No, score=0.134 tagged_above=-999 required=5 tests=[AWL=0.124, T_HEADER_FROM_DIFFERENT_DOMAINS=0.01] autolearn=disabled Received: from arlo.cworth.org ([127.0.0.1]) by localhost (arlo.cworth.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id XichQvwJyqfN for ; Fri, 14 Aug 2015 09:49:30 -0700 (PDT) Received: from gitolite.debian.net (gitolite.debian.net [87.98.215.224]) by arlo.cworth.org (Postfix) with ESMTPS id F099F6DE18FD for ; Fri, 14 Aug 2015 09:49:29 -0700 (PDT) Received: from remotemail by gitolite.debian.net with local (Exim 4.80) (envelope-from ) id 1ZQI9v-0003eC-OJ; Fri, 14 Aug 2015 16:48:47 +0000 Received: (nullmailer pid 15758 invoked by uid 1000); Fri, 14 Aug 2015 16:48:02 -0000 From: David Bremner To: notmuch@notmuchmail.org Subject: [PATCH 4/5] cli: add global option "--uuid" Date: Fri, 14 Aug 2015 18:47:57 +0200 Message-Id: <1439570878-15165-5-git-send-email-david@tethera.net> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1439570878-15165-1-git-send-email-david@tethera.net> References: <1439570878-15165-1-git-send-email-david@tethera.net> X-BeenThere: notmuch@notmuchmail.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 14 Aug 2015 16:49:31 -0000 The function notmuch_exit_if_unmatched_db_uuid is split from notmuch_process_shared_options because it needs an open notmuch database. There are two exceptional cases in uuid handling. 1) notmuch config and notmuch setup don't currently open the database, so it doesn't make sense to check the UUID. 2) notmuch compact opens the database inside the library, so we either need to open the database just to check uuid, or change the API. --- doc/man1/notmuch.rst | 11 +++++++++-- notmuch-client.h | 4 ++++ notmuch-compact.c | 5 +++++ notmuch-config.c | 4 ++++ notmuch-count.c | 2 ++ notmuch-dump.c | 2 ++ notmuch-insert.c | 2 ++ notmuch-new.c | 3 ++- notmuch-reply.c | 2 ++ notmuch-restore.c | 2 ++ notmuch-search.c | 2 ++ notmuch-setup.c | 4 ++++ notmuch-show.c | 2 ++ notmuch-tag.c | 2 ++ notmuch.c | 18 ++++++++++++++++++ test/T570-revision-tracking.sh | 27 +++++++++++++++++++++++++++ test/random-corpus.c | 2 ++ 17 files changed, 91 insertions(+), 3 deletions(-) diff --git a/doc/man1/notmuch.rst b/doc/man1/notmuch.rst index 0401c91..3acfbdb 100644 --- a/doc/man1/notmuch.rst +++ b/doc/man1/notmuch.rst @@ -51,9 +51,16 @@ Supported global options for ``notmuch`` include Specify the configuration file to use. This overrides any configuration file specified by ${NOTMUCH\_CONFIG}. + ``--uuid=HEX`` + Enforce that the database UUID (a unique identifier which + persists until e.g. the database is compacted) + is HEX; exit with an error if it is not. This is useful to + detect rollover in modification counts on messages. You can + find this UUID using e.g. ``notmuch count --lastmod`` + All global options except ``--config`` can also be specified after the -command. For example, ``notmuch subcommand --version`` is equivalent to -``notmuch --version subcommand``. +command. For example, ``notmuch subcommand --uuid=HEX`` is +equivalent to ``notmuch --uuid=HEX subcommand``. COMMANDS ======== diff --git a/notmuch-client.h b/notmuch-client.h index 78680aa..4a4f86c 100644 --- a/notmuch-client.h +++ b/notmuch-client.h @@ -466,7 +466,11 @@ notmuch_database_dump (notmuch_database_t *notmuch, notmuch_bool_t gzip_output); #include "command-line-arguments.h" + +extern char *notmuch_requested_db_uuid; extern const notmuch_opt_desc_t notmuch_shared_options []; +void notmuch_exit_if_unmatched_db_uuid (notmuch_database_t *notmuch); + void notmuch_process_shared_options (const char* subcommand_name); int notmuch_minimal_options (const char* subcommand_name, int argc, char **argv); diff --git a/notmuch-compact.c b/notmuch-compact.c index 5be551d..9373721 100644 --- a/notmuch-compact.c +++ b/notmuch-compact.c @@ -46,6 +46,11 @@ notmuch_compact_command (notmuch_config_t *config, int argc, char *argv[]) if (opt_index < 0) return EXIT_FAILURE; + if (notmuch_requested_db_uuid) { + fprintf (stderr, "Error: --uuid not implemented for compact\n"); + return EXIT_FAILURE; + } + notmuch_process_shared_options (argv[0]); if (! quiet) diff --git a/notmuch-config.c b/notmuch-config.c index 9348278..d252bb2 100644 --- a/notmuch-config.c +++ b/notmuch-config.c @@ -878,6 +878,10 @@ notmuch_config_command (notmuch_config_t *config, int argc, char *argv[]) if (opt_index < 0) return EXIT_FAILURE; + if (notmuch_requested_db_uuid) + fprintf (stderr, "Warning: ignoring --uuid=%s\n", + notmuch_requested_db_uuid); + /* skip at least subcommand argument */ argc-= opt_index; argv+= opt_index; diff --git a/notmuch-count.c b/notmuch-count.c index 182710a..f26e726 100644 --- a/notmuch-count.c +++ b/notmuch-count.c @@ -189,6 +189,8 @@ notmuch_count_command (notmuch_config_t *config, int argc, char *argv[]) NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much)) return EXIT_FAILURE; + notmuch_exit_if_unmatched_db_uuid (notmuch); + query_str = query_string_from_args (config, argc-opt_index, argv+opt_index); if (query_str == NULL) { fprintf (stderr, "Out of memory.\n"); diff --git a/notmuch-dump.c b/notmuch-dump.c index fab22bd..24fc2f2 100644 --- a/notmuch-dump.c +++ b/notmuch-dump.c @@ -215,6 +215,8 @@ notmuch_dump_command (notmuch_config_t *config, int argc, char *argv[]) NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much)) return EXIT_FAILURE; + notmuch_exit_if_unmatched_db_uuid (notmuch); + char *output_file_name = NULL; int opt_index; diff --git a/notmuch-insert.c b/notmuch-insert.c index c277d62..5205c17 100644 --- a/notmuch-insert.c +++ b/notmuch-insert.c @@ -536,6 +536,8 @@ notmuch_insert_command (notmuch_config_t *config, int argc, char *argv[]) NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much)) return EXIT_FAILURE; + notmuch_exit_if_unmatched_db_uuid (notmuch); + /* Write the message to the Maildir new directory. */ newpath = maildir_write_new (config, STDIN_FILENO, maildir); if (! newpath) { diff --git a/notmuch-new.c b/notmuch-new.c index ee786a3..514e06a 100644 --- a/notmuch-new.c +++ b/notmuch-new.c @@ -1009,10 +1009,11 @@ notmuch_new_command (notmuch_config_t *config, int argc, char *argv[]) fputs (status_string, stderr); free (status_string); } - return EXIT_FAILURE; } + notmuch_exit_if_unmatched_db_uuid (notmuch); + if (notmuch_database_needs_upgrade (notmuch)) { time_t now = time (NULL); struct tm *gm_time = gmtime (&now); diff --git a/notmuch-reply.c b/notmuch-reply.c index 4464741..7c5c28f 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -831,6 +831,8 @@ notmuch_reply_command (notmuch_config_t *config, int argc, char *argv[]) NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much)) return EXIT_FAILURE; + notmuch_exit_if_unmatched_db_uuid (notmuch); + query = notmuch_query_create (notmuch, query_string); if (query == NULL) { fprintf (stderr, "Out of memory\n"); diff --git a/notmuch-restore.c b/notmuch-restore.c index 2a534dc..9abc64f 100644 --- a/notmuch-restore.c +++ b/notmuch-restore.c @@ -165,6 +165,8 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[]) } notmuch_process_shared_options (argv[0]); + notmuch_exit_if_unmatched_db_uuid (notmuch); + name_for_error = input_file_name ? input_file_name : "stdin"; if (! accumulate) diff --git a/notmuch-search.c b/notmuch-search.c index b89a17e..3076c3f 100644 --- a/notmuch-search.c +++ b/notmuch-search.c @@ -583,6 +583,8 @@ _notmuch_search_prepare (search_context_t *ctx, notmuch_config_t *config, int ar return EXIT_FAILURE; } + notmuch_exit_if_unmatched_db_uuid (ctx->notmuch); + query_str = query_string_from_args (ctx->notmuch, argc, argv); if (query_str == NULL) { fprintf (stderr, "Out of memory.\n"); diff --git a/notmuch-setup.c b/notmuch-setup.c index 7dd5822..9aaf928 100644 --- a/notmuch-setup.c +++ b/notmuch-setup.c @@ -148,6 +148,10 @@ notmuch_setup_command (notmuch_config_t *config, if (notmuch_minimal_options ("setup", argc, argv) < 0) return EXIT_FAILURE; + if (notmuch_requested_db_uuid) + fprintf (stderr, "Warning: ignoring --uuid=%s\n", + notmuch_requested_db_uuid); + if (notmuch_config_is_new (config)) welcome_message_pre_setup (); diff --git a/notmuch-show.c b/notmuch-show.c index b80933a..6ef3308 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -1213,6 +1213,8 @@ notmuch_show_command (notmuch_config_t *config, int argc, char *argv[]) NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much)) return EXIT_FAILURE; + notmuch_exit_if_unmatched_db_uuid (notmuch); + query = notmuch_query_create (notmuch, query_string); if (query == NULL) { fprintf (stderr, "Out of memory\n"); diff --git a/notmuch-tag.c b/notmuch-tag.c index 38d99aa..7ae98f6 100644 --- a/notmuch-tag.c +++ b/notmuch-tag.c @@ -261,6 +261,8 @@ notmuch_tag_command (notmuch_config_t *config, int argc, char *argv[]) NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much)) return EXIT_FAILURE; + notmuch_exit_if_unmatched_db_uuid (notmuch); + if (notmuch_config_get_maildir_synchronize_flags (config)) tag_flags |= TAG_FLAG_MAILDIR_SYNC; diff --git a/notmuch.c b/notmuch.c index 9580c3f..ce6c575 100644 --- a/notmuch.c +++ b/notmuch.c @@ -47,10 +47,12 @@ static int _help_for (const char *topic); static notmuch_bool_t print_version = FALSE, print_help = FALSE; +char *notmuch_requested_db_uuid = NULL; const notmuch_opt_desc_t notmuch_shared_options [] = { { NOTMUCH_OPT_BOOLEAN, &print_version, "version", 'v', 0 }, { NOTMUCH_OPT_BOOLEAN, &print_help, "help", 'h', 0 }, + { NOTMUCH_OPT_STRING, ¬much_requested_db_uuid, "uuid", 'u', 0 }, {0, 0, 0, 0, 0} }; @@ -218,6 +220,22 @@ be supported in the future.\n", notmuch_format_version); } } +void +notmuch_exit_if_unmatched_db_uuid (notmuch_database_t *notmuch) +{ + const char *uuid = NULL; + + if (!notmuch_requested_db_uuid) + return; + IGNORE_RESULT (notmuch_database_get_revision (notmuch, &uuid)); + + if (strcmp (notmuch_requested_db_uuid, uuid) != 0){ + fprintf (stderr, "Error: requested database revision %s does not match %s\n", + notmuch_requested_db_uuid, uuid); + exit (1); + } +} + static void exec_man (const char *page) { diff --git a/test/T570-revision-tracking.sh b/test/T570-revision-tracking.sh index 4fff689..20b44cb 100755 --- a/test/T570-revision-tracking.sh +++ b/test/T570-revision-tracking.sh @@ -46,4 +46,31 @@ notmuch tag +a-random-tag-8743632 '*' after=$(notmuch count --lastmod '*' | cut -f3) result=$(($before < $after)) test_expect_equal 1 ${result} + +notmuch count --lastmod '*' | cut -f2 > UUID + +test_expect_success 'search succeeds with correct uuid' \ + "notmuch search --uuid=$(cat UUID) '*'" + +test_expect_success 'uuid works as global option ' \ + "notmuch --uuid=$(cat UUID) search '*'" + +test_expect_code 1 'uuid works as global option II' \ + "notmuch --uuid=this-is-no-uuid search '*'" + +test_expect_code 1 'search fails with incorrect uuid' \ + "notmuch search --uuid=this-is-no-uuid '*'" + +test_expect_success 'show succeeds with correct uuid' \ + "notmuch show --uuid=$(cat UUID) '*'" + +test_expect_code 1 'show fails with incorrect uuid' \ + "notmuch show --uuid=this-is-no-uuid '*'" + +test_expect_success 'tag succeeds with correct uuid' \ + "notmuch tag --uuid=$(cat UUID) +test '*'" + +test_expect_code 1 'tag fails with incorrect uuid' \ + "notmuch tag --uuid=this-is-no-uuid '*' +test2" + test_done diff --git a/test/random-corpus.c b/test/random-corpus.c index b377eb4..d74271d 100644 --- a/test/random-corpus.c +++ b/test/random-corpus.c @@ -119,6 +119,8 @@ const notmuch_opt_desc_t notmuch_shared_options[] = { { 0, 0, 0, 0, 0 } }; +char *notmuch_requested_db_uuid = NULL; + void notmuch_process_shared_options (unused (const char *dummy)) { -- 2.5.0