[PATCH] Add --include-duplicates option to a couple of commands.

Carl Worth cworth at cworth.org
Mon Jan 24 22:39:24 PST 2011


This adds new functionality under the names of:

	notmuch search --output=files --include-duplicates
	notmuch show --include-duplicates
	notmuch show --format=json --include-duplicates

These new commands behave similarly to the existing commands without
the --include-duplicates agument. The difference is that with the new
argument any duplicate mail files will be included in the
output. Here, files are considered duplicates if they contain
identical contents for the Message-Id header, (regardless of any other
differences in the content of the file). Without the
--include-duplicates argument, these commands would emit a single,
arbitrary file in the face of duplicates.

WARNING: This commit is not yet ready to be pushed to the notmuch
repository. There are at least two problems with the commit so far:

	1. Nothing has been documented yet.

	   Fixing this shouldn't be too hard. It's mostly just taking
	   the text from above and shoving it into the
	   documentation. I can do this easily enough myself.

	2. show --format=json --include-duplicates doesn't work yet

	   This is a more serious problem. I believe the JSON output
	   with this patch is not correct and will likely break a
	   client trying to consume it. It inserts the duplicate
	   message into an array next to the existing message. Our
	   current JSON schema isn't documented formally that I could
	   find, except for a comment in the emacs code that consumes
	   it:

		A thread is a forest or list of trees. A tree is a two
		element list where the first element is a message, and
		the second element is a possibly empty forest of
		replies.

	   I believe this commit breaks the "two-element list"
	   expectation. What we would want instead is the duplicate
	   message to appear as a peer next to the original message,
	   (and then perhaps have replies appear only to one of the
	   messages).

My current need for --include-duplicates was recently satisfied, so I
won't likely pursue this further for now. But I wanted to put this
code out rather than losing it.

If someone wants to fix the patch to do the "right thing" with the
JSON output, then that would be great.

ALSO NOTE: I left the
json.expected-output/notmuch-show-thread-format-json-maildir-storage
out of this commit. It has lines in it that are too long to be sent
via git-send-email.
---
 notmuch-search.c                                   |   30 +++++-
 notmuch-show.c                                     |   61 +++++++++--
 test/basic                                         |    2 +-
 test/json                                          |   33 ++++++-
 ...-show-thread-include-duplicates-maildir-storage |   94 ++++++++++++++++
 .../notmuch-show-thread-maildir-storage            |   47 ++++++++
 test/search-output                                 |  113 ++++++++++++++++++++
 7 files changed, 361 insertions(+), 19 deletions(-)
 create mode 100644 test/json.expected-output/notmuch-show-thread-include-duplicates-maildir-storage
 create mode 100644 test/json.expected-output/notmuch-show-thread-maildir-storage

