mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-11-25 04:18:08 +01:00
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.
This commit is contained in:
parent
5a3b42fb8c
commit
f76d8f82dd
17 changed files with 91 additions and 3 deletions
|
@ -51,9 +51,16 @@ Supported global options for ``notmuch`` include
|
||||||
Specify the configuration file to use. This overrides any
|
Specify the configuration file to use. This overrides any
|
||||||
configuration file specified by ${NOTMUCH\_CONFIG}.
|
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
|
All global options except ``--config`` can also be specified after the
|
||||||
command. For example, ``notmuch subcommand --version`` is equivalent to
|
command. For example, ``notmuch subcommand --uuid=HEX`` is
|
||||||
``notmuch --version subcommand``.
|
equivalent to ``notmuch --uuid=HEX subcommand``.
|
||||||
|
|
||||||
COMMANDS
|
COMMANDS
|
||||||
========
|
========
|
||||||
|
|
|
@ -466,7 +466,11 @@ notmuch_database_dump (notmuch_database_t *notmuch,
|
||||||
notmuch_bool_t gzip_output);
|
notmuch_bool_t gzip_output);
|
||||||
|
|
||||||
#include "command-line-arguments.h"
|
#include "command-line-arguments.h"
|
||||||
|
|
||||||
|
extern char *notmuch_requested_db_uuid;
|
||||||
extern const notmuch_opt_desc_t notmuch_shared_options [];
|
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);
|
void notmuch_process_shared_options (const char* subcommand_name);
|
||||||
int notmuch_minimal_options (const char* subcommand_name,
|
int notmuch_minimal_options (const char* subcommand_name,
|
||||||
int argc, char **argv);
|
int argc, char **argv);
|
||||||
|
|
|
@ -46,6 +46,11 @@ notmuch_compact_command (notmuch_config_t *config, int argc, char *argv[])
|
||||||
if (opt_index < 0)
|
if (opt_index < 0)
|
||||||
return EXIT_FAILURE;
|
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]);
|
notmuch_process_shared_options (argv[0]);
|
||||||
|
|
||||||
if (! quiet)
|
if (! quiet)
|
||||||
|
|
|
@ -878,6 +878,10 @@ notmuch_config_command (notmuch_config_t *config, int argc, char *argv[])
|
||||||
if (opt_index < 0)
|
if (opt_index < 0)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
if (notmuch_requested_db_uuid)
|
||||||
|
fprintf (stderr, "Warning: ignoring --uuid=%s\n",
|
||||||
|
notmuch_requested_db_uuid);
|
||||||
|
|
||||||
/* skip at least subcommand argument */
|
/* skip at least subcommand argument */
|
||||||
argc-= opt_index;
|
argc-= opt_index;
|
||||||
argv+= opt_index;
|
argv+= opt_index;
|
||||||
|
|
|
@ -189,6 +189,8 @@ notmuch_count_command (notmuch_config_t *config, int argc, char *argv[])
|
||||||
NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
|
NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
notmuch_exit_if_unmatched_db_uuid (notmuch);
|
||||||
|
|
||||||
query_str = query_string_from_args (config, argc-opt_index, argv+opt_index);
|
query_str = query_string_from_args (config, argc-opt_index, argv+opt_index);
|
||||||
if (query_str == NULL) {
|
if (query_str == NULL) {
|
||||||
fprintf (stderr, "Out of memory.\n");
|
fprintf (stderr, "Out of memory.\n");
|
||||||
|
|
|
@ -215,6 +215,8 @@ notmuch_dump_command (notmuch_config_t *config, int argc, char *argv[])
|
||||||
NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much))
|
NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much))
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
notmuch_exit_if_unmatched_db_uuid (notmuch);
|
||||||
|
|
||||||
char *output_file_name = NULL;
|
char *output_file_name = NULL;
|
||||||
int opt_index;
|
int opt_index;
|
||||||
|
|
||||||
|
|
|
@ -536,6 +536,8 @@ notmuch_insert_command (notmuch_config_t *config, int argc, char *argv[])
|
||||||
NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much))
|
NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much))
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
notmuch_exit_if_unmatched_db_uuid (notmuch);
|
||||||
|
|
||||||
/* Write the message to the Maildir new directory. */
|
/* Write the message to the Maildir new directory. */
|
||||||
newpath = maildir_write_new (config, STDIN_FILENO, maildir);
|
newpath = maildir_write_new (config, STDIN_FILENO, maildir);
|
||||||
if (! newpath) {
|
if (! newpath) {
|
||||||
|
|
|
@ -1009,10 +1009,11 @@ notmuch_new_command (notmuch_config_t *config, int argc, char *argv[])
|
||||||
fputs (status_string, stderr);
|
fputs (status_string, stderr);
|
||||||
free (status_string);
|
free (status_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notmuch_exit_if_unmatched_db_uuid (notmuch);
|
||||||
|
|
||||||
if (notmuch_database_needs_upgrade (notmuch)) {
|
if (notmuch_database_needs_upgrade (notmuch)) {
|
||||||
time_t now = time (NULL);
|
time_t now = time (NULL);
|
||||||
struct tm *gm_time = gmtime (&now);
|
struct tm *gm_time = gmtime (&now);
|
||||||
|
|
|
@ -831,6 +831,8 @@ notmuch_reply_command (notmuch_config_t *config, int argc, char *argv[])
|
||||||
NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
|
NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
notmuch_exit_if_unmatched_db_uuid (notmuch);
|
||||||
|
|
||||||
query = notmuch_query_create (notmuch, query_string);
|
query = notmuch_query_create (notmuch, query_string);
|
||||||
if (query == NULL) {
|
if (query == NULL) {
|
||||||
fprintf (stderr, "Out of memory\n");
|
fprintf (stderr, "Out of memory\n");
|
||||||
|
|
|
@ -165,6 +165,8 @@ notmuch_restore_command (notmuch_config_t *config, int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
notmuch_process_shared_options (argv[0]);
|
notmuch_process_shared_options (argv[0]);
|
||||||
|
notmuch_exit_if_unmatched_db_uuid (notmuch);
|
||||||
|
|
||||||
name_for_error = input_file_name ? input_file_name : "stdin";
|
name_for_error = input_file_name ? input_file_name : "stdin";
|
||||||
|
|
||||||
if (! accumulate)
|
if (! accumulate)
|
||||||
|
|
|
@ -583,6 +583,8 @@ _notmuch_search_prepare (search_context_t *ctx, notmuch_config_t *config, int ar
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notmuch_exit_if_unmatched_db_uuid (ctx->notmuch);
|
||||||
|
|
||||||
query_str = query_string_from_args (ctx->notmuch, argc, argv);
|
query_str = query_string_from_args (ctx->notmuch, argc, argv);
|
||||||
if (query_str == NULL) {
|
if (query_str == NULL) {
|
||||||
fprintf (stderr, "Out of memory.\n");
|
fprintf (stderr, "Out of memory.\n");
|
||||||
|
|
|
@ -148,6 +148,10 @@ notmuch_setup_command (notmuch_config_t *config,
|
||||||
if (notmuch_minimal_options ("setup", argc, argv) < 0)
|
if (notmuch_minimal_options ("setup", argc, argv) < 0)
|
||||||
return EXIT_FAILURE;
|
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))
|
if (notmuch_config_is_new (config))
|
||||||
welcome_message_pre_setup ();
|
welcome_message_pre_setup ();
|
||||||
|
|
||||||
|
|
|
@ -1213,6 +1213,8 @@ notmuch_show_command (notmuch_config_t *config, int argc, char *argv[])
|
||||||
NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
|
NOTMUCH_DATABASE_MODE_READ_ONLY, ¬much))
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
notmuch_exit_if_unmatched_db_uuid (notmuch);
|
||||||
|
|
||||||
query = notmuch_query_create (notmuch, query_string);
|
query = notmuch_query_create (notmuch, query_string);
|
||||||
if (query == NULL) {
|
if (query == NULL) {
|
||||||
fprintf (stderr, "Out of memory\n");
|
fprintf (stderr, "Out of memory\n");
|
||||||
|
|
|
@ -261,6 +261,8 @@ notmuch_tag_command (notmuch_config_t *config, int argc, char *argv[])
|
||||||
NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much))
|
NOTMUCH_DATABASE_MODE_READ_WRITE, ¬much))
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
notmuch_exit_if_unmatched_db_uuid (notmuch);
|
||||||
|
|
||||||
if (notmuch_config_get_maildir_synchronize_flags (config))
|
if (notmuch_config_get_maildir_synchronize_flags (config))
|
||||||
tag_flags |= TAG_FLAG_MAILDIR_SYNC;
|
tag_flags |= TAG_FLAG_MAILDIR_SYNC;
|
||||||
|
|
||||||
|
|
18
notmuch.c
18
notmuch.c
|
@ -47,10 +47,12 @@ static int
|
||||||
_help_for (const char *topic);
|
_help_for (const char *topic);
|
||||||
|
|
||||||
static notmuch_bool_t print_version = FALSE, print_help = FALSE;
|
static notmuch_bool_t print_version = FALSE, print_help = FALSE;
|
||||||
|
char *notmuch_requested_db_uuid = NULL;
|
||||||
|
|
||||||
const notmuch_opt_desc_t notmuch_shared_options [] = {
|
const notmuch_opt_desc_t notmuch_shared_options [] = {
|
||||||
{ NOTMUCH_OPT_BOOLEAN, &print_version, "version", 'v', 0 },
|
{ NOTMUCH_OPT_BOOLEAN, &print_version, "version", 'v', 0 },
|
||||||
{ NOTMUCH_OPT_BOOLEAN, &print_help, "help", 'h', 0 },
|
{ NOTMUCH_OPT_BOOLEAN, &print_help, "help", 'h', 0 },
|
||||||
|
{ NOTMUCH_OPT_STRING, ¬much_requested_db_uuid, "uuid", 'u', 0 },
|
||||||
{0, 0, 0, 0, 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
|
static void
|
||||||
exec_man (const char *page)
|
exec_man (const char *page)
|
||||||
{
|
{
|
||||||
|
|
|
@ -46,4 +46,31 @@ notmuch tag +a-random-tag-8743632 '*'
|
||||||
after=$(notmuch count --lastmod '*' | cut -f3)
|
after=$(notmuch count --lastmod '*' | cut -f3)
|
||||||
result=$(($before < $after))
|
result=$(($before < $after))
|
||||||
test_expect_equal 1 ${result}
|
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
|
test_done
|
||||||
|
|
|
@ -119,6 +119,8 @@ const notmuch_opt_desc_t notmuch_shared_options[] = {
|
||||||
{ 0, 0, 0, 0, 0 }
|
{ 0, 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
char *notmuch_requested_db_uuid = NULL;
|
||||||
|
|
||||||
void
|
void
|
||||||
notmuch_process_shared_options (unused (const char *dummy))
|
notmuch_process_shared_options (unused (const char *dummy))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue