CLI/reply: convert to new config framework

This is messier than some of the other conversions because the
extensive use of 'config' as a talloc context.
This commit is contained in:
David Bremner 2020-11-07 21:58:32 -04:00
parent 0ab0b48be2
commit 8588719eb1
3 changed files with 108 additions and 52 deletions

View file

@ -112,25 +112,26 @@ match_address (const char *str, const char *address, address_match_t mode)
/* Match given string against user's configured "primary" and "other" /* Match given string against user's configured "primary" and "other"
* addresses according to mode. */ * addresses according to mode. */
static const char * static const char *
address_match (const char *str, notmuch_config_t *config, address_match_t mode) address_match (const char *str, notmuch_database_t *notmuch, address_match_t mode)
{ {
const char *primary; const char *primary;
const char **other; notmuch_config_values_t *other = NULL;
size_t i, other_len;
if (! str || *str == '\0') if (! str || *str == '\0')
return NULL; return NULL;
primary = notmuch_config_get_user_primary_email (config); primary = notmuch_config_get (notmuch, NOTMUCH_CONFIG_PRIMARY_EMAIL);
if (match_address (str, primary, mode)) if (match_address (str, primary, mode))
return primary; return primary;
other = notmuch_config_get_user_other_email (config, &other_len); for (other = notmuch_config_get_values (notmuch, NOTMUCH_CONFIG_OTHER_EMAIL);
for (i = 0; i < other_len; i++) { notmuch_config_values_valid (other);
if (match_address (str, other[i], mode)) notmuch_config_values_move_to_next (other)) {
return other[i]; const char *addr = notmuch_config_values_get (other);
}
if (match_address (str, addr, mode))
return addr;
}
return NULL; return NULL;
} }
@ -138,26 +139,26 @@ address_match (const char *str, notmuch_config_t *config, address_match_t mode)
* user's "primary" or "other" addresses. If so, return the matching * user's "primary" or "other" addresses. If so, return the matching
* address, NULL otherwise. */ * address, NULL otherwise. */
static const char * static const char *
user_address_in_string (const char *str, notmuch_config_t *config) user_address_in_string (const char *str, notmuch_database_t *notmuch)
{ {
return address_match (str, config, USER_ADDRESS_IN_STRING); return address_match (str, notmuch, USER_ADDRESS_IN_STRING);
} }
/* Do any of the addresses configured as one of the user's "primary" /* Do any of the addresses configured as one of the user's "primary"
* or "other" addresses contain the given string. If so, return the * or "other" addresses contain the given string. If so, return the
* matching address, NULL otherwise. */ * matching address, NULL otherwise. */
static const char * static const char *
string_in_user_address (const char *str, notmuch_config_t *config) string_in_user_address (const char *str, notmuch_database_t *notmuch)
{ {
return address_match (str, config, STRING_IN_USER_ADDRESS); return address_match (str, notmuch, STRING_IN_USER_ADDRESS);
} }
/* Is the given address configured as one of the user's "primary" or /* Is the given address configured as one of the user's "primary" or
* "other" addresses. */ * "other" addresses. */
static bool static bool
address_is_users (const char *address, notmuch_config_t *config) address_is_users (const char *address, notmuch_database_t *notmuch)
{ {
return address_match (address, config, STRING_IS_USER_ADDRESS) != NULL; return address_match (address, notmuch, STRING_IS_USER_ADDRESS) != NULL;
} }
/* Scan addresses in 'list'. /* Scan addresses in 'list'.
@ -175,7 +176,7 @@ address_is_users (const char *address, notmuch_config_t *config)
*/ */
static unsigned int static unsigned int
scan_address_list (InternetAddressList *list, scan_address_list (InternetAddressList *list,
notmuch_config_t *config, notmuch_database_t *notmuch,
GMimeMessage *message, GMimeMessage *message,
GMimeAddressType type, GMimeAddressType type,
const char **user_from) const char **user_from)
@ -195,7 +196,7 @@ scan_address_list (InternetAddressList *list,
group = INTERNET_ADDRESS_GROUP (address); group = INTERNET_ADDRESS_GROUP (address);
group_list = internet_address_group_get_members (group); group_list = internet_address_group_get_members (group);
n += scan_address_list (group_list, config, message, type, user_from); n += scan_address_list (group_list, notmuch, message, type, user_from);
} else { } else {
InternetAddressMailbox *mailbox; InternetAddressMailbox *mailbox;
const char *name; const char *name;
@ -206,7 +207,7 @@ scan_address_list (InternetAddressList *list,
name = internet_address_get_name (address); name = internet_address_get_name (address);
addr = internet_address_mailbox_get_addr (mailbox); addr = internet_address_mailbox_get_addr (mailbox);
if (address_is_users (addr, config)) { if (address_is_users (addr, notmuch)) {
if (user_from && *user_from == NULL) if (user_from && *user_from == NULL)
*user_from = addr; *user_from = addr;
} else if (message) { } else if (message) {
@ -324,7 +325,7 @@ get_bcc (GMimeMessage *message)
*/ */
static const char * static const char *
add_recipients_from_message (GMimeMessage *reply, add_recipients_from_message (GMimeMessage *reply,
notmuch_config_t *config, notmuch_database_t *notmuch,
GMimeMessage *message, GMimeMessage *message,
bool reply_all) bool reply_all)
{ {
@ -346,7 +347,7 @@ add_recipients_from_message (GMimeMessage *reply,
recipients = reply_to_map[i].get_header (message); recipients = reply_to_map[i].get_header (message);
n += scan_address_list (recipients, config, reply, n += scan_address_list (recipients, notmuch, reply,
reply_to_map[i].recipient_type, &from_addr); reply_to_map[i].recipient_type, &from_addr);
if (! reply_all && n) { if (! reply_all && n) {
@ -384,7 +385,7 @@ add_recipients_from_message (GMimeMessage *reply,
* Return the address that was found, if any, and NULL otherwise. * Return the address that was found, if any, and NULL otherwise.
*/ */
static const char * static const char *
guess_from_in_received_for (notmuch_config_t *config, const char *received) guess_from_in_received_for (notmuch_database_t *notmuch, const char *received)
{ {
const char *ptr; const char *ptr;
@ -392,7 +393,7 @@ guess_from_in_received_for (notmuch_config_t *config, const char *received)
if (! ptr) if (! ptr)
return NULL; return NULL;
return user_address_in_string (ptr, config); return user_address_in_string (ptr, notmuch);
} }
/* /*
@ -408,7 +409,7 @@ guess_from_in_received_for (notmuch_config_t *config, const char *received)
* Return the address that was found, if any, and NULL otherwise. * Return the address that was found, if any, and NULL otherwise.
*/ */
static const char * static const char *
guess_from_in_received_by (notmuch_config_t *config, const char *received) guess_from_in_received_by (notmuch_database_t *notmuch, const char *received)
{ {
const char *addr; const char *addr;
const char *by = received; const char *by = received;
@ -446,7 +447,7 @@ guess_from_in_received_by (notmuch_config_t *config, const char *received)
*/ */
*(tld - 1) = '.'; *(tld - 1) = '.';
addr = string_in_user_address (domain, config); addr = string_in_user_address (domain, notmuch);
if (addr) { if (addr) {
free (mta); free (mta);
return addr; return addr;
@ -469,12 +470,13 @@ guess_from_in_received_by (notmuch_config_t *config, const char *received)
* Return the address that was found, if any, and NULL otherwise. * Return the address that was found, if any, and NULL otherwise.
*/ */
static const char * static const char *
guess_from_in_received_headers (notmuch_config_t *config, guess_from_in_received_headers (notmuch_message_t *message)
notmuch_message_t *message)
{ {
const char *received, *addr; const char *received, *addr;
char *sanitized; char *sanitized;
notmuch_database_t *notmuch = notmuch_message_get_database (message);
received = notmuch_message_get_header (message, "received"); received = notmuch_message_get_header (message, "received");
if (! received) if (! received)
return NULL; return NULL;
@ -483,9 +485,9 @@ guess_from_in_received_headers (notmuch_config_t *config,
if (! sanitized) if (! sanitized)
return NULL; return NULL;
addr = guess_from_in_received_for (config, sanitized); addr = guess_from_in_received_for (notmuch, sanitized);
if (! addr) if (! addr)
addr = guess_from_in_received_by (config, sanitized); addr = guess_from_in_received_by (notmuch, sanitized);
talloc_free (sanitized); talloc_free (sanitized);
@ -500,7 +502,7 @@ guess_from_in_received_headers (notmuch_config_t *config,
* Return the address that was found, if any, and NULL otherwise. * Return the address that was found, if any, and NULL otherwise.
*/ */
static const char * static const char *
get_from_in_to_headers (notmuch_config_t *config, notmuch_message_t *message) get_from_in_to_headers (notmuch_message_t *message)
{ {
size_t i; size_t i;
const char *tohdr, *addr; const char *tohdr, *addr;
@ -510,11 +512,13 @@ get_from_in_to_headers (notmuch_config_t *config, notmuch_message_t *message)
"Delivered-To", "Delivered-To",
}; };
notmuch_database_t *notmuch = notmuch_message_get_database (message);
for (i = 0; i < ARRAY_SIZE (to_headers); i++) { for (i = 0; i < ARRAY_SIZE (to_headers); i++) {
tohdr = notmuch_message_get_header (message, to_headers[i]); tohdr = notmuch_message_get_header (message, to_headers[i]);
/* Note: tohdr potentially contains a list of email addresses. */ /* Note: tohdr potentially contains a list of email addresses. */
addr = user_address_in_string (tohdr, config); addr = user_address_in_string (tohdr, notmuch);
if (addr) if (addr)
return addr; return addr;
} }
@ -524,7 +528,6 @@ get_from_in_to_headers (notmuch_config_t *config, notmuch_message_t *message)
static GMimeMessage * static GMimeMessage *
create_reply_message (void *ctx, create_reply_message (void *ctx,
notmuch_config_t *config,
notmuch_message_t *message, notmuch_message_t *message,
GMimeMessage *mime_message, GMimeMessage *mime_message,
bool reply_all, bool reply_all,
@ -532,7 +535,7 @@ create_reply_message (void *ctx,
{ {
const char *subject, *from_addr = NULL; const char *subject, *from_addr = NULL;
const char *in_reply_to, *orig_references, *references; const char *in_reply_to, *orig_references, *references;
notmuch_database_t *notmuch = notmuch_message_get_database (message);
/* /*
* Use the below header order for limited headers, "pretty" order * Use the below header order for limited headers, "pretty" order
* otherwise. * otherwise.
@ -558,7 +561,7 @@ create_reply_message (void *ctx,
g_mime_object_set_header (GMIME_OBJECT (reply), "References", references, NULL); g_mime_object_set_header (GMIME_OBJECT (reply), "References", references, NULL);
from_addr = add_recipients_from_message (reply, config, from_addr = add_recipients_from_message (reply, notmuch,
mime_message, reply_all); mime_message, reply_all);
/* The above is all that is needed for limited headers. */ /* The above is all that is needed for limited headers. */
@ -578,7 +581,7 @@ create_reply_message (void *ctx,
* Delivered-To: headers. * Delivered-To: headers.
*/ */
if (from_addr == NULL) if (from_addr == NULL)
from_addr = get_from_in_to_headers (config, message); from_addr = get_from_in_to_headers (message);
/* /*
* Check for a (for <email@add.res>) clause in Received: headers, * Check for a (for <email@add.res>) clause in Received: headers,
@ -586,14 +589,14 @@ create_reply_message (void *ctx,
* of Received: headers * of Received: headers
*/ */
if (from_addr == NULL) if (from_addr == NULL)
from_addr = guess_from_in_received_headers (config, message); from_addr = guess_from_in_received_headers (message);
/* Default to user's primary address. */ /* Default to user's primary address. */
if (from_addr == NULL) if (from_addr == NULL)
from_addr = notmuch_config_get_user_primary_email (config); from_addr = notmuch_config_get (notmuch, NOTMUCH_CONFIG_PRIMARY_EMAIL);
from_addr = talloc_asprintf (ctx, "%s <%s>", from_addr = talloc_asprintf (ctx, "%s <%s>",
notmuch_config_get_user_name (config), notmuch_config_get (notmuch, NOTMUCH_CONFIG_USER_NAME),
from_addr); from_addr);
g_mime_object_set_header (GMIME_OBJECT (reply), "From", from_addr, NULL); g_mime_object_set_header (GMIME_OBJECT (reply), "From", from_addr, NULL);
@ -615,7 +618,7 @@ enum {
}; };
static int static int
do_reply (notmuch_config_t *config, do_reply (notmuch_database_t *notmuch,
notmuch_query_t *query, notmuch_query_t *query,
notmuch_show_params_t *params, notmuch_show_params_t *params,
int format, int format,
@ -641,9 +644,9 @@ do_reply (notmuch_config_t *config,
} }
if (format == FORMAT_JSON) if (format == FORMAT_JSON)
sp = sprinter_json_create (config, stdout); sp = sprinter_json_create (notmuch, stdout);
else else
sp = sprinter_sexp_create (config, stdout); sp = sprinter_sexp_create (notmuch, stdout);
} }
status = notmuch_query_search_messages (query, &messages); status = notmuch_query_search_messages (query, &messages);
@ -655,10 +658,10 @@ do_reply (notmuch_config_t *config,
notmuch_messages_move_to_next (messages)) { notmuch_messages_move_to_next (messages)) {
message = notmuch_messages_get (messages); message = notmuch_messages_get (messages);
if (mime_node_open (config, message, &params->crypto, &node)) if (mime_node_open (notmuch, message, &params->crypto, &node))
return 1; return 1;
reply = create_reply_message (config, config, message, reply = create_reply_message (notmuch, message,
GMIME_MESSAGE (node->part), reply_all, GMIME_MESSAGE (node->part), reply_all,
format == FORMAT_HEADERS_ONLY); format == FORMAT_HEADERS_ONLY);
if (! reply) if (! reply)
@ -675,7 +678,7 @@ do_reply (notmuch_config_t *config,
/* Start the original */ /* Start the original */
sp->map_key (sp, "original"); sp->map_key (sp, "original");
format_part_sprinter (config, sp, node, true, false); format_part_sprinter (notmuch, sp, node, true, false);
/* End */ /* End */
sp->end (sp); sp->end (sp);
@ -700,9 +703,8 @@ do_reply (notmuch_config_t *config,
} }
int int
notmuch_reply_command (notmuch_config_t *config, unused(notmuch_database_t *notmuch), int argc, char *argv[]) notmuch_reply_command (unused(notmuch_config_t *config), notmuch_database_t *notmuch, int argc, char *argv[])
{ {
notmuch_database_t *notmuch;
notmuch_query_t *query; notmuch_query_t *query;
char *query_string; char *query_string;
int opt_index; int opt_index;
@ -743,7 +745,7 @@ notmuch_reply_command (notmuch_config_t *config, unused(notmuch_database_t *notm
notmuch_exit_if_unsupported_format (); notmuch_exit_if_unsupported_format ();
query_string = query_string_from_args (config, argc - opt_index, argv + opt_index); query_string = query_string_from_args (notmuch, argc - opt_index, argv + opt_index);
if (query_string == NULL) { if (query_string == NULL) {
fprintf (stderr, "Out of memory\n"); fprintf (stderr, "Out of memory\n");
return EXIT_FAILURE; return EXIT_FAILURE;
@ -754,10 +756,6 @@ notmuch_reply_command (notmuch_config_t *config, unused(notmuch_database_t *notm
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (notmuch_database_open (notmuch_config_get_database_path (config),
NOTMUCH_DATABASE_MODE_READ_ONLY, &notmuch))
return EXIT_FAILURE;
notmuch_exit_if_unmatched_db_uuid (notmuch); notmuch_exit_if_unmatched_db_uuid (notmuch);
query = notmuch_query_create (notmuch, query_string); query = notmuch_query_create (notmuch, query_string);
@ -766,7 +764,7 @@ notmuch_reply_command (notmuch_config_t *config, unused(notmuch_database_t *notm
return EXIT_FAILURE; return EXIT_FAILURE;
} }
if (do_reply (config, query, &params, format, reply_all) != 0) if (do_reply (notmuch, query, &params, format, reply_all) != 0)
return EXIT_FAILURE; return EXIT_FAILURE;
_notmuch_crypto_cleanup (&params.crypto); _notmuch_crypto_cleanup (&params.crypto);

View file

@ -155,7 +155,7 @@ static command_t commands[] = {
"Show all messages matching the search terms." }, "Show all messages matching the search terms." },
{ "count", notmuch_count_command, NOTMUCH_COMMAND_DATABASE_EARLY, { "count", notmuch_count_command, NOTMUCH_COMMAND_DATABASE_EARLY,
"Count messages matching the search terms." }, "Count messages matching the search terms." },
{ "reply", notmuch_reply_command, NOTMUCH_COMMAND_CONFIG_OPEN, { "reply", notmuch_reply_command, NOTMUCH_COMMAND_DATABASE_EARLY,
"Construct a reply template for a set of messages." }, "Construct a reply template for a set of messages." },
{ "tag", notmuch_tag_command, NOTMUCH_COMMAND_CONFIG_OPEN, { "tag", notmuch_tag_command, NOTMUCH_COMMAND_CONFIG_OPEN,
"Add/remove tags for all messages matching the search terms." }, "Add/remove tags for all messages matching the search terms." },

View file

@ -210,4 +210,62 @@ count2=$(notmuch count --lastmod '*' | cut -f3)
restore_config restore_config
test_expect_success "test '$count2 -gt $count1'" test_expect_success "test '$count2 -gt $count1'"
add_message '[from]="Sender <sender@example.com>"' \
[to]=test_suite@notmuchmail.org \
'[cc]="Other Parties <cc@example.com>"' \
[subject]=notmuch-reply-test \
'[date]="Tue, 05 Jan 2010 15:43:56 -0000"' \
'[body]="reply with CC"'
cat <<EOF > EXPECTED
Before:
After:
From: Notmuch Test Suite <test_suite@notmuchmail.org>
Subject: Re: notmuch-reply-test
To: Sender <sender@example.com>
Cc: Other Parties <cc@example.com>
In-Reply-To: <${gen_msg_id}>
References: <${gen_msg_id}>
On Tue, 05 Jan 2010 15:43:56 -0000, Sender <sender@example.com> wrote:
> reply with CC
EOF
test_begin_subtest "reply with saved query from config file"
backup_config
query_name="test${RANDOM}"
printf "Before:\n" > OUTPUT
notmuch reply query:$query_name 2>&1 >> OUTPUT
printf "\n[query]\n${query_name} = id:${gen_msg_id}\n" >> notmuch-config
printf "After:\n" >> OUTPUT
notmuch reply query:$query_name >> OUTPUT
restore_config
test_expect_equal_file EXPECTED OUTPUT
test_begin_subtest "reply with saved query from config file (xdg)"
backup_config
query_name="test${RANDOM}"
xdg_config
printf "Before:\n" > OUTPUT
notmuch reply query:$query_name 2>&1 >> OUTPUT
printf "\n[query]\n${query_name} = id:${gen_msg_id}\n" >> ${CONFIG_PATH}
printf "After:\n" >> OUTPUT
notmuch reply query:$query_name >> OUTPUT
restore_config
test_expect_equal_file EXPECTED OUTPUT
test_begin_subtest "reply with saved query from config file (xdg+profile)"
backup_config
query_name="test${RANDOM}"
xdg_config $query_name
printf "Before:\n" > OUTPUT
notmuch reply query:$query_name 2>&1 >> OUTPUT
printf "\n[query]\n${query_name} = id:${gen_msg_id}\n" >> ${CONFIG_PATH}
printf "After:\n" >> OUTPUT
notmuch reply query:$query_name >> OUTPUT
restore_config
test_expect_equal_file EXPECTED OUTPUT
test_done test_done