diff --git a/notmuch-search.c b/notmuch-search.c
index c628b36..6d032c2 100644
--- a/notmuch-search.c
+++ b/notmuch-search.c
@@ -247,7 +247,8 @@ static int
 do_search_messages (const void *ctx,
 		    const search_format_t *format,
 		    notmuch_query_t *query,
-		    output_t output)
+		    output_t output,
+		    notmuch_bool_t include_duplicates)
 {
     notmuch_message_t *message;
     notmuch_messages_t *messages;
@@ -269,8 +270,25 @@ do_search_messages (const void *ctx,
 	    fputs (format->item_sep, stdout);
 
 	if (output == OUTPUT_FILES) {
-	    format->item_id (ctx, "",
-			     notmuch_message_get_filename (message));
+	    if (include_duplicates) {
+		notmuch_filenames_t *filenames;
+		int first_filename = 1;
+
+		for (filenames = notmuch_message_get_filenames (message);
+		     notmuch_filenames_valid (filenames);
+		     notmuch_filenames_move_to_next (filenames))
+		{
+		    if (! first_filename)
+			fputs (format->item_sep, stdout);
+		    first_filename = 0;
+
+		    format->item_id (ctx, "",
+				     notmuch_filenames_get (filenames));
+		}
+	    } else {
+		format->item_id (ctx, "",
+				 notmuch_message_get_filename (message));
+	    }
 	} else { /* output == OUTPUT_MESSAGES */
 	    format->item_id (ctx, "id:",
 			     notmuch_message_get_message_id (message));
@@ -352,6 +370,7 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
     const search_format_t *format = &format_text;
     int i, ret;
     output_t output = OUTPUT_SUMMARY;
+    notmuch_bool_t include_duplicates = 0;
 
     for (i = 0; i < argc && argv[i][0] == '-'; i++) {
 	if (strcmp (argv[i], "--") == 0) {
@@ -394,6 +413,8 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
 		fprintf (stderr, "Invalid value for --output: %s\n", opt);
 		return 1;
 	    }
+	} else if (STRNCMP_LITERAL (argv[i], "--include-duplicates") == 0) {
+	    include_duplicates = 1;
 	} else {
 	    fprintf (stderr, "Unrecognized option: %s\n", argv[i]);
 	    return 1;
@@ -438,7 +459,8 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
 	break;
     case OUTPUT_MESSAGES:
     case OUTPUT_FILES:
-	ret = do_search_messages (ctx, format, query, output);
+	ret = do_search_messages (ctx, format, query, output,
+				  include_duplicates);
 	break;
     case OUTPUT_TAGS:
 	ret = do_search_tags (ctx, notmuch, format, query);
diff --git a/notmuch-show.c b/notmuch-show.c
index ef421ec..3fbbeac 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -463,7 +463,11 @@ format_part_json (GMimeObject *part, int *part_count)
 }
 
 static void
-show_message (void *ctx, const show_format_t *format, notmuch_message_t *message, int indent)
+show_message (void *ctx,
+	      const show_format_t *format,
+	      notmuch_message_t *message,
+	      const char *filename,
+	      int indent)
 {
     fputs (format->message_start, stdout);
     if (format->message)
@@ -476,18 +480,22 @@ show_message (void *ctx, const show_format_t *format, notmuch_message_t *message
 
     fputs (format->body_start, stdout);
     if (format->part)
-	show_message_body (notmuch_message_get_filename (message), format->part);
+	show_message_body (filename, format->part);
     fputs (format->body_end, stdout);
 
     fputs (format->message_end, stdout);
 }
 
-
 static void
-show_messages (void *ctx, const show_format_t *format, notmuch_messages_t *messages, int indent,
-	       notmuch_bool_t entire_thread)
+show_messages (void *ctx,
+	       const show_format_t *format,
+	       notmuch_messages_t *messages,
+	       int indent,
+	       notmuch_bool_t entire_thread,
+	       notmuch_bool_t include_duplicates)
 {
     notmuch_message_t *message;
+    const char *filename;
     notmuch_bool_t match;
     int first_set = 1;
     int next_indent;
@@ -498,7 +506,7 @@ show_messages (void *ctx, const show_format_t *format, notmuch_messages_t *messa
 	 notmuch_messages_valid (messages);
 	 notmuch_messages_move_to_next (messages))
     {
-	if (!first_set)
+	if (! first_set)
 	    fputs (format->message_set_sep, stdout);
 	first_set = 0;
 
@@ -511,14 +519,38 @@ show_messages (void *ctx, const show_format_t *format, notmuch_messages_t *messa
 	next_indent = indent;
 
 	if (match || entire_thread) {
-	    show_message (ctx, format, message, indent);
+
+	    if (include_duplicates) {
+		notmuch_filenames_t *filenames;
+		int first_filename = 1;
+
+		for (filenames = notmuch_message_get_filenames (message);
+		     notmuch_filenames_valid (filenames);
+		     notmuch_filenames_move_to_next (filenames))
+		{
+		    if (! first_filename) {
+			fputs (format->message_set_end, stdout);
+			fputs (format->message_set_sep, stdout);
+			fputs (format->message_set_start, stdout);
+		    }
+		    first_filename = 0;
+
+		    filename = notmuch_filenames_get (filenames);
+
+		    show_message (ctx, format, message, filename, indent);
+		}
+	    } else {
+		filename = notmuch_message_get_filename (message);
+		show_message (ctx, format, message, filename, indent);
+	    }
+
 	    next_indent = indent + 1;
 
 	    fputs (format->message_set_sep, stdout);
 	}
 
 	show_messages (ctx, format, notmuch_message_get_replies (message),
-		       next_indent, entire_thread);
+		       next_indent, entire_thread, include_duplicates);
 
 	notmuch_message_destroy (message);
 
@@ -579,7 +611,8 @@ static int
 do_show (void *ctx,
 	 notmuch_query_t *query,
 	 const show_format_t *format,
-	 int entire_thread)
+	 notmuch_bool_t entire_thread,
+	 notmuch_bool_t include_duplicates)
 {
     notmuch_threads_t *threads;
     notmuch_thread_t *thread;
@@ -604,7 +637,8 @@ do_show (void *ctx,
 	    fputs (format->message_set_sep, stdout);
 	first_toplevel = 0;
 
-	show_messages (ctx, format, messages, 0, entire_thread);
+	show_messages (ctx, format, messages, 0,
+		       entire_thread, include_duplicates);
 
 	notmuch_thread_destroy (thread);
 
@@ -624,7 +658,8 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))
     char *query_string;
     char *opt;
     const show_format_t *format = &format_text;
-    int entire_thread = 0;
+    notmuch_bool_t entire_thread = 0;
+    notmuch_bool_t include_duplicates = 0;
     int i;
     int raw = 0;
 
@@ -650,6 +685,8 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))
 	    }
 	} else if (STRNCMP_LITERAL (argv[i], "--entire-thread") == 0) {
 	    entire_thread = 1;
+	} else if (STRNCMP_LITERAL (argv[i], "--include-duplicates") == 0) {
+	    include_duplicates = 1;
 	} else {
 	    fprintf (stderr, "Unrecognized option: %s\n", argv[i]);
 	    return 1;
@@ -688,7 +725,7 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))
     if (raw)
 	return do_show_raw (ctx, query);
     else
