+static int
+database_dump_config (notmuch_database_t *notmuch, gzFile output)
+{
+ notmuch_config_list_t *list;
+ int ret = EXIT_FAILURE;
+ char *buffer = NULL;
+ size_t buffer_size = 0;
+
+ if (print_status_database ("notmuch dump", notmuch,
+ notmuch_database_get_config_list (notmuch, NULL, &list)))
+ goto DONE;
+
+ for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) {
+ if (hex_encode (notmuch, notmuch_config_list_key (list),
+ &buffer, &buffer_size) != HEX_SUCCESS) {
+ fprintf (stderr, "Error: failed to hex-encode config key %s\n",
+ notmuch_config_list_key (list));
+ goto DONE;
+ }
+ gzprintf (output, "#@ %s", buffer);
+
+ if (hex_encode (notmuch, notmuch_config_list_value (list),
+ &buffer, &buffer_size) != HEX_SUCCESS) {
+ fprintf (stderr, "Error: failed to hex-encode config value %s\n",
+ notmuch_config_list_value (list) );
+ goto DONE;
+ }
+
+ gzprintf (output, " %s\n", buffer);
+ }
+
+ ret = EXIT_SUCCESS;
+
+ DONE:
+ if (list)
+ notmuch_config_list_destroy (list);
+
+ if (buffer)
+ talloc_free (buffer);
+
+ return ret;
+}
+
+static void
+print_dump_header (gzFile output, int output_format, int include)
+{
+ gzprintf (output, "#notmuch-dump %s:%d %s%s%s\n",
+ (output_format == DUMP_FORMAT_SUP) ? "sup" : "batch-tag",
+ NOTMUCH_DUMP_VERSION,
+ (include & DUMP_INCLUDE_CONFIG) ? "config" : "",
+ (include & DUMP_INCLUDE_TAGS) && (include & DUMP_INCLUDE_CONFIG) ? "," : "",
+ (include & DUMP_INCLUDE_TAGS) ? "tags" : "");
+}
+
+static int
+dump_tags_message (void *ctx,
+ notmuch_message_t *message, int output_format,
+ gzFile output,
+ char **buffer_p, size_t *size_p)
+{
+ int first = 1;
+ const char *message_id;
+
+ message_id = notmuch_message_get_message_id (message);
+
+ if (output_format == DUMP_FORMAT_BATCH_TAG &&
+ strchr (message_id, '\n')) {
+ /* This will produce a line break in the output, which
+ * would be difficult to handle in tools. However, it's
+ * also impossible to produce an email containing a line
+ * break in a message ID because of unfolding, so we can
+ * safely disallow it. */
+ fprintf (stderr, "Warning: skipping message id containing line break: \"%s\"\n", message_id);
+ return EXIT_SUCCESS;
+ }
+
+ if (output_format == DUMP_FORMAT_SUP) {
+ gzprintf (output, "%s (", message_id);
+ }
+
+ for (notmuch_tags_t *tags = notmuch_message_get_tags (message);
+ notmuch_tags_valid (tags);
+ notmuch_tags_move_to_next (tags)) {
+ const char *tag_str = notmuch_tags_get (tags);
+
+ if (! first)
+ gzputs (output, " ");
+
+ first = 0;
+
+ if (output_format == DUMP_FORMAT_SUP) {
+ gzputs (output, tag_str);
+ } else {
+ if (hex_encode (ctx, tag_str,
+ buffer_p, size_p) != HEX_SUCCESS) {
+ fprintf (stderr, "Error: failed to hex-encode tag %s\n",
+ tag_str);
+ return EXIT_FAILURE;
+ }
+ gzprintf (output, "+%s", *buffer_p);
+ }
+ }
+
+ if (output_format == DUMP_FORMAT_SUP) {
+ gzputs (output, ")\n");
+ } else {
+ if (make_boolean_term (ctx, "id", message_id,
+ buffer_p, size_p)) {
+ fprintf (stderr, "Error quoting message id %s: %s\n",
+ message_id, strerror (errno));
+ return EXIT_FAILURE;
+ }
+ gzprintf (output, " -- %s\n", *buffer_p);
+ }
+ return EXIT_SUCCESS;
+}
+
+static int
+database_dump_file (notmuch_database_t *notmuch, gzFile output,
+ const char *query_str, int output_format, int include)