mirror of
https://git.notmuchmail.org/git/notmuch
synced 2024-11-25 04:18:08 +01:00
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:
parent
5c32365d87
commit
4176e527fc
3 changed files with 141 additions and 2 deletions
|
@ -11,7 +11,7 @@ DESCRIPTION
|
||||||
===========
|
===========
|
||||||
|
|
||||||
Search for messages matching the given search terms, and display the
|
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
|
See **notmuch-search-terms(7)** for details of the supported syntax for
|
||||||
<search-terms>.
|
<search-terms>.
|
||||||
|
|
|
@ -53,6 +53,7 @@ typedef struct {
|
||||||
int offset;
|
int offset;
|
||||||
int limit;
|
int limit;
|
||||||
int dupe;
|
int dupe;
|
||||||
|
GHashTable *addresses;
|
||||||
} search_context_t;
|
} search_context_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -240,6 +241,28 @@ do_search_threads (search_context_t *ctx)
|
||||||
return 0;
|
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
|
static void
|
||||||
print_mailbox (const search_context_t *ctx, const mailbox_t *mailbox)
|
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. */
|
/* Print addresses from InternetAddressList. */
|
||||||
static void
|
static void
|
||||||
process_address_list (const search_context_t *ctx, InternetAddressList *list)
|
process_address_list (const search_context_t *ctx,
|
||||||
|
InternetAddressList *list)
|
||||||
{
|
{
|
||||||
InternetAddress *address;
|
InternetAddress *address;
|
||||||
int i;
|
int i;
|
||||||
|
@ -298,6 +322,9 @@ process_address_list (const search_context_t *ctx, InternetAddressList *list)
|
||||||
.addr = internet_address_mailbox_get_addr (mailbox),
|
.addr = internet_address_mailbox_get_addr (mailbox),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (is_duplicate (ctx, mbx.name, mbx.addr))
|
||||||
|
continue;
|
||||||
|
|
||||||
print_mailbox (ctx, &mbx);
|
print_mailbox (ctx, &mbx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -321,6 +348,13 @@ process_address_header (const search_context_t *ctx, const char *value)
|
||||||
g_object_unref (list);
|
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
|
static int
|
||||||
_count_filenames (notmuch_message_t *message)
|
_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))
|
argc - opt_index, argv + opt_index))
|
||||||
return EXIT_FAILURE;
|
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);
|
ret = do_search_messages (ctx);
|
||||||
|
|
||||||
|
g_hash_table_unref (ctx->addresses);
|
||||||
|
|
||||||
|
|
||||||
_notmuch_search_cleanup (ctx);
|
_notmuch_search_cleanup (ctx);
|
||||||
|
|
||||||
return ret ? EXIT_FAILURE : EXIT_SUCCESS;
|
return ret ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||||
|
|
99
test/T095-address.sh
Executable file
99
test/T095-address.sh
Executable 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
|
Loading…
Reference in a new issue