cli: address: Do not output duplicate addresses

This filters out duplicate addresses from address command output.

It also also adds tests for the address command.

The code here is an extended version of a patch from Jani Nikula.
This commit is contained in:
Michal Sojka 2014-11-05 01:25:57 +01:00 committed by David Bremner
parent 5c32365d87
commit 4176e527fc
3 changed files with 141 additions and 2 deletions

View file

@ -11,7 +11,7 @@ DESCRIPTION
===========
Search for messages matching the given search terms, and display the
addresses from them.
addresses from them. Duplicate addresses are filtered out.
See **notmuch-search-terms(7)** for details of the supported syntax for
<search-terms>.

View file

@ -53,6 +53,7 @@ typedef struct {
int offset;
int limit;
int dupe;
GHashTable *addresses;
} search_context_t;
typedef struct {
@ -240,6 +241,28 @@ do_search_threads (search_context_t *ctx)
return 0;
}
/* Returns TRUE iff name and addr is duplicate. If not, stores the
* name/addr pair in order to detect subsequent duplicates. */
static notmuch_bool_t
is_duplicate (const search_context_t *ctx, const char *name, const char *addr)
{
notmuch_bool_t duplicate;
char *key;
key = talloc_asprintf (ctx->format, "%s <%s>", name, addr);
if (! key)
return FALSE;
duplicate = g_hash_table_lookup_extended (ctx->addresses, key, NULL, NULL);
if (! duplicate)
g_hash_table_insert (ctx->addresses, key, NULL);
else
talloc_free (key);
return duplicate;
}
static void
print_mailbox (const search_context_t *ctx, const mailbox_t *mailbox)
{
@ -274,7 +297,8 @@ print_mailbox (const search_context_t *ctx, const mailbox_t *mailbox)
/* Print addresses from InternetAddressList. */
static void
process_address_list (const search_context_t *ctx, InternetAddressList *list)
process_address_list (const search_context_t *ctx,
InternetAddressList *list)
{
InternetAddress *address;
int i;
@ -298,6 +322,9 @@ process_address_list (const search_context_t *ctx, InternetAddressList *list)
.addr = internet_address_mailbox_get_addr (mailbox),
};
if (is_duplicate (ctx, mbx.name, mbx.addr))
continue;
print_mailbox (ctx, &mbx);
}
}
@ -321,6 +348,13 @@ process_address_header (const search_context_t *ctx, const char *value)
g_object_unref (list);
}
/* Destructor for talloc-allocated GHashTable keys and values. */
static void
_talloc_free_for_g_hash (void *ptr)
{
talloc_free (ptr);
}
static int
_count_filenames (notmuch_message_t *message)
{
@ -673,8 +707,14 @@ notmuch_address_command (notmuch_config_t *config, int argc, char *argv[])
argc - opt_index, argv + opt_index))
return EXIT_FAILURE;
ctx->addresses = g_hash_table_new_full (g_str_hash, g_str_equal,
_talloc_free_for_g_hash, NULL);
ret = do_search_messages (ctx);
g_hash_table_unref (ctx->addresses);
_notmuch_search_cleanup (ctx);
return ret ? EXIT_FAILURE : EXIT_SUCCESS;

99
test/T095-address.sh Executable file
View file