-	return do_show (ctx, query, format, entire_thread);
+	return do_show (ctx, query, format, entire_thread, include_duplicates);
 
     notmuch_query_destroy (query);
     notmuch_database_close (notmuch);
diff --git a/test/basic b/test/basic
index e1269e2..a8e2dd7 100755
--- a/test/basic
+++ b/test/basic
@@ -52,7 +52,7 @@ test_expect_code 2 'failure to clean up causes the test to fail' '
 # Ensure that all tests are being run
 test_begin_subtest 'Ensure that all available tests will be run by notmuch-test'
 tests_in_suite=$(grep TESTS= ../notmuch-test | sed -e "s/TESTS=\"\(.*\)\"/\1/" | tr " " "\n" | sort)
-available=$(ls -1 ../ | grep -v -E "^(aggregate-results.sh|Makefile|Makefile.local|notmuch-test|README|test-lib.sh|test-results|tmp.*|valgrind|corpus*|emacs.expected-output|smtp-dummy|smtp-dummy.c|test-verbose|test.expected-output|.*~)" | sort)
+available=$(ls -1 ../ | grep -v -E "^(aggregate-results.sh|Makefile|Makefile.local|notmuch-test|README|test-lib.sh|test-results|tmp.*|valgrind|corpus*|emacs.expected-output|smtp-dummy|smtp-dummy.c|test-verbose|.*.expected-output|.*~)" | sort)
 test_expect_equal "$tests_in_suite" "$available"
 
 EXPECTED=../test.expected-output
diff --git a/test/json b/test/json
index 7fe2a27..f2349cc 100755
--- a/test/json
+++ b/test/json
@@ -2,12 +2,21 @@
 test_description="--format=json output"
 . ./test-lib.sh
 
