On Sun, Aug 09 2015, David Bremner <david at tethera.net> wrote:

> The function notmuch_exit_if_unmatched_db_uuid is split from
> notmuch_process_shared_options because it needs an open notmuch
> database.
> ---
>  doc/man1/notmuch.rst           | 12 ++++++++++--
>  notmuch-client.h               |  4 ++++
>  notmuch-compact.c              |  4 ++++
>  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..0b89544 100644
> --- a/doc/man1/notmuch.rst
> +++ b/doc/man1/notmuch.rst
> @@ -51,9 +51,17 @@ 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 in the first column of output from
> +       ``notmuch count --output=modifications``
> +
>  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..61fccd8 100644
> --- a/notmuch-compact.c
> +++ b/notmuch-compact.c
> @@ -46,6 +46,10 @@ 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, "Warning: ignoring --uuid=%s\n",
> +              notmuch_requested_db_uuid);
> +

I see in these commands this warning is issued, we don't open the database
(at this time, IIRC compact opens it later)...

... In this case I'm wondering whether giving --uuid should be considered
as error (and stopping) instead of printing warning and continuing.  In
some other cases we do warn and continue but here ... we're modifying
the database or configurations...
... later we could add database uuid check always if --uuid is given
and allow continuing if it matches in these cases...

One more (now the trivial thing) to go, do not stop here ;)

>      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 7c61ccb..091e376 100644
> --- a/notmuch-count.c
> +++ b/notmuch-count.c
> @@ -191,6 +191,8 @@ notmuch_count_command (notmuch_config_t *config, int 
> argc, char *argv[])
>                              NOTMUCH_DATABASE_MODE_READ_ONLY, &notmuch))
>       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, &notmuch))
>       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, &notmuch))
>       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, &notmuch))
>       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, &notmuch))
>       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, &notmuch))
>       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, &notmuch_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 008c5d0..74e3ba9 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 --output=modifications '*' | cut -f2)
>  result=$(($before < $after))
>  test_expect_equal 1 ${result}
> +
> +notmuch count --output=modifications '*' | cut -f1 > UUID

the above could be

UUID=$(notmuch count --output=modifications '*' | cut -f1)

> +
> +test_expect_success 'search succeeds with correct uuid' \
> +                 "notmuch search --uuid=$(cat UUID) '*'"

And then these just as 

test_expect_success 'search succeeds with correct uuid' \
                    "notmuch search --uuid=${UUID} '*'"


Tomi


> +
> +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.1.4

Reply via email to