@ -0,0 +1,99 @@
#!/usr/bin/env bash
test_description='"notmuch address" in several variants'
. ./test-lib.sh
add_email_corpus
test_begin_subtest "--output=sender"
notmuch address --output=sender '*' >OUTPUT
cat <<EOF >EXPECTED
François Boulogne <boulogne.f@gmail.com>
Olivier Berger <olivier.berger@it-sudparis.eu>
Chris Wilson <chris@chris-wilson.co.uk>
Carl Worth <cworth@cworth.org>
Alexander Botero-Lowry <alex.boterolowry@gmail.com>
Keith Packard <keithp@keithp.com>
Jjgod Jiang <gzjjgod@gmail.com>
Rolland Santimano <rollandsantimano@yahoo.com>
Jan Janak <jan@ryngle.com>
Stewart Smith <stewart@flamingspork.com>
Lars Kellogg-Stedman <lars@seas.harvard.edu>
Alex Botero-Lowry <alex.boterolowry@gmail.com>
Ingmar Vanhassel <ingmar@exherbo.org>
Aron Griffis <agriffis@n01se.net>
Adrian Perez de Castro <aperez@igalia.com>
Israel Herraiz <isra@herraiz.org>
Mikhail Gusarov <dottedmag@dottedmag.net>
EOF
test_expect_equal_file OUTPUT EXPECTED
test_begin_subtest "--output=sender --format=json"
notmuch address --output=sender --format=json '*' >OUTPUT
cat <<EOF >EXPECTED
[{"name": "François Boulogne", "address": "boulogne.f@gmail.com", "name-addr": "François Boulogne <boulogne.f@gmail.com>"},
{"name": "Olivier Berger", "address": "olivier.berger@it-sudparis.eu", "name-addr": "Olivier Berger <olivier.berger@it-sudparis.eu>"},
{"name": "Chris Wilson", "address": "chris@chris-wilson.co.uk", "name-addr": "Chris Wilson <chris@chris-wilson.co.uk>"},
{"name": "Carl Worth", "address": "cworth@cworth.org", "name-addr": "Carl Worth <cworth@cworth.org>"},
{"name": "Alexander Botero-Lowry", "address": "alex.boterolowry@gmail.com", "name-addr": "Alexander Botero-Lowry <alex.boterolowry@gmail.com>"},
{"name": "Keith Packard", "address": "keithp@keithp.com", "name-addr": "Keith Packard <keithp@keithp.com>"},
{"name": "Jjgod Jiang", "address": "gzjjgod@gmail.com", "name-addr": "Jjgod Jiang <gzjjgod@gmail.com>"},
{"name": "Rolland Santimano", "address": "rollandsantimano@yahoo.com", "name-addr": "Rolland Santimano <rollandsantimano@yahoo.com>"},
{"name": "Jan Janak", "address": "jan@ryngle.com", "name-addr": "Jan Janak <jan@ryngle.com>"},
{"name": "Stewart Smith", "address": "stewart@flamingspork.com", "name-addr": "Stewart Smith <stewart@flamingspork.com>"},
{"name": "Lars Kellogg-Stedman", "address": "lars@seas.harvard.edu", "name-addr": "Lars Kellogg-Stedman <lars@seas.harvard.edu>"},
{"name": "Alex Botero-Lowry", "address": "alex.boterolowry@gmail.com", "name-addr": "Alex Botero-Lowry <alex.boterolowry@gmail.com>"},
{"name": "Ingmar Vanhassel", "address": "ingmar@exherbo.org", "name-addr": "Ingmar Vanhassel <ingmar@exherbo.org>"},
{"name": "Aron Griffis", "address": "agriffis@n01se.net", "name-addr": "Aron Griffis <agriffis@n01se.net>"},
{"name": "Adrian Perez de Castro", "address": "aperez@igalia.com", "name-addr": "Adrian Perez de Castro <aperez@igalia.com>"},
{"name": "Israel Herraiz", "address": "isra@herraiz.org", "name-addr": "Israel Herraiz <isra@herraiz.org>"},
{"name": "Mikhail Gusarov", "address": "dottedmag@dottedmag.net", "name-addr": "Mikhail Gusarov <dottedmag@dottedmag.net>"}]
EOF
test_expect_equal_file OUTPUT EXPECTED
test_begin_subtest "--output=recipients"
notmuch address --output=recipients '*' >OUTPUT
cat <<EOF >EXPECTED
Allan McRae <allan@archlinux.org>
"Discussion about the Arch User Repository (AUR)" <aur-general@archlinux.org>
olivier.berger@it-sudparis.eu
notmuch@notmuchmail.org
notmuch <notmuch@notmuchmail.org>
Keith Packard <keithp@keithp.com>
Mikhail Gusarov <dottedmag@dottedmag.net>
EOF
test_expect_equal_file OUTPUT EXPECTED
test_begin_subtest "--output=sender --output=recipients"
notmuch address --output=sender --output=recipients '*' >OUTPUT
cat <<EOF >EXPECTED
François Boulogne <boulogne.f@gmail.com>
Allan McRae <allan@archlinux.org>
"Discussion about the Arch User Repository (AUR)" <aur-general@archlinux.org>
Olivier Berger <olivier.berger@it-sudparis.eu>
olivier.berger@it-sudparis.eu
Chris Wilson <chris@chris-wilson.co.uk>
notmuch@notmuchmail.org
Carl Worth <cworth@cworth.org>
Alexander Botero-Lowry <alex.boterolowry@gmail.com>
Keith Packard <keithp@keithp.com>
Jjgod Jiang <gzjjgod@gmail.com>
Rolland Santimano <rollandsantimano@yahoo.com>
Jan Janak <jan@ryngle.com>
Stewart Smith <stewart@flamingspork.com>
Lars Kellogg-Stedman <lars@seas.harvard.edu>
notmuch <notmuch@notmuchmail.org>
Alex Botero-Lowry <alex.boterolowry@gmail.com>
Ingmar Vanhassel <ingmar@exherbo.org>
Aron Griffis <agriffis@n01se.net>
Adrian Perez de Castro <aperez@igalia.com>
Israel Herraiz <isra@herraiz.org>
Mikhail Gusarov <dottedmag@dottedmag.net>
EOF
test_expect_equal_file OUTPUT EXPECTED
test_begin_subtest "without --output"
notmuch address '*' >OUTPUT
# Use EXPECTED from previous subtest
test_expect_equal_file OUTPUT EXPECTED
test_done