-test_begin_subtest "Show message: json"
+EXPECTED=../json.expected-output
+
+add_email_corpus
+
+# Setup a duplicate message for testing
+cp "$MAIL_DIR/cur/03:2," "$MAIL_DIR/cur/03:2-duplicate,"
+increment_mtime "$MAIL_DIR/cur"
+notmuch new >/dev/null
+
+test_begin_subtest "Show single message: --format=json"
 add_message "[subject]=\"json-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"json-show-message\""
 output=$(notmuch show --format=json "json-show-message")
 test_expect_equal "$output" "[[[{\"id\": \"${gen_msg_id}\", \"match\": true, \"filename\": \"${gen_msg_filename}\", \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Notmuch Test Suite <test_suite at notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite at notmuchmail.org>\", \"Cc\": \"\", \"Bcc\": \"\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 -0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"json-show-message\n\"}]}, []]]]"
 
-test_begin_subtest "Search message: json"
+test_begin_subtest "Search single message: --format=json"
 add_message "[subject]=\"json-search-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"json-search-message\""
 output=$(notmuch search --format=json "json-search-message" | notmuch_search_sanitize)
 test_expect_equal "$output" "[{\"thread\": \"XXX\",
@@ -18,6 +27,26 @@ test_expect_equal "$output" "[{\"thread\": \"XXX\",
 \"subject\": \"json-search-subject\",
 \"tags\": [\"inbox\", \"unread\"]}]"
 
+test_begin_subtest "Show thread:"
+output=$(notmuch show id:20091117190054.GU3165 at dottiness.seas.harvard.edu)
+expected=$(cat $EXPECTED/notmuch-show-thread-maildir-storage)
+test_expect_equal "$output" "$expected"
+
+test_begin_subtest "Show thread: --include-duplicates"
+output=$(notmuch show --include-duplicates id:20091117190054.GU3165 at dottiness.seas.harvard.edu)
+expected=$(cat $EXPECTED/notmuch-show-thread-include-duplicates-maildir-storage)
+test_expect_equal "$output" "$expected"
+
+test_begin_subtest "Show thread: --format=json"
+output=$(notmuch show --format=json id:20091117190054.GU3165 at dottiness.seas.harvard.edu)
+expected=$(cat $EXPECTED/notmuch-show-thread-format-json-maildir-storage)
+test_expect_equal "$output" "$expected"
+
+test_begin_subtest "Show thread: --format=json --include-duplicates"
+output=$(notmuch show --format=json --include-duplicates id:20091117190054.GU3165 at dottiness.seas.harvard.edu)
+expected=$(cat $EXPECTED/notmuch-show-thread-format-json-include-duplicates-maildir-storage)
+test_expect_equal "$output" "$expected"
+
 test_begin_subtest "Search by subject (utf-8):"
 add_message [subject]=utf8-sübjéct "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\""
 output=$(notmuch search subject:utf8-sübjéct | notmuch_search_sanitize)
