From f76d8f82dd004cf14426a91e8a80dcd2a4b97317 Mon Sep 17 00:00:00 2001 From: David Bremner Date: Mon, 6 Apr 2015 07:39:55 +0900 Subject: [PATCH] cli: add global option "--uuid" 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 0401c91b..3acfbdb4 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 78680aa1..4a4f86c4 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 5be551d4..93737216 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 93482787..d252bb25 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 182710a6..f26e726a 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 fab22bdd..24fc2f23 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 c277d620..5205c17a 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 ee786a3b..514e06a4 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 4464741f..7c5c28f4 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 2a534dc4..9abc64fd 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 b89a17e5..3076c3f6 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 7dd5822a..9aaf9286 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 b80933ad..6ef33085 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 38d99aa9..7ae98f6c 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 9580c3fe..ce6c5756 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 4fff6896..20b44cbe 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 b377eb40..d74271d9 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.26.2