Return-Path: X-Original-To: notmuch@notmuchmail.org Delivered-To: notmuch@notmuchmail.org Received: from localhost (localhost [127.0.0.1]) by olra.theworths.org (Postfix) with ESMTP id 49304429E20 for ; Mon, 24 Jan 2011 22:39:29 -0800 (PST) X-Virus-Scanned: Debian amavisd-new at olra.theworths.org X-Spam-Flag: NO X-Spam-Score: -1 X-Spam-Level: X-Spam-Status: No, score=-1 tagged_above=-999 required=5 tests=[ALL_TRUSTED=-1] autolearn=disabled Received: from olra.theworths.org ([127.0.0.1]) by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Ba5CEj8Omrf6; Mon, 24 Jan 2011 22:39:27 -0800 (PST) Received: from yoom.amr.corp.intel.com (localhost [127.0.0.1]) by olra.theworths.org (Postfix) with ESMTP id D9CA0431FB6; Mon, 24 Jan 2011 22:39:25 -0800 (PST) From: Carl Worth To: notmuch@notmuchmail.org Subject: [PATCH] Add --include-duplicates option to a couple of commands. Date: Tue, 25 Jan 2011 16:39:24 +1000 Message-Id: <1295937564-2518-1-git-send-email-cworth@cworth.org> X-Mailer: git-send-email 1.7.2.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: notmuch@notmuchmail.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Jan 2011 06:39:29 -0000 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 \", \"To\": \"Notmuch Test Suite \", \"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@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@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@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@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@dottiness.seas.harvard.edu depth:0 match:1 filename:/home/cworth/src/notmuch/test/tmp.json/mail/cur/03:2, + header{ +Lars Kellogg-Stedman (2009-11-17) (inbox unread) +Subject: [notmuch] Working with Maildir storage? +From: Lars Kellogg-Stedman +To: notmuch@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 +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@notmuchmail.org +http://notmuchmail.org/mailman/listinfo/notmuch + part} + body} + message} + message{ id:20091117190054.GU3165@dottiness.seas.harvard.edu depth:0 match:1 filename:/home/cworth/src/notmuch/test/tmp.json/mail/cur/03:2, + header{ +Lars Kellogg-Stedman (2009-11-17) (inbox unread) +Subject: [notmuch] Working with Maildir storage? +From: Lars Kellogg-Stedman +To: notmuch@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 +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@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@dottiness.seas.harvard.edu depth:0 match:1 filename:/home/cworth/src/notmuch/test/tmp.json/mail/cur/03:2, + header{ +Lars Kellogg-Stedman (2009-11-17) (inbox unread) +Subject: [notmuch] Working with Maildir storage? +From: Lars Kellogg-Stedman +To: notmuch@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 +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@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