diff --git a/test/json.expected-output/notmuch-show-thread-include-duplicates-maildir-storage b/test/json.expected-output/notmuch-show-thread-include-duplicates-maildir-storage
new file mode 100644
index 0000000..d6e8816
--- /dev/null
+++ b/test/json.expected-output/notmuch-show-thread-include-duplicates-maildir-storage
@@ -0,0 +1,94 @@
+message{ id:20091117190054.GU3165 at dottiness.seas.harvard.edu depth:0 match:1 filename:/home/cworth/src/notmuch/test/tmp.json/mail/cur/03:2,
+header{
+Lars Kellogg-Stedman <lars at seas.harvard.edu> (2009-11-17) (inbox unread)
+Subject: [notmuch] Working with Maildir storage?
+From: Lars Kellogg-Stedman <lars at seas.harvard.edu>
+To: notmuch at notmuchmail.org
+Date: Tue, 17 Nov 2009 14:00:54 -0500
+header}
+body{
+part{ ID: 1, Content-type: text/plain
+I saw the LWN article and decided to take a look at notmuch.  I'm
+currently using mutt and mairix to index and read a collection of
+Maildir mail folders (around 40,000 messages total).
+
+notmuch indexed the messages without complaint, but my attempt at
+searching bombed out. Running, for example:
+
+  notmuch search storage
+
+Resulted in 4604 lines of errors along the lines of:
+
+  Error opening
+  /home/lars/Mail/read-messages.2008/cur/1246413773.24928_27334.hostname,U=3026:2,S:
+  Too many open files
+
+I'm curious if this is expected behavior (i.e., notmuch does not work
+with Maildir) or if something else is going on.
+
+Cheers,
+
+-- 
+Lars Kellogg-Stedman <lars at seas.harvard.edu>
+Senior Technologist, Computing and Information Technology
+Harvard University School of Engineering and Applied Sciences
+
+part}
+part{ ID: 2, Content-type: application/pgp-signature
+Non-text part: application/pgp-signature
+part}
+part{ ID: 3, Content-type: text/plain
+_______________________________________________
+notmuch mailing list
+notmuch at notmuchmail.org
+http://notmuchmail.org/mailman/listinfo/notmuch
+part}
+body}
+message}
+message{ id:20091117190054.GU3165 at dottiness.seas.harvard.edu depth:0 match:1 filename:/home/cworth/src/notmuch/test/tmp.json/mail/cur/03:2,
+header{
+Lars Kellogg-Stedman <lars at seas.harvard.edu> (2009-11-17) (inbox unread)
+Subject: [notmuch] Working with Maildir storage?
+From: Lars Kellogg-Stedman <lars at seas.harvard.edu>
+To: notmuch at notmuchmail.org
+Date: Tue, 17 Nov 2009 14:00:54 -0500
+header}
+body{
+part{ ID: 1, Content-type: text/plain
+I saw the LWN article and decided to take a look at notmuch.  I'm
+currently using mutt and mairix to index and read a collection of
+Maildir mail folders (around 40,000 messages total).
+
+notmuch indexed the messages without complaint, but my attempt at
+searching bombed out. Running, for example:
+
+  notmuch search storage
+
+Resulted in 4604 lines of errors along the lines of:
+
+  Error opening
+  /home/lars/Mail/read-messages.2008/cur/1246413773.24928_27334.hostname,U=3026:2,S:
+  Too many open files
+
+I'm curious if this is expected behavior (i.e., notmuch does not work
+with Maildir) or if something else is going on.
+
+Cheers,
+
+-- 
+Lars Kellogg-Stedman <lars at seas.harvard.edu>
+Senior Technologist, Computing and Information Technology
+Harvard University School of Engineering and Applied Sciences
+
+part}
+part{ ID: 2, Content-type: application/pgp-signature
+Non-text part: application/pgp-signature
+part}
+part{ ID: 3, Content-type: text/plain
+_______________________________________________
+notmuch mailing list
+notmuch at notmuchmail.org
+http://notmuchmail.org/mailman/listinfo/notmuch
+part}
+body}
+message}
diff --git a/test/json.expected-output/notmuch-show-thread-maildir-storage b/test/json.expected-output/notmuch-show-thread-maildir-storage
new file mode 100644
index 0000000..77fefa8
--- /dev/null
+++ b/test/json.expected-output/notmuch-show-thread-maildir-storage
@@ -0,0 +1,47 @@
+message{ id:20091117190054.GU3165 at dottiness.seas.harvard.edu depth:0 match:1 filename:/home/cworth/src/notmuch/test/tmp.json/mail/cur/03:2,
+header{
+Lars Kellogg-Stedman <lars at seas.harvard.edu> (2009-11-17) (inbox unread)
+Subject: [notmuch] Working with Maildir storage?
+From: Lars Kellogg-Stedman <lars at seas.harvard.edu>
+To: notmuch at notmuchmail.org
+Date: Tue, 17 Nov 2009 14:00:54 -0500
+header}
+body{
+part{ ID: 1, Content-type: text/plain
+I saw the LWN article and decided to take a look at notmuch.  I'm
+currently using mutt and mairix to index and read a collection of
+Maildir mail folders (around 40,000 messages total).
+
+notmuch indexed the messages without complaint, but my attempt at
+searching bombed out. Running, for example:
+
+  notmuch search storage
+
+Resulted in 4604 lines of errors along the lines of:
+
+  Error opening
+  /home/lars/Mail/read-messages.2008/cur/1246413773.24928_27334.hostname,U=3026:2,S:
+  Too many open files
+
+I'm curious if this is expected behavior (i.e., notmuch does not work
+with Maildir) or if something else is going on.
+
+Cheers,
+
+-- 
+Lars Kellogg-Stedman <lars at seas.harvard.edu>
+Senior Technologist, Computing and Information Technology
+Harvard University School of Engineering and Applied Sciences
+
+part}
+part{ ID: 2, Content-type: application/pgp-signature
+Non-text part: application/pgp-signature
+part}
+part{ ID: 3, Content-type: text/plain
+_______________________________________________
+notmuch mailing list
+notmuch at notmuchmail.org
+http://notmuchmail.org/mailman/listinfo/notmuch
+part}
+body}
+message}
diff --git a/test/search-output b/test/search-output
index b414993..69d4c89 100755
--- a/test/search-output
+++ b/test/search-output
@@ -4,6 +4,11 @@ test_description='various settings for "notmuch search --output="'
 
 add_email_corpus
 
