mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-11-28 05:34:11 +01:00
CLI: add properties to dump output
Part of providing extensibility via properties is to make sure that user data is not lost. Thus we need to be able to dump and restore properties.
This commit is contained in:
parent
f240528095
commit
b7345d277e
5 changed files with 116 additions and 13 deletions
|
@ -71,7 +71,7 @@ Supported options for **dump** include
|
||||||
characters. Note also that tags with spaces will not be
|
characters. Note also that tags with spaces will not be
|
||||||
correctly restored with this format.
|
correctly restored with this format.
|
||||||
|
|
||||||
``--include=(config|tags)``
|
``--include=(config|properties|tags)``
|
||||||
|
|
||||||
Control what kind of metadata is included in the output.
|
Control what kind of metadata is included in the output.
|
||||||
|
|
||||||
|
@ -81,14 +81,22 @@ Supported options for **dump** include
|
||||||
starts with "#@ ", followed by a space separated key-value
|
starts with "#@ ", followed by a space separated key-value
|
||||||
pair. Both key and value are hex encoded if needed.
|
pair. Both key and value are hex encoded if needed.
|
||||||
|
|
||||||
|
**properties**
|
||||||
|
|
||||||
|
Output per-message (key,value) metadata. Each line starts
|
||||||
|
with "#= ", followed by a message id, and a space separated
|
||||||
|
list of key=value pairs. pair. Ids, keys and values are hex
|
||||||
|
encoded if needed.
|
||||||
|
|
||||||
**tags**
|
**tags**
|
||||||
|
|
||||||
Output per-message metadata, namely tags. See *format* above
|
Output per-message boolean metadata, namely tags. See *format* above
|
||||||
for description of the output.
|
for description of the output.
|
||||||
|
|
||||||
The default is to include both tags and configuration
|
The default is to include all available types of data. The
|
||||||
information. As of version 2 of the dump format, there is a
|
option can be specified multiple times to select some subset. As
|
||||||
header line of the following form
|
of version 2 of the dump format, there is a header line of the
|
||||||
|
following form
|
||||||
|
|
||||||
|
|
|
|
||||||
| #notmuch-dump <*format*>:<*version*> <*included*>
|
| #notmuch-dump <*format*>:<*version*> <*included*>
|
||||||
|
|
|
@ -449,8 +449,11 @@ typedef enum dump_formats {
|
||||||
typedef enum dump_includes {
|
typedef enum dump_includes {
|
||||||
DUMP_INCLUDE_TAGS = 1,
|
DUMP_INCLUDE_TAGS = 1,
|
||||||
DUMP_INCLUDE_CONFIG = 2,
|
DUMP_INCLUDE_CONFIG = 2,
|
||||||
|
DUMP_INCLUDE_PROPERTIES = 4
|
||||||
} dump_include_t;
|
} dump_include_t;
|
||||||
|
|
||||||
|
#define DUMP_INCLUDE_DEFAULT (DUMP_INCLUDE_TAGS | DUMP_INCLUDE_CONFIG | DUMP_INCLUDE_PROPERTIES)
|
||||||
|
|
||||||
#define NOTMUCH_DUMP_VERSION 2
|
#define NOTMUCH_DUMP_VERSION 2
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -69,12 +69,77 @@ database_dump_config (notmuch_database_t *notmuch, gzFile output)
|
||||||
static void
|
static void
|
||||||
print_dump_header (gzFile output, int output_format, int include)
|
print_dump_header (gzFile output, int output_format, int include)
|
||||||
{
|
{
|
||||||
gzprintf (output, "#notmuch-dump %s:%d %s%s%s\n",
|
const char *sep = "";
|
||||||
|
|
||||||
|
gzprintf (output, "#notmuch-dump %s:%d ",
|
||||||
(output_format == DUMP_FORMAT_SUP) ? "sup" : "batch-tag",
|
(output_format == DUMP_FORMAT_SUP) ? "sup" : "batch-tag",
|
||||||
NOTMUCH_DUMP_VERSION,
|
NOTMUCH_DUMP_VERSION);
|
||||||
(include & DUMP_INCLUDE_CONFIG) ? "config" : "",
|
|
||||||
(include & DUMP_INCLUDE_TAGS) && (include & DUMP_INCLUDE_CONFIG) ? "," : "",
|
if (include & DUMP_INCLUDE_CONFIG) {
|
||||||
(include & DUMP_INCLUDE_TAGS) ? "tags" : "");
|
gzputs (output, "config");
|
||||||
|
sep = ",";
|
||||||
|
}
|
||||||
|
if (include & DUMP_INCLUDE_PROPERTIES) {
|
||||||
|
gzprintf (output, "%sproperties", sep);
|
||||||
|
sep = ",";
|
||||||
|
}
|
||||||
|
if (include & DUMP_INCLUDE_TAGS) {
|
||||||
|
gzprintf (output, "%sproperties", sep);
|
||||||
|
}
|
||||||
|
gzputs (output, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
dump_properties_message (void *ctx,
|
||||||
|
notmuch_message_t *message,
|
||||||
|
gzFile output,
|
||||||
|
char **buffer_p, size_t *size_p)
|
||||||
|
{
|
||||||
|
const char *message_id;
|
||||||
|
notmuch_message_properties_t *list;
|
||||||
|
notmuch_bool_t first = TRUE;
|
||||||
|
|
||||||
|
message_id = notmuch_message_get_message_id (message);
|
||||||
|
|
||||||
|
if (strchr (message_id, '\n')) {
|
||||||
|
fprintf (stderr, "Warning: skipping message id containing line break: \"%s\"\n", message_id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (list = notmuch_message_get_properties (message, "", FALSE);
|
||||||
|
notmuch_message_properties_valid (list); notmuch_message_properties_move_to_next (list)) {
|
||||||
|
const char *key, *val;
|
||||||
|
|
||||||
|
if (first) {
|
||||||
|
if (hex_encode (ctx, message_id, buffer_p, size_p) != HEX_SUCCESS) {
|
||||||
|
fprintf (stderr, "Error: failed to hex-encode message-id %s\n", message_id);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
gzprintf (output, "#= %s", *buffer_p);
|
||||||
|
first = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
key = notmuch_message_properties_key (list);
|
||||||
|
val = notmuch_message_properties_value (list);
|
||||||
|
|
||||||
|
if (hex_encode (ctx, key, buffer_p, size_p) != HEX_SUCCESS) {
|
||||||
|
fprintf (stderr, "Error: failed to hex-encode key %s\n", key);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
gzprintf (output, " %s", *buffer_p);
|
||||||
|
|
||||||
|
if (hex_encode (ctx, val, buffer_p, size_p) != HEX_SUCCESS) {
|
||||||
|
fprintf (stderr, "Error: failed to hex-encode value %s\n", val);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
gzprintf (output, "=%s", *buffer_p);
|
||||||
|
}
|
||||||
|
notmuch_message_properties_destroy (list);
|
||||||
|
|
||||||
|
if (! first)
|
||||||
|
gzprintf (output, "\n", *buffer_p);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -159,7 +224,7 @@ database_dump_file (notmuch_database_t *notmuch, gzFile output,
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! (include & DUMP_INCLUDE_TAGS))
|
if (! (include & (DUMP_INCLUDE_TAGS | DUMP_INCLUDE_PROPERTIES)))
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
|
||||||
if (! query_str)
|
if (! query_str)
|
||||||
|
@ -189,6 +254,11 @@ database_dump_file (notmuch_database_t *notmuch, gzFile output,
|
||||||
&buffer, &buffer_size))
|
&buffer, &buffer_size))
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
if ((include & DUMP_INCLUDE_PROPERTIES) &&
|
||||||
|
dump_properties_message (notmuch, message, output,
|
||||||
|
&buffer, &buffer_size))
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
notmuch_message_destroy (message);
|
notmuch_message_destroy (message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,6 +382,7 @@ notmuch_dump_command (notmuch_config_t *config, int argc, char *argv[])
|
||||||
{ 0, 0 } } },
|
{ 0, 0 } } },
|
||||||
{ NOTMUCH_OPT_KEYWORD_FLAGS, &include, "include", 'I',
|
{ NOTMUCH_OPT_KEYWORD_FLAGS, &include, "include", 'I',
|
||||||
(notmuch_keyword_t []){ { "config", DUMP_INCLUDE_CONFIG },
|
(notmuch_keyword_t []){ { "config", DUMP_INCLUDE_CONFIG },
|
||||||
|
{ "properties", DUMP_INCLUDE_PROPERTIES },
|
||||||
{ "tags", DUMP_INCLUDE_TAGS} } },
|
{ "tags", DUMP_INCLUDE_TAGS} } },
|
||||||
{ NOTMUCH_OPT_STRING, &output_file_name, "output", 'o', 0 },
|
{ NOTMUCH_OPT_STRING, &output_file_name, "output", 'o', 0 },
|
||||||
{ NOTMUCH_OPT_BOOLEAN, &gzip_output, "gzip", 'z', 0 },
|
{ NOTMUCH_OPT_BOOLEAN, &gzip_output, "gzip", 'z', 0 },
|
||||||
|
@ -326,7 +397,7 @@ notmuch_dump_command (notmuch_config_t *config, int argc, char *argv[])
|
||||||
notmuch_process_shared_options (argv[0]);
|
notmuch_process_shared_options (argv[0]);
|
||||||
|
|
||||||
if (include == 0)
|
if (include == 0)
|
||||||
include = DUMP_INCLUDE_CONFIG | DUMP_INCLUDE_TAGS;
|
include = DUMP_INCLUDE_CONFIG | DUMP_INCLUDE_TAGS | DUMP_INCLUDE_PROPERTIES;
|
||||||
|
|
||||||
if (opt_index < argc) {
|
if (opt_index < argc) {
|
||||||
query_str = query_string_from_args (notmuch, argc - opt_index, argv + opt_index);
|
query_str = query_string_from_args (notmuch, argc - opt_index, argv + opt_index);
|
||||||
|
|
|
@ -1042,7 +1042,7 @@ notmuch_new_command (notmuch_config_t *config, int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
if (notmuch_database_dump (notmuch, backup_name, "",
|
if (notmuch_database_dump (notmuch, backup_name, "",
|
||||||
DUMP_FORMAT_BATCH_TAG, DUMP_INCLUDE_CONFIG | DUMP_INCLUDE_TAGS, TRUE)) {
|
DUMP_FORMAT_BATCH_TAG, DUMP_INCLUDE_DEFAULT, TRUE)) {
|
||||||
fprintf (stderr, "Backup failed. Aborting upgrade.");
|
fprintf (stderr, "Backup failed. Aborting upgrade.");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,6 +89,17 @@ testkey2 = NULL
|
||||||
EOF
|
EOF
|
||||||
test_expect_equal_file EXPECTED OUTPUT
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "notmuch_message_remove_all_properties"
|
||||||
|
cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
|
||||||
|
EXPECT0(notmuch_message_remove_all_properties (message, NULL));
|
||||||
|
print_properties (message, "", FALSE);
|
||||||
|
EOF
|
||||||
|
cat <<'EOF' >EXPECTED
|
||||||
|
== stdout ==
|
||||||
|
== stderr ==
|
||||||
|
EOF
|
||||||
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
test_begin_subtest "notmuch_message_get_properties: empty list"
|
test_begin_subtest "notmuch_message_get_properties: empty list"
|
||||||
cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
|
cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
|
||||||
{
|
{
|
||||||
|
@ -188,4 +199,14 @@ cat <<'EOF' >EXPECTED
|
||||||
EOF
|
EOF
|
||||||
test_expect_equal_file EXPECTED OUTPUT
|
test_expect_equal_file EXPECTED OUTPUT
|
||||||
|
|
||||||
|
test_begin_subtest "dump message properties"
|
||||||
|
cat <<EOF > PROPERTIES
|
||||||
|
#= 4EFC743A.3060609@april.org fancy%20key%20with%20%c3%a1cc%c3%a8nts=import%20value%20with%20= testkey1=alice testkey1=bob testkey1=testvalue1 testkey1=testvalue2 testkey3=alice3 testkey3=bob3 testkey3=testvalue3
|
||||||
|
EOF
|
||||||
|
cat c_head - c_tail <<'EOF' | test_C ${MAIL_DIR}
|
||||||
|
EXPECT0(notmuch_message_add_property (message, "fancy key with áccènts", "import value with ="));
|
||||||
|
EOF
|
||||||
|
notmuch dump | grep '^#=' > OUTPUT
|
||||||
|
test_expect_equal_file PROPERTIES OUTPUT
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
|
Loading…
Reference in a new issue