+# Setup a duplicate message for testing
+cp "$MAIL_DIR/cur/01:2," "$MAIL_DIR/cur/01:2-duplicate,"
+increment_mtime "$MAIL_DIR/cur"
+notmuch new >/dev/null
+
 test_begin_subtest "notmuch search --output=threads"
 output=$(notmuch search --output=threads '*' | sed -e s/thread:.*/thread:THREADID/)
 test_expect_equal "$output" "thread:THREADID
@@ -213,6 +218,60 @@ MAIL_DIR/cur/07:2,
 MAIL_DIR/cur/02:2,
 MAIL_DIR/cur/01:2,"
 
+test_begin_subtest "notmuch search --output=files --include-duplicates"
+output=$(notmuch search --output=files --include-duplicates '*' | sed -e "s,$MAIL_DIR,MAIL_DIR,")
+test_expect_equal "$output" "MAIL_DIR/cur/50:2,
+MAIL_DIR/cur/49:2,
+MAIL_DIR/cur/48:2,
+MAIL_DIR/cur/47:2,
+MAIL_DIR/cur/46:2,
+MAIL_DIR/cur/45:2,
+MAIL_DIR/cur/44:2,
+MAIL_DIR/cur/43:2,
+MAIL_DIR/cur/42:2,
+MAIL_DIR/cur/41:2,
+MAIL_DIR/cur/40:2,
+MAIL_DIR/cur/39:2,
+MAIL_DIR/cur/38:2,
+MAIL_DIR/cur/37:2,
+MAIL_DIR/cur/36:2,
+MAIL_DIR/cur/35:2,
+MAIL_DIR/cur/34:2,
+MAIL_DIR/cur/33:2,
+MAIL_DIR/cur/32:2,
+MAIL_DIR/cur/31:2,
+MAIL_DIR/cur/30:2,
+MAIL_DIR/cur/29:2,
+MAIL_DIR/cur/28:2,
+MAIL_DIR/cur/27:2,
+MAIL_DIR/cur/26:2,
+MAIL_DIR/cur/25:2,
+MAIL_DIR/cur/24:2,
+MAIL_DIR/cur/23:2,
+MAIL_DIR/cur/22:2,
+MAIL_DIR/cur/21:2,
+MAIL_DIR/cur/19:2,
+MAIL_DIR/cur/18:2,
+MAIL_DIR/cur/20:2,
+MAIL_DIR/cur/17:2,
+MAIL_DIR/cur/16:2,
+MAIL_DIR/cur/15:2,
+MAIL_DIR/cur/14:2,
+MAIL_DIR/cur/13:2,
+MAIL_DIR/cur/12:2,
+MAIL_DIR/cur/11:2,
+MAIL_DIR/cur/10:2,
+MAIL_DIR/cur/09:2,
+MAIL_DIR/cur/08:2,
+MAIL_DIR/cur/06:2,
+MAIL_DIR/cur/05:2,
+MAIL_DIR/cur/04:2,
+MAIL_DIR/cur/03:2,
+MAIL_DIR/cur/07:2,
+MAIL_DIR/cur/02:2,
+MAIL_DIR/cur/01:2,
+MAIL_DIR/cur/01:2-duplicate,"
+
 test_begin_subtest "notmuch search --format=json --output=files"
 output=$(notmuch search --format=json --output=files '*' | sed -e "s,$MAIL_DIR,MAIL_DIR,")
 test_expect_equal "$output" '["MAIL_DIR/cur/50:2,",
@@ -266,6 +325,60 @@ test_expect_equal "$output" '["MAIL_DIR/cur/50:2,",
 "MAIL_DIR/cur/02:2,",
 "MAIL_DIR/cur/01:2,"]'
 
+test_begin_subtest "notmuch search --format=json --output=files --include-duplicates"
+output=$(notmuch search --format=json --output=files --include-duplicates '*' | sed -e "s,$MAIL_DIR,MAIL_DIR,")
+test_expect_equal "$output" '["MAIL_DIR/cur/50:2,",
+"MAIL_DIR/cur/49:2,",
+"MAIL_DIR/cur/48:2,",
+"MAIL_DIR/cur/47:2,",
+"MAIL_DIR/cur/46:2,",
+"MAIL_DIR/cur/45:2,",
+"MAIL_DIR/cur/44:2,",
+"MAIL_DIR/cur/43:2,",
+"MAIL_DIR/cur/42:2,",
+"MAIL_DIR/cur/41:2,",
+"MAIL_DIR/cur/40:2,",
+"MAIL_DIR/cur/39:2,",
+"MAIL_DIR/cur/38:2,",
+"MAIL_DIR/cur/37:2,",
+"MAIL_DIR/cur/36:2,",
+"MAIL_DIR/cur/35:2,",
+"MAIL_DIR/cur/34:2,",
+"MAIL_DIR/cur/33:2,",
+"MAIL_DIR/cur/32:2,",
+"MAIL_DIR/cur/31:2,",
+"MAIL_DIR/cur/30:2,",
+"MAIL_DIR/cur/29:2,",
+"MAIL_DIR/cur/28:2,",
+"MAIL_DIR/cur/27:2,",
+"MAIL_DIR/cur/26:2,",
+"MAIL_DIR/cur/25:2,",
+"MAIL_DIR/cur/24:2,",
+"MAIL_DIR/cur/23:2,",
+"MAIL_DIR/cur/22:2,",
+"MAIL_DIR/cur/21:2,",
+"MAIL_DIR/cur/19:2,",
+"MAIL_DIR/cur/18:2,",
+"MAIL_DIR/cur/20:2,",
+"MAIL_DIR/cur/17:2,",
+"MAIL_DIR/cur/16:2,",
+"MAIL_DIR/cur/15:2,",
+"MAIL_DIR/cur/14:2,",
+"MAIL_DIR/cur/13:2,",
+"MAIL_DIR/cur/12:2,",
+"MAIL_DIR/cur/11:2,",
+"MAIL_DIR/cur/10:2,",
+"MAIL_DIR/cur/09:2,",
+"MAIL_DIR/cur/08:2,",
+"MAIL_DIR/cur/06:2,",
+"MAIL_DIR/cur/05:2,",
+"MAIL_DIR/cur/04:2,",
+"MAIL_DIR/cur/03:2,",
+"MAIL_DIR/cur/07:2,",
+"MAIL_DIR/cur/02:2,",
+"MAIL_DIR/cur/01:2,",
+"MAIL_DIR/cur/01:2-duplicate,"]'
+
 test_begin_subtest "notmuch search --output=tags"
 output=$(notmuch search --output=tags '*')
 test_expect_equal "$output" "attachment
-- 
1.7.2.3



More information about the notmuch mailing list