unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
* Display duplicate messages in emacs front-end
@ 2022-07-01 21:45 David Bremner
  2022-07-01 21:45 ` [PATCH 1/9] test: use notmuch_json_show_sanitize more places David Bremner
                   ` (10 more replies)
  0 siblings, 11 replies; 17+ messages in thread
From: David Bremner @ 2022-07-01 21:45 UTC (permalink / raw)
  To: notmuch

This obsoletes the WIP series [1]. Compared to that series, this one
includes somewhat improved documentation, better error handling, and
implements the --duplicate argument for notmuch-reply, and uses it in
the emacs front end.

[1]: id:20220619232152.846823-1-david@tethera.net


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 1/9] test: use notmuch_json_show_sanitize more places
  2022-07-01 21:45 Display duplicate messages in emacs front-end David Bremner
@ 2022-07-01 21:45 ` David Bremner
  2022-07-01 21:45 ` [PATCH 2/9] test: define and use notmuch_sexp_*_sanitize functions David Bremner
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: David Bremner @ 2022-07-01 21:45 UTC (permalink / raw)
  To: notmuch

This makes the tests more robust against changing output formats, by
allowing us to centralize fixes in the sanitization function. It is
not appropriate for all cases, in particular it is unneeded when using
test_json_nodes, and unhelpful when testing filenames.
---
 test/T070-insert.sh    |  6 +++---
 test/T160-json.sh      | 16 ++++++++--------
 test/T190-multipart.sh | 24 ++++++++++++------------
 test/T220-reply.sh     |  7 ++++---
 4 files changed, 27 insertions(+), 26 deletions(-)

diff --git a/test/T070-insert.sh b/test/T070-insert.sh
index e1e3b151..7d5f842d 100755
--- a/test/T070-insert.sh
+++ b/test/T070-insert.sh
@@ -43,13 +43,13 @@ test_begin_subtest "Permissions on inserted message should be 0600"
 test_expect_equal "600" "$(stat -c %a "$cur_msg_filename")"
 
 test_begin_subtest "Insert message adds default tags"
-output=$(notmuch show --format=json "subject:insert-subject")
+output=$(notmuch show --format=json "subject:insert-subject" | notmuch_json_show_sanitize)
 expected='[[[{
- "id": "'"${gen_msg_id}"'",
+ "id": "XXXXX",
  "crypto": {},
  "match": true,
  "excluded": false,
- "filename": ["'"${cur_msg_filename}"'"],
+ "filename": ["YYYYY"],
  "timestamp": 946728000,
  "date_relative": "2000-01-01",
  "tags": ["inbox","unread"],
diff --git a/test/T160-json.sh b/test/T160-json.sh
index ec7b1461..e1252353 100755
--- a/test/T160-json.sh
+++ b/test/T160-json.sh
@@ -5,17 +5,17 @@ test_description="--format=json output"
 
 test_begin_subtest "Show message: json"
 add_message "[subject]=\"json-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[bcc]=\"test_suite+bcc@notmuchmail.org\"" "[reply-to]=\"test_suite+replyto@notmuchmail.org\"" "[body]=\"json-show-message\""
-output=$(notmuch show --format=json "json-show-message")
-test_expect_equal_json "$output" "[[[{\"id\": \"${gen_msg_id}\", \"crypto\": {}, \"match\": true, \"excluded\": false, \"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@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Bcc\": \"test_suite+bcc@notmuchmail.org\", \"Reply-To\": \"test_suite+replyto@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"json-show-message\n\"}]}, []]]]"
+output=$(notmuch show --format=json "json-show-message" | notmuch_json_show_sanitize)
+test_expect_equal_json "$output" "[[[{\"id\": \"XXXXX\", \"crypto\": {}, \"match\": true, \"excluded\": false, \"filename\": [\"YYYYY\"], \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Bcc\": \"test_suite+bcc@notmuchmail.org\", \"Reply-To\": \"test_suite+replyto@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"json-show-message\n\"}]}, []]]]"
 
 # This should be the same output as above.
 test_begin_subtest "Show message: json --body=true"
-output=$(notmuch show --format=json --body=true "json-show-message")
-test_expect_equal_json "$output" "[[[{\"id\": \"${gen_msg_id}\",  \"crypto\": {}, \"match\": true, \"excluded\": false, \"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@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Bcc\": \"test_suite+bcc@notmuchmail.org\", \"Reply-To\": \"test_suite+replyto@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"json-show-message\n\"}]}, []]]]"
+output=$(notmuch show --format=json --body=true "json-show-message" | notmuch_json_show_sanitize)
+test_expect_equal_json "$output" "[[[{\"id\": \"XXXXX\",  \"crypto\": {}, \"match\": true, \"excluded\": false, \"filename\": [\"YYYYY\"], \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Bcc\": \"test_suite+bcc@notmuchmail.org\", \"Reply-To\": \"test_suite+replyto@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"json-show-message\n\"}]}, []]]]"
 
 test_begin_subtest "Show message: json --body=false"
-output=$(notmuch show --format=json --body=false "json-show-message")
-test_expect_equal_json "$output" "[[[{\"id\": \"${gen_msg_id}\",  \"crypto\": {}, \"match\": true, \"excluded\": false, \"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@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Bcc\": \"test_suite+bcc@notmuchmail.org\", \"Reply-To\": \"test_suite+replyto@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}}, []]]]"
+output=$(notmuch show --format=json --body=false "json-show-message" | notmuch_json_show_sanitize)
+test_expect_equal_json "$output" "[[[{\"id\": \"XXXXX\",  \"crypto\": {}, \"match\": true, \"excluded\": false, \"filename\": [\"YYYYY\"], \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Bcc\": \"test_suite+bcc@notmuchmail.org\", \"Reply-To\": \"test_suite+replyto@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}}, []]]]"
 
 test_begin_subtest "Search message: json"
 add_message "[subject]=\"json-search-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"json-search-message\""
@@ -33,8 +33,8 @@ test_expect_equal_json "$output" "[{\"thread\": \"XXX\",
 
 test_begin_subtest "Show message: json, utf-8"
 add_message "[subject]=\"json-show-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"jsön-show-méssage\""
-output=$(notmuch show --format=json "jsön-show-méssage")
-test_expect_equal_json "$output" "[[[{\"id\": \"${gen_msg_id}\",  \"crypto\": {}, \"match\": true, \"excluded\": false, \"filename\": [\"${gen_msg_filename}\"], \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-utf8-body-sübjéct\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"jsön-show-méssage\n\"}]}, []]]]"
+output=$(notmuch show --format=json "jsön-show-méssage" | notmuch_json_show_sanitize)
+test_expect_equal_json "$output" "[[[{\"id\": \"XXXXX\",  \"crypto\": {}, \"match\": true, \"excluded\": false, \"filename\": [\"YYYYY\"], \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\",\"unread\"], \"headers\": {\"Subject\": \"json-show-utf8-body-sübjéct\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"text/plain\", \"content\": \"jsön-show-méssage\n\"}]}, []]]]"
 
 test_begin_subtest "Show message: json, inline attachment filename"
 subject='json-show-inline-attachment-filename'
diff --git a/test/T190-multipart.sh b/test/T190-multipart.sh
index d3b7f87c..cfe48ac5 100755
--- a/test/T190-multipart.sh
+++ b/test/T190-multipart.sh
@@ -376,18 +376,18 @@ test_begin_subtest "--format=text --part=8, no part, expect error"
 test_expect_success "notmuch show --format=text --part=8 'id:87liy5ap00.fsf@yoom.home.cworth.org'"
 
 test_begin_subtest "--format=json --part=0, full message"
-notmuch show --format=json --part=0 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+notmuch show --format=json --part=0 'id:87liy5ap00.fsf@yoom.home.cworth.org' | notmuch_json_show_sanitize >OUTPUT
 cat <<EOF >EXPECTED
-{"id": "87liy5ap00.fsf@yoom.home.cworth.org", "crypto": {}, "match": true, "excluded": false, "filename": ["${MAIL_DIR}/multipart"], "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["attachment","inbox","signed","unread"], "headers": {"Subject": "Multipart message", "From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Date": "Fri, 05 Jan 2001 15:43:57 +0000"}, "body": [
+{"id": "XXXXX", "crypto": {}, "match": true, "excluded": false, "filename": ["YYYYY"], "timestamp": 42, "date_relative": "2001-01-05", "tags": ["attachment","inbox","signed","unread"], "headers": {"Subject": "Multipart message", "From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Date": "GENERATED_DATE"}, "body": [
 {"id": 1, "content-type": "multipart/signed", "content": [
 {"id": 2, "content-type": "multipart/mixed", "content": [
-{"id": 3, "content-type": "message/rfc822", "content-disposition": "inline", "content": [{"headers": {"Subject": "html message", "From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Date": "Fri, 05 Jan 2001 15:42:57 +0000"}, "body": [
+{"id": 3, "content-type": "message/rfc822", "content-disposition": "inline", "content": [{"headers": {"Subject": "html message", "From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Date": "GENERATED_DATE"}, "body": [
 {"id": 4, "content-type": "multipart/alternative", "content": [
-{"id": 5, "content-type": "text/html", "content-length": 71},
+{"id": 5, "content-type": "text/html", "content-length": "NONZERO"},
 {"id": 6, "content-type": "text/plain", "content": "This is an embedded message, with a multipart/alternative part.\n"}]}]}]}, 
 {"id": 7, "content-type": "text/plain", "content-disposition": "attachment", "filename": "attachment", "content": "This is a text attachment.\n"},
 {"id": 8, "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"}]}, 
-{"id": 9, "content-type": "application/pgp-signature", "content-length": 197}]}]}
+{"id": 9, "content-type": "application/pgp-signature", "content-length": "NONZERO"}]}]}
 EOF
 test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED)"
 
@@ -485,7 +485,7 @@ notmuch show --format=raw 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
 test_expect_equal_file "${MAIL_DIR}"/multipart  OUTPUT
 
 test_begin_subtest "--format=raw --part=0, full message"
-notmuch show --format=raw --part=0 'id:87liy5ap00.fsf@yoom.home.cworth.org' >OUTPUT
+notmuch show --format=raw --part=0 'id:87liy5ap00.fsf@yoom.home.cworth.org' | notmuch_json_show_sanitize >OUTPUT
 test_expect_equal_file "${MAIL_DIR}"/multipart OUTPUT
 
 test_begin_subtest "--format=raw --part=1, message body"
@@ -727,10 +727,10 @@ notmuch new > /dev/null
 
 cat_expected_head () {
         cat <<EOF
-[[[{"id": "htmlmessage", "match":true, "excluded": false, "date_relative":"2000-01-01",
+[[[{"id": "XXXXX", "match":true, "excluded": false, "date_relative":"2000-01-01",
    "crypto": {},
    "timestamp": 946684800,
-   "filename": ["${MAIL_DIR}/include-html"],
+   "filename": ["YYYYY"],
    "tags": ["inbox", "unread"],
    "headers": { "Date": "Sat, 01 Jan 2000 00:00:00 +0000", "From": "A <a@example.com>",
                 "Subject": "html message", "To": "B <b@example.com>"},
@@ -742,8 +742,8 @@ EOF
 cat_expected_head > EXPECTED.nohtml
 cat <<EOF >> EXPECTED.nohtml
 "content": [
-  { "id": 2, "content-charset": "UTF-8", "content-length": 21, "content-type": "text/html"},
-  { "id": 3, "content-charset": "ISO-8859-1", "content-length": 20, "content-type": "text/html"},
+  { "id": 2, "content-charset": "UTF-8", "content-length": "NONZERO", "content-type": "text/html"},
+  { "id": 3, "content-charset": "ISO-8859-1", "content-length": "NONZERO", "content-type": "text/html"},
   { "id": 4, "content-type": "text/plain", "content": "0.5 equals \\u00bd\\n"}
 ]}]},[]]]]
 EOF
@@ -759,11 +759,11 @@ cat <<EOF >> EXPECTED.withhtml
 EOF
 
 test_begin_subtest "html parts excluded by default"
-notmuch show --format=json id:htmlmessage > OUTPUT
+notmuch show --format=json id:htmlmessage | notmuch_json_show_sanitize > OUTPUT
 test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED.nohtml)"
 
 test_begin_subtest "html parts included"
-notmuch show --format=json --include-html id:htmlmessage > OUTPUT
+notmuch show --format=json --include-html id:htmlmessage | notmuch_json_show_sanitize > OUTPUT
 test_expect_equal_json "$(cat OUTPUT)" "$(cat EXPECTED.withhtml)"
 
 test_begin_subtest "indexes mime-type #1"
diff --git a/test/T220-reply.sh b/test/T220-reply.sh
index 4e9984d2..50179efc 100755
--- a/test/T220-reply.sh
+++ b/test/T220-reply.sh
@@ -298,7 +298,8 @@ On Tue, 05 Jan 2010 15:43:56 -0000, ☃ <snowman@example.com> wrote:
 OK"
 
 test_begin_subtest "Reply with RFC 2047-encoded headers (JSON)"
-output=$(echo '{"answer":' && notmuch reply --format=json id:${gen_msg_id} 2>&1 && echo ', "success": "OK"}')
+output=$(echo '{"answer":' && notmuch reply --format=json id:${gen_msg_id} 2>&1 | notmuch_json_show_sanitize \
+	 && echo ', "success": "OK"}')
 test_expect_equal_json "$output" '
 {  "answer": {
     "original": {
@@ -312,14 +313,14 @@ test_expect_equal_json "$output" '
         "crypto": {},
         "date_relative": "2010-01-05",
         "excluded": false,
-        "filename": ["'${MAIL_DIR}'/msg-015"],
+        "filename": ["YYYYY"],
         "headers": {
             "Date": "Tue, 05 Jan 2010 15:43:56 +0000",
             "From": "\u2603 <snowman@example.com>",
             "Subject": "\u00e0\u00df\u00e7",
             "To": "Notmuch Test Suite <test_suite@notmuchmail.org>"
         },
-        "id": "'${gen_msg_id}'",
+        "id": "XXXXX",
         "match": false,
         "tags": [
             "inbox",
-- 
2.35.2
\r

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 2/9] test: define and use notmuch_sexp_*_sanitize functions
  2022-07-01 21:45 Display duplicate messages in emacs front-end David Bremner
  2022-07-01 21:45 ` [PATCH 1/9] test: use notmuch_json_show_sanitize more places David Bremner
@ 2022-07-01 21:45 ` David Bremner
  2022-07-01 21:45 ` [PATCH 3/9] test: add new corpus of duplicate messages David Bremner
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: David Bremner @ 2022-07-01 21:45 UTC (permalink / raw)
  To: notmuch

These are based on the equivalent functions for json. Like those,
these are pretty simple-minded, and don't really understand the
syntax.
---
 test/T170-sexp.sh | 29 ++++++++++++++---------------
 test/test-lib.sh  | 14 ++++++++++++++
 2 files changed, 28 insertions(+), 15 deletions(-)

diff --git a/test/T170-sexp.sh b/test/T170-sexp.sh
index 0d32560c..76e07481 100755
--- a/test/T170-sexp.sh
+++ b/test/T170-sexp.sh
@@ -5,32 +5,32 @@ test_description="--format=sexp output"
 
 test_begin_subtest "Show message: sexp"
 add_message "[subject]=\"sexp-show-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[bcc]=\"test_suite+bcc@notmuchmail.org\"" "[reply-to]=\"test_suite+replyto@notmuchmail.org\"" "[body]=\"sexp-show-message\""
-output=$(notmuch show --format=sexp "sexp-show-message")
-test_expect_equal "$output" "((((:id \"${gen_msg_id}\" :match t :excluded nil :filename (\"${gen_msg_filename}\") :timestamp 946728000 :date_relative \"2000-01-01\" :tags (\"inbox\" \"unread\") :body ((:id 1 :content-type \"text/plain\" :content \"sexp-show-message\n\")) :crypto () :headers (:Subject \"sexp-show-subject\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :Bcc \"test_suite+bcc@notmuchmail.org\" :Reply-To \"test_suite+replyto@notmuchmail.org\" :Date \"Sat, 01 Jan 2000 12:00:00 +0000\")) ())))"
+output=$(notmuch show --format=sexp "sexp-show-message" | notmuch_sexp_show_sanitize)
+test_expect_equal "$output" "((((:id \"XXXXX\" :match t :excluded nil :filename (\"YYYYY\") :timestamp 42 :date_relative \"2000-01-01\" :tags (\"inbox\" \"unread\") :body ((:id 1 :content-type \"text/plain\" :content \"sexp-show-message\n\")) :crypto () :headers (:Subject \"sexp-show-subject\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :Bcc \"test_suite+bcc@notmuchmail.org\" :Reply-To \"test_suite+replyto@notmuchmail.org\" :Date \"GENERATED_DATE\")) ())))"
 
 # This should be the same output as above.
 test_begin_subtest "Show message: sexp --body=true"
-output=$(notmuch show --format=sexp --body=true "sexp-show-message")
-test_expect_equal "$output" "((((:id \"${gen_msg_id}\" :match t :excluded nil :filename (\"${gen_msg_filename}\") :timestamp 946728000 :date_relative \"2000-01-01\" :tags (\"inbox\" \"unread\") :body ((:id 1 :content-type \"text/plain\" :content \"sexp-show-message\n\")) :crypto () :headers (:Subject \"sexp-show-subject\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :Bcc \"test_suite+bcc@notmuchmail.org\" :Reply-To \"test_suite+replyto@notmuchmail.org\" :Date \"Sat, 01 Jan 2000 12:00:00 +0000\")) ())))"
+output=$(notmuch show --format=sexp --body=true "sexp-show-message" | notmuch_sexp_show_sanitize)
+test_expect_equal "$output" "((((:id \"XXXXX\" :match t :excluded nil :filename (\"YYYYY\") :timestamp 42 :date_relative \"2000-01-01\" :tags (\"inbox\" \"unread\") :body ((:id 1 :content-type \"text/plain\" :content \"sexp-show-message\n\")) :crypto () :headers (:Subject \"sexp-show-subject\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :Bcc \"test_suite+bcc@notmuchmail.org\" :Reply-To \"test_suite+replyto@notmuchmail.org\" :Date \"GENERATED_DATE\")) ())))"
 
 test_begin_subtest "Show message: sexp --body=false"
-output=$(notmuch show --format=sexp --body=false "sexp-show-message")
-test_expect_equal "$output" "((((:id \"${gen_msg_id}\" :match t :excluded nil :filename (\"${gen_msg_filename}\") :timestamp 946728000 :date_relative \"2000-01-01\" :tags (\"inbox\" \"unread\") :crypto () :headers (:Subject \"sexp-show-subject\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :Bcc \"test_suite+bcc@notmuchmail.org\" :Reply-To \"test_suite+replyto@notmuchmail.org\" :Date \"Sat, 01 Jan 2000 12:00:00 +0000\")) ())))"
+output=$(notmuch show --format=sexp --body=false "sexp-show-message" | notmuch_sexp_show_sanitize)
+test_expect_equal "$output" "((((:id \"XXXXX\" :match t :excluded nil :filename (\"YYYYY\") :timestamp 42 :date_relative \"2000-01-01\" :tags (\"inbox\" \"unread\") :crypto () :headers (:Subject \"sexp-show-subject\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :Bcc \"test_suite+bcc@notmuchmail.org\" :Reply-To \"test_suite+replyto@notmuchmail.org\" :Date \"GENERATED_DATE\")) ())))"
 
 test_begin_subtest "Search message: sexp"
 add_message "[subject]=\"sexp-search-subject\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"sexp-search-message\""
-output=$(notmuch search --format=sexp "sexp-search-message" | notmuch_search_sanitize)
-test_expect_equal "$output" "((:thread \"0000000000000002\" :timestamp 946728000 :date_relative \"2000-01-01\" :matched 1 :total 1 :authors \"Notmuch Test Suite\" :subject \"sexp-search-subject\" :query (\"id:$gen_msg_id\" nil) :tags (\"inbox\" \"unread\")))"
+output=$(notmuch search --format=sexp "sexp-search-message" | notmuch_sexp_search_sanitize)
+test_expect_equal "$output" "((:thread \"XXX\" :timestamp 946728000 :date_relative \"2000-01-01\" :matched 1 :total 1 :authors \"Notmuch Test Suite\" :subject \"sexp-search-subject\" :query (\"id:$gen_msg_id\" nil) :tags (\"inbox\" \"unread\")))"
 
 test_begin_subtest "Show message: sexp, utf-8"
 add_message "[subject]=\"sexp-show-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"jsön-show-méssage\""
-output=$(notmuch show --format=sexp "jsön-show-méssage")
-test_expect_equal "$output" "((((:id \"${gen_msg_id}\" :match t :excluded nil :filename (\"${gen_msg_filename}\") :timestamp 946728000 :date_relative \"2000-01-01\" :tags (\"inbox\" \"unread\") :body ((:id 1 :content-type \"text/plain\" :content \"jsön-show-méssage\n\")) :crypto () :headers (:Subject \"sexp-show-utf8-body-sübjéct\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :Date \"Sat, 01 Jan 2000 12:00:00 +0000\")) ())))"
+output=$(notmuch show --format=sexp "jsön-show-méssage" | notmuch_sexp_show_sanitize)
+test_expect_equal "$output" "((((:id \"XXXXX\" :match t :excluded nil :filename (\"YYYYY\") :timestamp 42 :date_relative \"2000-01-01\" :tags (\"inbox\" \"unread\") :body ((:id 1 :content-type \"text/plain\" :content \"jsön-show-méssage\n\")) :crypto () :headers (:Subject \"sexp-show-utf8-body-sübjéct\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :Date \"GENERATED_DATE\")) ())))"
 
 test_begin_subtest "Search message: sexp, utf-8"
 add_message "[subject]=\"sexp-search-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"jsön-search-méssage\""
-output=$(notmuch search --format=sexp "jsön-search-méssage" | notmuch_search_sanitize)
-test_expect_equal "$output" "((:thread \"0000000000000004\" :timestamp 946728000 :date_relative \"2000-01-01\" :matched 1 :total 1 :authors \"Notmuch Test Suite\" :subject \"sexp-search-utf8-body-sübjéct\" :query (\"id:$gen_msg_id\" nil) :tags (\"inbox\" \"unread\")))"
+output=$(notmuch search --format=sexp "jsön-search-méssage" | notmuch_sexp_search_sanitize)
+test_expect_equal "$output" "((:thread \"XXX\" :timestamp 946728000 :date_relative \"2000-01-01\" :matched 1 :total 1 :authors \"Notmuch Test Suite\" :subject \"sexp-search-utf8-body-sübjéct\" :query (\"id:$gen_msg_id\" nil) :tags (\"inbox\" \"unread\")))"
 
 test_begin_subtest "Show message: sexp, inline attachment filename"
 subject='sexp-show-inline-attachment-filename'
@@ -54,10 +54,9 @@ add_message "[subject]=\"extra-headers\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0
 	for <test_suite_other@notmuchmail.org>; Sat, 10 Apr 2010 07:54:51 -0400 (EDT)\"" \
 
 notmuch config set show.extra_headers "in-reply-to;received"
-notmuch show --format=sexp --body=false id:${gen_msg_id} | \
-    notmuch_dir_sanitize | sed 's/msg-[0-9]*/MSG/g'> OUTPUT
+notmuch show --format=sexp --body=false id:${gen_msg_id} | notmuch_sexp_show_sanitize > OUTPUT
 cat <<EOF > EXPECTED
-((((:id "MSG@notmuch-test-suite" :match t :excluded nil :filename ("MAIL_DIR/MSG") :timestamp 946728000 :date_relative "2000-01-01" :tags ("inbox" "unread") :crypto () :headers (:Subject "extra-headers" :From "Notmuch Test Suite <test_suite@notmuchmail.org>" :To "Notmuch Test Suite <test_suite@notmuchmail.org>" :Date "Sat, 01 Jan 2000 12:00:00 +0000" :In-Reply-To "<parent@notmuch-test-suite>" :Received "from mail.example.com (mail.example.com [1.1.1.1])\011by mail.notmuchmail.org (some MTA) with ESMTP id 12345678\011for <test_suite_other@notmuchmail.org>; Sat, 10 Apr 2010 07:54:51 -0400 (EDT)")) ())))
+((((:id "XXXXX" :match t :excluded nil :filename ("YYYYY") :timestamp 42 :date_relative "2000-01-01" :tags ("inbox" "unread") :crypto () :headers (:Subject "extra-headers" :From "Notmuch Test Suite <test_suite@notmuchmail.org>" :To "Notmuch Test Suite <test_suite@notmuchmail.org>" :Date "GENERATED_DATE" :In-Reply-To "<parent@notmuch-test-suite>" :Received "from mail.example.com (mail.example.com [1.1.1.1])\011by mail.notmuchmail.org (some MTA) with ESMTP id 12345678\011for <test_suite_other@notmuchmail.org>; Sat, 10 Apr 2010 07:54:51 -0400 (EDT)")) ())))
 EOF
 test_expect_equal_file EXPECTED OUTPUT
 
diff --git a/test/test-lib.sh b/test/test-lib.sh
index 75a62214..4eb58ea0 100644
--- a/test/test-lib.sh
+++ b/test/test-lib.sh
@@ -527,6 +527,20 @@ notmuch_json_show_sanitize () {
 	-e 's|"content-length": [1-9][0-9]*|"content-length": "NONZERO"|g'
 }
 
+notmuch_sexp_show_sanitize () {
+    sed \
+	-e 's|:id "[^"]*"|:id "XXXXX"|g' \
+	-e 's|:Date "Sat, 01 Jan 2000 [^"]*0000"|:Date "GENERATED_DATE"|g' \
+	-e 's|:filename "signature.asc"||g' \
+	-e 's|:filename ("/[^"]*")|:filename ("YYYYY")|g' \
+	-e 's|:timestamp 9........|:timestamp 42|g' \
+	-e 's|:content-length [1-9][0-9]*|:content-length "NONZERO"|g'
+}
+
+notmuch_sexp_search_sanitize () {
+    sed -e 's|:thread "[^"]*"|:thread "XXX"|'
+}
+
 notmuch_emacs_error_sanitize () {
     local command
     command=$1
-- 
2.35.2
\r

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 3/9] test: add new corpus of duplicate messages
  2022-07-01 21:45 Display duplicate messages in emacs front-end David Bremner
  2022-07-01 21:45 ` [PATCH 1/9] test: use notmuch_json_show_sanitize more places David Bremner
  2022-07-01 21:45 ` [PATCH 2/9] test: define and use notmuch_sexp_*_sanitize functions David Bremner
@ 2022-07-01 21:45 ` David Bremner
  2022-07-05 10:07   ` David Bremner
  2022-07-01 21:45 ` [PATCH 4/9] CLI/show: initial support for --duplicate for (raw output only) David Bremner
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 17+ messages in thread
From: David Bremner @ 2022-07-01 21:45 UTC (permalink / raw)
  To: notmuch

This corpus will be used to test a new --duplicate option for notmuch-show
---
 test/corpora/duplicate/msg-1-1:2, |  85 ++++++++++++++
 test/corpora/duplicate/msg-1-2:2, | 113 ++++++++++++++++++
 test/corpora/duplicate/msg-2-1:2, |  43 +++++++
 test/corpora/duplicate/msg-2-2:2, | 140 +++++++++++++++++++++++
 test/corpora/duplicate/msg-3-1:2, | 183 +++++++++++++++++++++++++++++
 test/corpora/duplicate/msg-3-2:2, | 184 ++++++++++++++++++++++++++++++
 test/corpora/duplicate/msg-3-3:2, | 178 +++++++++++++++++++++++++++++
 test/corpora/duplicate/msg-3-4:2, | 184 ++++++++++++++++++++++++++++++
 test/corpora/duplicate/msg-3-5:2, | 179 +++++++++++++++++++++++++++++
 9 files changed, 1289 insertions(+)
 create mode 100644 test/corpora/duplicate/msg-1-1:2,
 create mode 100644 test/corpora/duplicate/msg-1-2:2,
 create mode 100644 test/corpora/duplicate/msg-2-1:2,
 create mode 100644 test/corpora/duplicate/msg-2-2:2,
 create mode 100644 test/corpora/duplicate/msg-3-1:2,
 create mode 100644 test/corpora/duplicate/msg-3-2:2,
 create mode 100644 test/corpora/duplicate/msg-3-3:2,
 create mode 100644 test/corpora/duplicate/msg-3-4:2,
 create mode 100644 test/corpora/duplicate/msg-3-5:2,

diff --git a/test/corpora/duplicate/msg-1-1:2, b/test/corpora/duplicate/msg-1-1:2,
new file mode 100644
index 00000000..bc7da06d
--- /dev/null
+++ b/test/corpora/duplicate/msg-1-1:2,
@@ -0,0 +1,85 @@
+Return-path: <debian-science-maintainers-bounces+david=tethera.net@lists.alioth.debian.org>
+Envelope-to: david@tethera.net
+Delivery-date: Wed, 28 Nov 2012 18:41:46 -0400
+Received: from [199.188.72.155] (helo=yantan.tethera.net)
+	by tesseract.cs.unb.ca with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32)
+	(Exim 4.72)
+	(envelope-from <debian-science-maintainers-bounces+david=tethera.net@lists.alioth.debian.org>)
+	id 1TdqKA-00017j-3c
+	for david@tethera.net; Wed, 28 Nov 2012 18:41:46 -0400
+Received: from wagner.debian.org ([217.196.43.132])
+	by yantan.tethera.net with esmtp (Exim 4.72)
+	(envelope-from <debian-science-maintainers-bounces+david=tethera.net@lists.alioth.debian.org>)
+	id 1TdqK9-00072z-AF
+	for david@tethera.net; Wed, 28 Nov 2012 18:41:45 -0400
+Received: from localhost ([::1] helo=wagner.debian.org)
+	by wagner.debian.org with esmtp (Exim 4.72)
+	(envelope-from <debian-science-maintainers-bounces+david=tethera.net@lists.alioth.debian.org>)
+	id 1TdqK8-0007GZ-67
+	for david@tethera.net; Wed, 28 Nov 2012 22:41:44 +0000
+Received: from vasks.debian.org ([217.196.43.140])
+	by wagner.debian.org with esmtp (Exim 4.72)
+	(envelope-from <gladky-anton-guest@alioth.debian.org>)
+	id 1TdqIc-0006jm-OC; Wed, 28 Nov 2012 22:40:11 +0000
+Received: from gladky-anton-guest by vasks.debian.org with local (Exim 4.72)
+	(envelope-from <gladky-anton-guest@vasks.debian.org>)
+	id 1TdqIc-0003j1-DE; Wed, 28 Nov 2012 22:40:10 +0000
+Date: Wed, 28 Nov 2012 22:40:10 +0000
+From: Anton Gladky <gladky.anton@gmail.com>
+To: 691896@bugs.debian.org, control@bugs.debian.org,
+	691896-submitter@bugs.debian.org
+Message-ID: <debian/2.6.1.dfsg-4-1-g87ea161@87ea161e851dfb1ea324af00e4ecfccc18875e15>
+X-PTS-Approved: Yes
+X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on wagner.debian.org
+X-Spam-Level: 
+X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,FREEMAIL_FROM
+	autolearn=ham version=3.3.1
+Subject: [87ea161] Fix for Bug#691896 committed to git
+X-BeenThere: debian-science-maintainers@lists.alioth.debian.org
+X-Mailman-Version: 2.1.13
+Precedence: list
+List-Id: Mailing list for maintainer discussions and BTS messages
+	<debian-science-maintainers.lists.alioth.debian.org>
+List-Unsubscribe: <http://lists.alioth.debian.org/cgi-bin/mailman/options/debian-science-maintainers>,
+	<mailto:debian-science-maintainers-request@lists.alioth.debian.org?subject=unsubscribe>
+List-Archive: <http://lists.alioth.debian.org/pipermail/debian-science-maintainers>
+List-Post: <mailto:debian-science-maintainers@lists.alioth.debian.org>
+List-Help: <mailto:debian-science-maintainers-request@lists.alioth.debian.org?subject=help>
+List-Subscribe: <http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/debian-science-maintainers>,
+	<mailto:debian-science-maintainers-request@lists.alioth.debian.org?subject=subscribe>
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+Sender: debian-science-maintainers-bounces+david=tethera.net@lists.alioth.debian.org
+Errors-To: debian-science-maintainers-bounces+david=tethera.net@lists.alioth.debian.org
+X-SA-Exim-Connect-IP: ::1
+X-SA-Exim-Mail-From: debian-science-maintainers-bounces+david=tethera.net@lists.alioth.debian.org
+X-SA-Exim-Scanned: No (on wagner.debian.org); SAEximRunCond expanded to false
+X-Spam-Score: 1.3
+X-Spam_bar: +
+
+
+tags 691896 + pending
+thanks
+
+Hello,
+
+     The following change has been committed for this bug by
+ Anton Gladky <gladky.anton@gmail.com> on Wed, 31 Oct 2012 08:16:42 +0100.
+ The fix will be in the next upload. 
+====================================
+Minor fixes in README.Debian. (Closes: #691896)
+
+
+====================================
+
+You can check the diff of the fix at:
+
+    ;a=commitdiff;h=87ea161
+
+
+
+-- 
+debian-science-maintainers mailing list
+debian-science-maintainers@lists.alioth.debian.org
+http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/debian-science-maintainers
diff --git a/test/corpora/duplicate/msg-1-2:2, b/test/corpora/duplicate/msg-1-2:2,
new file mode 100644
index 00000000..dc0476e7
--- /dev/null
+++ b/test/corpora/duplicate/msg-1-2:2,
@@ -0,0 +1,113 @@
+Return-path: <debian-science-maintainers-bounces+david=tethera.net@lists.alioth.debian.org>
+Envelope-to: david@tethera.net
+Delivery-date: Wed, 28 Nov 2012 18:42:39 -0400
+Received: from [199.188.72.155] (helo=yantan.tethera.net)
+	by tesseract.cs.unb.ca with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32)
+	(Exim 4.72)
+	(envelope-from <debian-science-maintainers-bounces+david=tethera.net@lists.alioth.debian.org>)
+	id 1TdqL1-00017s-3b
+	for david@tethera.net; Wed, 28 Nov 2012 18:42:39 -0400
+Received: from wagner.debian.org ([217.196.43.132])
+	by yantan.tethera.net with esmtp (Exim 4.72)
+	(envelope-from <debian-science-maintainers-bounces+david=tethera.net@lists.alioth.debian.org>)
+	id 1TdqL0-00073Z-Gw
+	for david@tethera.net; Wed, 28 Nov 2012 18:42:38 -0400
+Received: from localhost ([::1] helo=alioth.debian.org)
+	by wagner.debian.org with esmtp (Exim 4.72)
+	(envelope-from <debian-science-maintainers-bounces+david=tethera.net@lists.alioth.debian.org>)
+	id 1TdqKz-0007sR-PR
+	for david@tethera.net; Wed, 28 Nov 2012 22:42:37 +0000
+Received: from buxtehude.debian.org ([140.211.166.26])
+	by wagner.debian.org with esmtp (Exim 4.72)
+	(envelope-from <debbugs@buxtehude.debian.org>) id 1TdqKU-0007SW-IG
+	for debian-science-maintainers@lists.alioth.debian.org;
+	Wed, 28 Nov 2012 22:42:07 +0000
+Received: from debbugs by buxtehude.debian.org with local (Exim 4.72)
+	(envelope-from <debbugs@buxtehude.debian.org>)
+	id 1TdqKR-0001dH-UL; Wed, 28 Nov 2012 22:42:03 +0000
+X-Loop: owner@bugs.debian.org
+Resent-From: Anton Gladky <gladky.anton@gmail.com>
+Resent-To: debian-bugs-dist@lists.debian.org
+Resent-CC: Debian Science Maintainers
+	<debian-science-maintainers@lists.alioth.debian.org>
+X-Loop: owner@bugs.debian.org
+Resent-Date: Wed, 28 Nov 2012 22:42:02 +0000
+Resent-Message-ID: <handler.691896.B691896.13541424145158@bugs.debian.org>
+X-Debian-PR-Message: followup 691896
+X-Debian-PR-Package: gmsh
+X-Debian-PR-Keywords: pending
+X-Debian-PR-Source: gmsh
+Received: via spool by 691896-submit@bugs.debian.org id=B691896.13541424145158
+	(code B ref 691896); Wed, 28 Nov 2012 22:42:02 +0000
+Received: (at 691896) by bugs.debian.org; 28 Nov 2012 22:40:14 +0000
+Received: from wagner.debian.org ([217.196.43.132])
+	by buxtehude.debian.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32)
+	(Exim 4.72) (envelope-from <gladky-anton-guest@alioth.debian.org>)
+	id 1TdqIg-0001Kh-Ba; Wed, 28 Nov 2012 22:40:14 +0000
+Received: from vasks.debian.org ([217.196.43.140])
+	by wagner.debian.org with esmtp (Exim 4.72)
+	(envelope-from <gladky-anton-guest@alioth.debian.org>)
+	id 1TdqIc-0006jm-OC; Wed, 28 Nov 2012 22:40:11 +0000
+Received: from gladky-anton-guest by vasks.debian.org with local (Exim 4.72)
+	(envelope-from <gladky-anton-guest@vasks.debian.org>)
+	id 1TdqIc-0003j1-DE; Wed, 28 Nov 2012 22:40:10 +0000
+Date: Wed, 28 Nov 2012 22:40:10 +0000
+From: Anton Gladky <gladky.anton@gmail.com>
+To: 691896@bugs.debian.org, control@bugs.debian.org,
+	691896-submitter@bugs.debian.org
+Message-ID: <debian/2.6.1.dfsg-4-1-g87ea161@87ea161e851dfb1ea324af00e4ecfccc18875e15>
+X-PTS-Approved: Yes
+Resent-Sender: Debian BTS <debbugs@buxtehude.debian.org>
+X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on wagner.debian.org
+X-Spam-Level: 
+X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00,FREEMAIL_FROM,
+	RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1
+Subject: Bug#691896: [87ea161] Fix for Bug#691896 committed to git
+x-debian-approved: yes
+X-BeenThere: debian-science-maintainers@lists.alioth.debian.org
+X-Mailman-Version: 2.1.13
+Precedence: list
+Reply-To: Anton Gladky <gladky.anton@gmail.com>, 691896@bugs.debian.org
+List-Id: Mailing list for maintainer discussions and BTS messages
+	<debian-science-maintainers.lists.alioth.debian.org>
+List-Unsubscribe: <http://lists.alioth.debian.org/cgi-bin/mailman/options/debian-science-maintainers>,
+	<mailto:debian-science-maintainers-request@lists.alioth.debian.org?subject=unsubscribe>
+List-Archive: <http://lists.alioth.debian.org/pipermail/debian-science-maintainers>
+List-Post: <mailto:debian-science-maintainers@lists.alioth.debian.org>
+List-Help: <mailto:debian-science-maintainers-request@lists.alioth.debian.org?subject=help>
+List-Subscribe: <http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/debian-science-maintainers>,
+	<mailto:debian-science-maintainers-request@lists.alioth.debian.org?subject=subscribe>
+MIME-Version: 1.0
+Content-Type: text/plain; charset="us-ascii"
+Content-Transfer-Encoding: 7bit
+Sender: debian-science-maintainers-bounces+david=tethera.net@lists.alioth.debian.org
+Errors-To: debian-science-maintainers-bounces+david=tethera.net@lists.alioth.debian.org
+X-SA-Exim-Connect-IP: ::1
+X-SA-Exim-Mail-From: debian-science-maintainers-bounces+david=tethera.net@lists.alioth.debian.org
+X-SA-Exim-Scanned: No (on wagner.debian.org); SAEximRunCond expanded to false
+X-Spam-Score: 1.3
+X-Spam_bar: +
+
+
+tags 691896 + pending
+thanks
+
+Hello,
+
+     The following change has been committed for this bug by
+ Anton Gladky <gladky.anton@gmail.com> on Wed, 31 Oct 2012 08:16:42 +0100.
+ The fix will be in the next upload. 
+====================================
+Minor fixes in README.Debian. (Closes: #691896)
+
+
+====================================
+
+You can check the diff of the fix at:
+
+    ;a=commitdiff;h=87ea161
+
+-- 
+debian-science-maintainers mailing list
+debian-science-maintainers@lists.alioth.debian.org
+http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/debian-science-maintainers
diff --git a/test/corpora/duplicate/msg-2-1:2, b/test/corpora/duplicate/msg-2-1:2,
new file mode 100644
index 00000000..e118d784
--- /dev/null
+++ b/test/corpora/duplicate/msg-2-1:2,
@@ -0,0 +1,43 @@
+From: David Bremner <bremner@debian.org>
+To: Samuel Bronson <naesten@gmail.com>, 695159@bugs.debian.org, Debian Bug Tracking System <submit@bugs.debian.org>
+Subject: Re: Bug#695159: debian-el: Shouldn't put downloaded bugs loose in ~/
+In-Reply-To: <87vcch7hxy.fsf@naesten.dyndns.org>
+References: <87vcch7hxy.fsf@naesten.dyndns.org>
+Date: Thu, 25 Oct 2018 10:41:38 -0300
+Message-ID: <87r2geywh9.fsf@tethera.net>
+MIME-Version: 1.0
+Content-Type: text/plain
+
+
+Control: severity -1 minor
+Control: tag -1 moreinfo
+
+Samuel Bronson <naesten@gmail.com> writes:
+
+> Package: debian-el
+> Version: 35.2+nmu1
+> Severity: normal
+> File: /usr/share/emacs/site-lisp/debian-el/debian-bug.el
+>
+> Dear Maintainer,
+>
+> After being mildly annoyed with this for ages, it finally occurred to me
+> to file a bug about it:
+>
+> It's rather rude of `getdebian-bug-get-bug-as-email' to default to
+> sticking downloaded mbox files loose in ~/, isn't it?
+>
+> (And might it not make sense to try and use the same files as the bts(1)
+> command from the devscripts package?)
+>
+
+Hi Samuel
+
+There is already a variable "debian-bug-download-directory" which can be
+customized. Is there an obviously better default? I guess we could put
+things in /tmp by default, with a minor privacy leak on multiuser
+systems.
+
+d
+
+# body 1
diff --git a/test/corpora/duplicate/msg-2-2:2, b/test/corpora/duplicate/msg-2-2:2,
new file mode 100644
index 00000000..a7549c47
--- /dev/null
+++ b/test/corpora/duplicate/msg-2-2:2,
@@ -0,0 +1,140 @@
+Return-path: <bounces+20181025-bremner=debian.org@tracker.debian.org>
+Envelope-to: david@tethera.net
+Delivery-date: Thu, 25 Oct 2018 09:45:10 -0400
+Received: from muffat.debian.org ([2607:f8f0:614:1::1274:33])
+	by fethera.tethera.net with esmtp (Exim 4.89)
+	(envelope-from <bounces+20181025-bremner=debian.org@tracker.debian.org>)
+	id 1gFfwj-0004Y9-69
+	for david@tethera.net; Thu, 25 Oct 2018 09:45:10 -0400
+Received: from ticharich.debian.org ([2001:41c8:1000:21::21:23])
+	from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=ticharich.debian.org,EMAIL=hostmaster@ticharich.debian.org (verified)
+	by muffat.debian.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
+	(Exim 4.89)
+	(envelope-from <bounces+20181025-bremner=debian.org@tracker.debian.org>)
+	id 1gFfwi-0004A1-J6
+	for david@tethera.net; Thu, 25 Oct 2018 13:45:08 +0000
+Received: from localhost ([::1] helo=ticharich.debian.org)
+	by ticharich.debian.org with esmtp (Exim 4.89)
+	(envelope-from <bounces+20181025-bremner=debian.org@tracker.debian.org>)
+	id 1gFfwh-0002Ex-6w
+	for david@tethera.net; Thu, 25 Oct 2018 13:45:07 +0000
+Received: from mailly.debian.org ([2001:41b8:202:deb:6564:a62:52c3:4b72])
+	from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=mailly.debian.org,EMAIL=hostmaster@mailly.debian.org (verified)
+	by ticharich.debian.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
+	(Exim 4.89)
+	(envelope-from <debbugs@buxtehude.debian.org>)
+	id 1gFfwg-0002Em-NI
+	for dispatch+emacs-goodies-el@tracker.debian.org; Thu, 25 Oct 2018 13:45:06 +0000
+Received: from quantz.debian.org ([2001:41c8:1000:21::21:28])
+	from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=quantz.debian.org,EMAIL=hostmaster@quantz.debian.org (verified)
+	by mailly.debian.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
+	(Exim 4.89)
+	(envelope-from <debbugs@buxtehude.debian.org>)
+	id 1gFfwg-0004h1-AC
+	for dispatch+emacs-goodies-el@tracker.debian.org; Thu, 25 Oct 2018 13:45:06 +0000
+Received: from qa by quantz.debian.org with local (Exim 4.89)
+	(envelope-from <debbugs@buxtehude.debian.org>)
+	id 1gFfwf-0007Lg-TQ
+	for dispatch+emacs-goodies-el@tracker.debian.org; Thu, 25 Oct 2018 13:45:05 +0000
+Received: from buxtehude.debian.org ([2607:f8f0:614:1::1274:39])
+	from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=buxtehude.debian.org,EMAIL=hostmaster@buxtehude.debian.org (verified)
+	by quantz.debian.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
+	(Exim 4.89)
+	(envelope-from <debbugs@buxtehude.debian.org>)
+	id 1gFfwf-0007J0-3r; Thu, 25 Oct 2018 13:45:05 +0000
+Received: from debbugs by buxtehude.debian.org with local (Exim 4.89)
+	(envelope-from <debbugs@buxtehude.debian.org>)
+	id 1gFfwc-0003jj-VU; Thu, 25 Oct 2018 13:45:02 +0000
+X-Loop: owner@bugs.debian.org
+Subject: Bug#695159: debian-el: Shouldn't put downloaded bugs loose in ~/
+Reply-To: David Bremner <bremner@debian.org>, 695159@bugs.debian.org
+Resent-From: David Bremner <bremner@debian.org>
+Resent-To: debian-bugs-dist@lists.debian.org
+Resent-CC: Debian Emacsen team <debian-emacsen@lists.debian.org>
+X-Loop: owner@bugs.debian.org
+Resent-Date: Thu, 25 Oct 2018 13:45:01 +0000
+Resent-Message-ID: <handler.695159.B.154047490313415@bugs.debian.org>
+X-Debian-PR-Message: followup 695159
+X-Debian-PR-Package: debian-el
+X-Debian-PR-Keywords: 
+References: <87vcch7hxy.fsf@naesten.dyndns.org> <87vcch7hxy.fsf@naesten.dyndns.org>
+X-Debian-PR-Source: debian-el, emacs-goodies-el
+Received: via spool by submit@bugs.debian.org id=B.154047490313415
+          (code B); Thu, 25 Oct 2018 13:45:01 +0000
+Received: (at submit) by bugs.debian.org; 25 Oct 2018 13:41:43 +0000
+X-Spam-Checker-Version: SpamAssassin 3.4.1-bugs.debian.org_2005_01_02
+	(2015-04-28) on buxtehude.debian.org
+X-Spam-Level: 
+X-Spam-Status: No, score=-19.5 required=4.0 tests=BAYES_00,FROMDEVELOPER,GMAIL,
+	HAS_BUG_NUMBER,TXREP autolearn=ham autolearn_force=no
+	version=3.4.1-bugs.debian.org_2005_01_02
+X-Spam-Bayes: score:0.0000 Tokens: new, 16; hammy, 110; neutral, 41; spammy,
+	2. spammytokens:0.971-+--privacy, 0.857-+--customized
+	hammytokens:0.000-+--UD:el, 0.000-+--H*F:U*bremner, 0.000-+--Maintainer,
+	0.000-+--sitelisp, 0.000-+--site-lisp
+Received: from fethera.tethera.net ([2607:5300:60:c5::1])
+	by buxtehude.debian.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
+	(Exim 4.89)
+	(envelope-from <bremner@debian.org>)
+	id 1gFftO-0003U6-RV; Thu, 25 Oct 2018 13:41:42 +0000
+Received: from remotemail by fethera.tethera.net with local (Exim 4.89)
+	(envelope-from <bremner@debian.org>)
+	id 1gFftL-0004VK-V8; Thu, 25 Oct 2018 09:41:39 -0400
+Received: (nullmailer pid 477 invoked by uid 1000);
+	Thu, 25 Oct 2018 13:41:38 -0000
+From: David Bremner <bremner@debian.org>
+To: Samuel Bronson <naesten@gmail.com>, 695159@bugs.debian.org, Debian Bug Tracking System <submit@bugs.debian.org>
+In-Reply-To: <87vcch7hxy.fsf@naesten.dyndns.org>
+Date: Thu, 25 Oct 2018 10:41:38 -0300
+Message-ID: <87r2geywh9.fsf@tethera.net>
+MIME-Version: 1.0
+Content-Type: text/plain
+Delivered-To: submit@bugs.debian.org
+Delivered-To: emacs-goodies-el@packages.qa.debian.org
+Delivered-To: dispatch+emacs-goodies-el@tracker.debian.org
+X-Loop: dispatch@tracker.debian.org
+X-Distro-Tracker-Keyword: bts
+X-Distro-Tracker-Package: emacs-goodies-el
+List-Id: <emacs-goodies-el.tracker.debian.org>
+X-Debian: tracker.debian.org
+X-Debian-Package: emacs-goodies-el
+X-PTS-Package: emacs-goodies-el
+X-PTS-Keyword: bts
+X-Distro-Tracker-Team: emacsen
+X-Spam_score: -2.3
+X-Spam_score_int: -22
+X-Spam_bar: --
+
+
+Control: severity -1 minor
+Control: tag -1 moreinfo
+
+Samuel Bronson <naesten@gmail.com> writes:
+
+> Package: debian-el
+> Version: 35.2+nmu1
+> Severity: normal
+> File: /usr/share/emacs/site-lisp/debian-el/debian-bug.el
+>
+> Dear Maintainer,
+>
+> After being mildly annoyed with this for ages, it finally occurred to me
+> to file a bug about it:
+>
+> It's rather rude of `getdebian-bug-get-bug-as-email' to default to
+> sticking downloaded mbox files loose in ~/, isn't it?
+>
+> (And might it not make sense to try and use the same files as the bts(1)
+> command from the devscripts package?)
+>
+
+Hi Samuel
+
+There is already a variable "debian-bug-download-directory" which can be
+customized. Is there an obviously better default? I guess we could put
+things in /tmp by default, with a minor privacy leak on multiuser
+systems.
+
+d
+
+# body 2
diff --git a/test/corpora/duplicate/msg-3-1:2, b/test/corpora/duplicate/msg-3-1:2,
new file mode 100644
index 00000000..8bb6a8c2
--- /dev/null
+++ b/test/corpora/duplicate/msg-3-1:2,
@@ -0,0 +1,183 @@
+Return-path: <pkg-emacsen-addons-bounces+bremner=debian.org@alioth-lists.debian.net>
+Envelope-to: david@tethera.net
+Delivery-date: Thu, 20 Dec 2018 13:27:11 -0500
+Received: from muffat.debian.org ([2607:f8f0:614:1::1274:33])
+	by fethera.tethera.net with esmtp (Exim 4.89)
+	(envelope-from <pkg-emacsen-addons-bounces+bremner=debian.org@alioth-lists.debian.net>)
+	id 1ga32M-0005ae-Ko
+	for david@tethera.net; Thu, 20 Dec 2018 13:27:11 -0500
+Received: from alioth-lists-01.debian.net ([2001:ba8:0:2c77:0:4:0:1])
+	by muffat.debian.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
+	(Exim 4.89)
+	(envelope-from <pkg-emacsen-addons-bounces+bremner=debian.org@alioth-lists.debian.net>)
+	id 1ga32K-0008PT-Nm
+	for david@tethera.net; Thu, 20 Dec 2018 18:27:08 +0000
+Received: from localhost ([::1] helo=alioth-lists-01.debian.net)
+	by alioth-lists-01.debian.net with esmtp (Exim 4.89)
+	(envelope-from <pkg-emacsen-addons-bounces+bremner=debian.org@alioth-lists.debian.net>)
+	id 1ga32I-0003to-Kn
+	for bremner@debian.org; Thu, 20 Dec 2018 18:27:06 +0000
+Received: from buxtehude.debian.org ([2607:f8f0:614:1::1274:39])
+ by alioth-lists-01.debian.net with esmtps
+ (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89)
+ (envelope-from <debbugs@buxtehude.debian.org>) id 1ga32H-0003tO-29
+ for pkg-emacsen-addons@lists.alioth.debian.org; Thu, 20 Dec 2018 18:27:05 +0000
+Received: from debbugs by buxtehude.debian.org with local (Exim 4.89)
+ (envelope-from <debbugs@buxtehude.debian.org>)
+ id 1ga32F-0005PP-9m; Thu, 20 Dec 2018 18:27:03 +0000
+X-Loop: owner@bugs.debian.org
+Resent-From: Sean Whitton <spwhitton@spwhitton.name>
+Resent-To: debian-bugs-dist@lists.debian.org
+Resent-CC: Debian Emacs addons team
+ <pkg-emacsen-addons@lists.alioth.debian.org>
+X-Loop: owner@bugs.debian.org
+Resent-Date: Thu, 20 Dec 2018 18:27:02 +0000
+Resent-Message-ID: <handler.916805.B916805.154533033319811@bugs.debian.org>
+X-Debian-PR-Message: followup 916805
+X-Debian-PR-Package: src:assess-el
+X-Debian-PR-Keywords: ftbfs
+References: <87k1k6h43h.fsf@zephyr.silentflame.com>
+X-Debian-PR-Source: assess-el
+Received: via spool by 916805-submit@bugs.debian.org id=B916805.154533033319811
+ (code B ref 916805); Thu, 20 Dec 2018 18:27:02 +0000
+Received: (at 916805) by bugs.debian.org; 20 Dec 2018 18:25:33 +0000
+X-Spam-Checker-Version: SpamAssassin 3.4.2-bugs.debian.org_2005_01_02
+ (2018-09-13) on buxtehude.debian.org
+X-Spam-Level: 
+X-Spam-Status: No, score=-8.8 required=4.0 tests=BAYES_00,DKIM_SIGNED,
+ DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,PGPSIGNATURE,RCVD_IN_DNSWL_LOW,
+ SORTED_RECIPS,SPF_HELO_PASS,SPF_PASS,SUSPICIOUS_RECIPS,TXREP
+ autolearn=ham autolearn_force=no
+ version=3.4.2-bugs.debian.org_2005_01_02
+X-Spam-Bayes: score:0.0000 Tokens: new, 32; hammy, 83; neutral, 22; spammy, 1.
+ spammytokens:0.902-+--emails
+ hammytokens:0.000-+--HX-ME-Sender:xms, 
+ 0.000-+--H*RU:10.202.2.43,
+ 0.000-+--Hx-spam-relays-external:10.202.2.43, 0.000-+--H*F:U*spwhitton,
+ 0.000-+--H*F:D*spwhitton.name
+Received: from wout2-smtp.messagingengine.com ([64.147.123.25])
+ by buxtehude.debian.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
+ (Exim 4.89) (envelope-from <spwhitton@spwhitton.name>)
+ id 1ga30m-00059C-Kv; Thu, 20 Dec 2018 18:25:32 +0000
+Received: from compute3.internal (compute3.nyi.internal [10.202.2.43])
+ by mailout.west.internal (Postfix) with ESMTP id C50B712F6;
+ Thu, 20 Dec 2018 13:25:30 -0500 (EST)
+Received: from mailfrontend1 ([10.202.2.162])
+ by compute3.internal (MEProxy); Thu, 20 Dec 2018 13:25:31 -0500
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=spwhitton.name;
+ h=from:to:subject:date:message-id:mime-version:content-type; s=
+ fm1; bh=jAd0CK1DR6lBA7NSLH5FsHIYQv3lqnNZlsr/mb10zqE=; b=X9S4kI14
+ zxdg9IKMIyALL2Eao3GTyyojuATJkgCqJvZWd8RWpty6RBStZfyeOqR1L3Gr5m3/
+ EVeiHQyFNnPor2xjMDmblfPS/u09JxVlc0KMpT0XXRfNWsVQn+U40nNRX15kXzZ/
+ D1rYhxpxzKRzU2tByUULCgbGlXAwJQtOXMDw3mpj1BxcoO13H/0H/KQTQ+AcpiOw
+ BV3JFKL/jA+mH8uAPIgNM2mUYZz5REO89eh3lPhLyc7tw745X+4ywZlo/Piqa0+6
+ BCldY9/nDR3csAUKx1+3hkpJPdqFALBWvG3SelGt44BqcoLsOJLB8QH6trCro39o
+ fEnBaUBTAkTAHA==
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=
+ messagingengine.com; h=content-type:date:from:message-id
+ :mime-version:subject:to:x-me-proxy:x-me-proxy:x-me-sender
+ :x-me-sender:x-sasl-enc; s=fm1; bh=jAd0CK1DR6lBA7NSLH5FsHIYQv3lq
+ nNZlsr/mb10zqE=; b=QYqLjUBZtfbO0DUlagvXRP2BPnpTgkvIna9/uCewkdoIH
+ /LuPW6DZUNWQa55qiDquqKXcs0tTODTEzYgeIDgqC+DDBTHnFQvXdWyS1X3o4sLL
+ 8dTKk8lv7M1/zKFxyg/ycNvPJGS9m4ZucGbxjwdgAcozhg7W1Qztxt9eVhPVnenS
+ 5sdeJ9mjIE7lYkKX4QVsXPOi86j6QlfMNyi/OnBfX2+95QiA/xPE/wEq4MYlLNm7
+ Av1P/8OrI4ImDKkOEivarktL+isYL7OXyGB4GfUTsydiy9dhP7RKPxrai1kJRu5S
+ b2470KXNatu2WkyMFrsdcwrSqyKIe096k5xPfVI2A==
+X-ME-Sender: <xms:mt4bXHFFQvAGVxMhHQP5DBif075kRubHE1KJQrR0OsDN2ClFFtlRXw>
+X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedtkedrudejfedguddugecutefuodetggdotefrod
+ ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfhuthenuceurghilhhouhhtmecu
+ fedttdenucfuohhrthgvugcurhgvtghiphhsucdlgedtmdenucfjughrpefhvffufffkgg
+ gtsehgtderredttddtnecuhfhrohhmpefuvggrnhcuhghhihhtthhonhcuoehsphifhhhi
+ thhtohhnsehsphifhhhithhtohhnrdhnrghmvgeqnecurfgrrhgrmhepmhgrihhlfhhroh
+ hmpehsphifhhhithhtohhnsehsphifhhhithhtohhnrdhnrghmvgenucevlhhushhtvghr
+ ufhiiigvpedt
+X-ME-Proxy: <xmx:mt4bXGqtKYX8StS4oLrucVpNHp3EoaoH6jbQkd2mTFzupx7FwIJ2dQ>
+ <xmx:mt4bXH457xpOO1PnlqWQoPt1r7kL_P9ta064wZO_JDW1QAycFDjIsg>
+ <xmx:mt4bXPQaOrPjDseNXftuMgX1Y9gyHDbVUCYSYNdX6oXwBQhAGwzqIw>
+ <xmx:mt4bXLbmA2mCpvakWE26qsCvS2IOX4eN0KdeU2tQi-SXYEBMLVpE3A>
+From: Sean Whitton <spwhitton@spwhitton.name>
+To: 916805@bugs.debian.org, 916807@bugs.debian.org, 916808@bugs.debian.org,
+ 916809@bugs.debian.org, 916811@bugs.debian.org, 916867@bugs.debian.org,
+ 916869@bugs.debian.org, 916872@bugs.debian.org, 916875@bugs.debian.org,
+ 916876@bugs.debian.org
+Date: Thu, 20 Dec 2018 18:25:26 +0000
+Message-ID: <87r2ecrr6x.fsf@zephyr.silentflame.com>
+MIME-Version: 1.0
+Received-SPF: pass client-ip=2607:f8f0:614:1::1274:39;
+ envelope-from=debbugs@buxtehude.debian.org; helo=buxtehude.debian.org
+x-debian-approved: yes
+Subject: [Pkg-emacsen-addons] Bug#916805: Increase severity to 'serious'
+X-BeenThere: pkg-emacsen-addons@alioth-lists.debian.net
+X-Mailman-Version: 2.1.23
+Precedence: list
+List-Id: Maintainers list for Emacs addon packages
+ <pkg-emacsen-addons.alioth-lists.debian.net>
+List-Unsubscribe: <https://alioth-lists.debian.net/cgi-bin/mailman/options/pkg-emacsen-addons>, 
+ <mailto:pkg-emacsen-addons-request@alioth-lists.debian.net?subject=unsubscribe>
+List-Archive: <http://alioth-lists.debian.net/pipermail/pkg-emacsen-addons/>
+List-Post: <mailto:pkg-emacsen-addons@alioth-lists.debian.net>
+List-Help: <mailto:pkg-emacsen-addons-request@alioth-lists.debian.net?subject=help>
+List-Subscribe: <https://alioth-lists.debian.net/cgi-bin/mailman/listinfo/pkg-emacsen-addons>,
+ <mailto:pkg-emacsen-addons-request@alioth-lists.debian.net?subject=subscribe>
+Reply-To: Sean Whitton <spwhitton@spwhitton.name>, 916805@bugs.debian.org
+Content-Type: multipart/mixed; boundary="===============5317466403067656157=="
+Errors-To: pkg-emacsen-addons-bounces+bremner=debian.org@alioth-lists.debian.net
+Sender: "Pkg-emacsen-addons"
+ <pkg-emacsen-addons-bounces+bremner=debian.org@alioth-lists.debian.net>
+X-Spam_score: 2.8
+X-Spam_score_int: 28
+X-Spam_bar: ++
+
+--===============5317466403067656157==
+Content-Type: multipart/signed; boundary="=-=-=";
+	micalg=pgp-sha512; protocol="application/pgp-signature"
+
+--=-=-=
+Content-Type: text/plain
+Content-Transfer-Encoding: quoted-printable
+
+control: severity -1 serious
+
+Hello,
+
+Emacs 26.1 has reached Debian unstable (sooner than expected; sorry for
+all the e-mails).
+
+=2D-=20
+Sean Whitton
+
+--=-=-=
+Content-Type: application/pgp-signature; name="signature.asc"
+
+-----BEGIN PGP SIGNATURE-----
+
+iQIzBAEBCgAdFiEEm5FwB64DDjbk/CSLaVt65L8GYkAFAlwb3pYACgkQaVt65L8G
+YkDLrhAAhORxZzZDE5vlXRm89JYA3jd9OyleioZvDDRCrpEd7CQ5AHiMMJizW1lU
+gn6OBIoW4O04TZ5oOuUnDHK/rS0G4zgNCJUyNf06zVECmdvkzspNNpQ3J5aOi4t2
+lhjRIFOKA9ifGsEqYLwP2dork1xFuyHEqHkDH8zpCTvdzkWky1bwAD/Pj5dArd7t
+FeQGsPm7/64H1/rHk8pSP2pQgRsMDX6rIdx3vuQ7r+NssdRq+II4e479l02TiCDi
+FBOX+n3nPXxREPdZ9EKL4SauL/AnRqpeC9GX6fC9OOnQeQ1xVTzNWKa6ixrqkFoH
+TI/vy51p16jFNgdkLkyLtZA8Tq72TIAKWbZC0GFzWJVNASWu7WDIoMn5pgoi454w
+TgsvK9MOnEYeABiDUa1ppaoMiP4+3j5yT0eWttTMSkcKjk1Ap1o+RfUxlIGl0Rog
+ShbG2y6Mv8FERtjzPVQ7VMLDN9zRIbtlSJFm7CboPNSAygzzzaA/RIN/e8MdbZoM
+a8AT9KiAVHEEcw+nWFAatAew5VP9iRZVgrVdWBszuaWOolxnYvpAL45WanqG0eab
+VMe66+rZ8momI0MsM9JcqBwXO+fOf8CrPSO9PL8VFEJXFLZQS7asFStJf2l8msWE
+3IYhvk4B6Nf1R96XzpXLlkOnoGtcnPVAvotrGU/rDfk5i/WF810=
+=mWfF
+-----END PGP SIGNATURE-----
+--=-=-=--
+
+
+--===============5317466403067656157==
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: base64
+Content-Disposition: inline
+
+X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KUGtnLWVtYWNz
+ZW4tYWRkb25zIG1haWxpbmcgbGlzdApQa2ctZW1hY3Nlbi1hZGRvbnNAYWxpb3RoLWxpc3RzLmRl
+Ymlhbi5uZXQKaHR0cHM6Ly9hbGlvdGgtbGlzdHMuZGViaWFuLm5ldC9jZ2ktYmluL21haWxtYW4v
+bGlzdGluZm8vcGtnLWVtYWNzZW4tYWRkb25zCg==
+
+--===============5317466403067656157==--
+
diff --git a/test/corpora/duplicate/msg-3-2:2, b/test/corpora/duplicate/msg-3-2:2,
new file mode 100644
index 00000000..292d515f
--- /dev/null
+++ b/test/corpora/duplicate/msg-3-2:2,
@@ -0,0 +1,184 @@
+Return-path: <pkg-emacsen-addons-bounces+bremner=debian.org@alioth-lists.debian.net>
+Envelope-to: david@tethera.net
+Delivery-date: Thu, 20 Dec 2018 13:27:12 -0500
+Received: from mailly.debian.org ([2001:41b8:202:deb:6564:a62:52c3:4b72])
+	by fethera.tethera.net with esmtp (Exim 4.89)
+	(envelope-from <pkg-emacsen-addons-bounces+bremner=debian.org@alioth-lists.debian.net>)
+	id 1ga32O-0005ap-Hn
+	for david@tethera.net; Thu, 20 Dec 2018 13:27:12 -0500
+Received: from alioth-lists-01.debian.net ([2001:ba8:0:2c77:0:4:0:1])
+	by mailly.debian.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
+	(Exim 4.89)
+	(envelope-from <pkg-emacsen-addons-bounces+bremner=debian.org@alioth-lists.debian.net>)
+	id 1ga32O-0004V7-4x
+	for david@tethera.net; Thu, 20 Dec 2018 18:27:12 +0000
+Received: from localhost ([::1] helo=alioth-lists-01.debian.net)
+	by alioth-lists-01.debian.net with esmtp (Exim 4.89)
+	(envelope-from <pkg-emacsen-addons-bounces+bremner=debian.org@alioth-lists.debian.net>)
+	id 1ga32N-0003wA-Sc
+	for bremner@debian.org; Thu, 20 Dec 2018 18:27:11 +0000
+Received: from buxtehude.debian.org ([2607:f8f0:614:1::1274:39])
+ by alioth-lists-01.debian.net with esmtps
+ (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89)
+ (envelope-from <debbugs@buxtehude.debian.org>) id 1ga32M-0003vQ-Q9
+ for pkg-emacsen-addons@lists.alioth.debian.org; Thu, 20 Dec 2018 18:27:10 +0000
+Received: from debbugs by buxtehude.debian.org with local (Exim 4.89)
+ (envelope-from <debbugs@buxtehude.debian.org>)
+ id 1ga32K-0005Sn-7B; Thu, 20 Dec 2018 18:27:08 +0000
+X-Loop: owner@bugs.debian.org
+Resent-From: Sean Whitton <spwhitton@spwhitton.name>
+Resent-To: debian-bugs-dist@lists.debian.org
+Resent-CC: Debian Emacs addons team
+ <pkg-emacsen-addons@lists.alioth.debian.org>
+X-Loop: owner@bugs.debian.org
+Resent-Date: Thu, 20 Dec 2018 18:27:06 +0000
+Resent-Message-ID: <handler.916808.B916808.154533033319830@bugs.debian.org>
+X-Debian-PR-Message: followup 916808
+X-Debian-PR-Package: src:hydra-el
+X-Debian-PR-Keywords: ftbfs
+References: <87bm5ih3w5.fsf@zephyr.silentflame.com>
+X-Debian-PR-Source: hydra-el
+Received: via spool by 916808-submit@bugs.debian.org id=B916808.154533033319830
+ (code B ref 916808); Thu, 20 Dec 2018 18:27:06 +0000
+Received: (at 916808) by bugs.debian.org; 20 Dec 2018 18:25:33 +0000
+X-Spam-Checker-Version: SpamAssassin 3.4.2-bugs.debian.org_2005_01_02
+ (2018-09-13) on buxtehude.debian.org
+X-Spam-Level: 
+X-Spam-Status: No, score=-11.3 required=4.0 tests=BAYES_00,DKIM_SIGNED,
+ DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,PGPSIGNATURE,RCVD_IN_DNSWL_LOW,
+ SORTED_RECIPS,SPF_HELO_PASS,SPF_PASS,SUSPICIOUS_RECIPS,TXREP
+ autolearn=unavailable autolearn_force=no
+ version=3.4.2-bugs.debian.org_2005_01_02
+X-Spam-Bayes: score:0.0000 Tokens: new, 0; hammy, 115; neutral, 22; spammy, 1.
+ spammytokens:0.902-+--emails
+ hammytokens:0.000-+--HX-ME-Sender:xms, 
+ 0.000-+--H*RU:10.202.2.43,
+ 0.000-+--Hx-spam-relays-external:10.202.2.43, 0.000-+--H*F:U*spwhitton,
+ 0.000-+--H*F:D*spwhitton.name
+Received: from wout2-smtp.messagingengine.com ([64.147.123.25])
+ by buxtehude.debian.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
+ (Exim 4.89) (envelope-from <spwhitton@spwhitton.name>)
+ id 1ga30m-00059C-Kv; Thu, 20 Dec 2018 18:25:32 +0000
+Received: from compute3.internal (compute3.nyi.internal [10.202.2.43])
+ by mailout.west.internal (Postfix) with ESMTP id C50B712F6;
+ Thu, 20 Dec 2018 13:25:30 -0500 (EST)
+Received: from mailfrontend1 ([10.202.2.162])
+ by compute3.internal (MEProxy); Thu, 20 Dec 2018 13:25:31 -0500
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=spwhitton.name;
+ h=from:to:subject:date:message-id:mime-version:content-type; s=
+ fm1; bh=jAd0CK1DR6lBA7NSLH5FsHIYQv3lqnNZlsr/mb10zqE=; b=X9S4kI14
+ zxdg9IKMIyALL2Eao3GTyyojuATJkgCqJvZWd8RWpty6RBStZfyeOqR1L3Gr5m3/
+ EVeiHQyFNnPor2xjMDmblfPS/u09JxVlc0KMpT0XXRfNWsVQn+U40nNRX15kXzZ/
+ D1rYhxpxzKRzU2tByUULCgbGlXAwJQtOXMDw3mpj1BxcoO13H/0H/KQTQ+AcpiOw
+ BV3JFKL/jA+mH8uAPIgNM2mUYZz5REO89eh3lPhLyc7tw745X+4ywZlo/Piqa0+6
+ BCldY9/nDR3csAUKx1+3hkpJPdqFALBWvG3SelGt44BqcoLsOJLB8QH6trCro39o
+ fEnBaUBTAkTAHA==
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=
+ messagingengine.com; h=content-type:date:from:message-id
+ :mime-version:subject:to:x-me-proxy:x-me-proxy:x-me-sender
+ :x-me-sender:x-sasl-enc; s=fm1; bh=jAd0CK1DR6lBA7NSLH5FsHIYQv3lq
+ nNZlsr/mb10zqE=; b=QYqLjUBZtfbO0DUlagvXRP2BPnpTgkvIna9/uCewkdoIH
+ /LuPW6DZUNWQa55qiDquqKXcs0tTODTEzYgeIDgqC+DDBTHnFQvXdWyS1X3o4sLL
+ 8dTKk8lv7M1/zKFxyg/ycNvPJGS9m4ZucGbxjwdgAcozhg7W1Qztxt9eVhPVnenS
+ 5sdeJ9mjIE7lYkKX4QVsXPOi86j6QlfMNyi/OnBfX2+95QiA/xPE/wEq4MYlLNm7
+ Av1P/8OrI4ImDKkOEivarktL+isYL7OXyGB4GfUTsydiy9dhP7RKPxrai1kJRu5S
+ b2470KXNatu2WkyMFrsdcwrSqyKIe096k5xPfVI2A==
+X-ME-Sender: <xms:mt4bXHFFQvAGVxMhHQP5DBif075kRubHE1KJQrR0OsDN2ClFFtlRXw>
+X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedtkedrudejfedguddugecutefuodetggdotefrod
+ ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfhuthenuceurghilhhouhhtmecu
+ fedttdenucfuohhrthgvugcurhgvtghiphhsucdlgedtmdenucfjughrpefhvffufffkgg
+ gtsehgtderredttddtnecuhfhrohhmpefuvggrnhcuhghhihhtthhonhcuoehsphifhhhi
+ thhtohhnsehsphifhhhithhtohhnrdhnrghmvgeqnecurfgrrhgrmhepmhgrihhlfhhroh
+ hmpehsphifhhhithhtohhnsehsphifhhhithhtohhnrdhnrghmvgenucevlhhushhtvghr
+ ufhiiigvpedt
+X-ME-Proxy: <xmx:mt4bXGqtKYX8StS4oLrucVpNHp3EoaoH6jbQkd2mTFzupx7FwIJ2dQ>
+ <xmx:mt4bXH457xpOO1PnlqWQoPt1r7kL_P9ta064wZO_JDW1QAycFDjIsg>
+ <xmx:mt4bXPQaOrPjDseNXftuMgX1Y9gyHDbVUCYSYNdX6oXwBQhAGwzqIw>
+ <xmx:mt4bXLbmA2mCpvakWE26qsCvS2IOX4eN0KdeU2tQi-SXYEBMLVpE3A>
+From: Sean Whitton <spwhitton@spwhitton.name>
+To: 916805@bugs.debian.org, 916807@bugs.debian.org, 916808@bugs.debian.org,
+ 916809@bugs.debian.org, 916811@bugs.debian.org, 916867@bugs.debian.org,
+ 916869@bugs.debian.org, 916872@bugs.debian.org, 916875@bugs.debian.org,
+ 916876@bugs.debian.org
+Date: Thu, 20 Dec 2018 18:25:26 +0000
+Message-ID: <87r2ecrr6x.fsf@zephyr.silentflame.com>
+MIME-Version: 1.0
+X-CrossAssassin-Score: 3
+Received-SPF: pass client-ip=2607:f8f0:614:1::1274:39;
+ envelope-from=debbugs@buxtehude.debian.org; helo=buxtehude.debian.org
+x-debian-approved: yes
+Subject: [Pkg-emacsen-addons] Bug#916808: Increase severity to 'serious'
+X-BeenThere: pkg-emacsen-addons@alioth-lists.debian.net
+X-Mailman-Version: 2.1.23
+Precedence: list
+List-Id: Maintainers list for Emacs addon packages
+ <pkg-emacsen-addons.alioth-lists.debian.net>
+List-Unsubscribe: <https://alioth-lists.debian.net/cgi-bin/mailman/options/pkg-emacsen-addons>, 
+ <mailto:pkg-emacsen-addons-request@alioth-lists.debian.net?subject=unsubscribe>
+List-Archive: <http://alioth-lists.debian.net/pipermail/pkg-emacsen-addons/>
+List-Post: <mailto:pkg-emacsen-addons@alioth-lists.debian.net>
+List-Help: <mailto:pkg-emacsen-addons-request@alioth-lists.debian.net?subject=help>
+List-Subscribe: <https://alioth-lists.debian.net/cgi-bin/mailman/listinfo/pkg-emacsen-addons>,
+ <mailto:pkg-emacsen-addons-request@alioth-lists.debian.net?subject=subscribe>
+Reply-To: Sean Whitton <spwhitton@spwhitton.name>, 916808@bugs.debian.org
+Content-Type: multipart/mixed; boundary="===============8231894308137086149=="
+Errors-To: pkg-emacsen-addons-bounces+bremner=debian.org@alioth-lists.debian.net
+Sender: "Pkg-emacsen-addons"
+ <pkg-emacsen-addons-bounces+bremner=debian.org@alioth-lists.debian.net>
+X-Spam_score: 2.8
+X-Spam_score_int: 28
+X-Spam_bar: ++
+
+--===============8231894308137086149==
+Content-Type: multipart/signed; boundary="=-=-=";
+	micalg=pgp-sha512; protocol="application/pgp-signature"
+
+--=-=-=
+Content-Type: text/plain
+Content-Transfer-Encoding: quoted-printable
+
+control: severity -1 serious
+
+Hello,
+
+Emacs 26.1 has reached Debian unstable (sooner than expected; sorry for
+all the e-mails).
+
+=2D-=20
+Sean Whitton
+
+--=-=-=
+Content-Type: application/pgp-signature; name="signature.asc"
+
+-----BEGIN PGP SIGNATURE-----
+
+iQIzBAEBCgAdFiEEm5FwB64DDjbk/CSLaVt65L8GYkAFAlwb3pYACgkQaVt65L8G
+YkDLrhAAhORxZzZDE5vlXRm89JYA3jd9OyleioZvDDRCrpEd7CQ5AHiMMJizW1lU
+gn6OBIoW4O04TZ5oOuUnDHK/rS0G4zgNCJUyNf06zVECmdvkzspNNpQ3J5aOi4t2
+lhjRIFOKA9ifGsEqYLwP2dork1xFuyHEqHkDH8zpCTvdzkWky1bwAD/Pj5dArd7t
+FeQGsPm7/64H1/rHk8pSP2pQgRsMDX6rIdx3vuQ7r+NssdRq+II4e479l02TiCDi
+FBOX+n3nPXxREPdZ9EKL4SauL/AnRqpeC9GX6fC9OOnQeQ1xVTzNWKa6ixrqkFoH
+TI/vy51p16jFNgdkLkyLtZA8Tq72TIAKWbZC0GFzWJVNASWu7WDIoMn5pgoi454w
+TgsvK9MOnEYeABiDUa1ppaoMiP4+3j5yT0eWttTMSkcKjk1Ap1o+RfUxlIGl0Rog
+ShbG2y6Mv8FERtjzPVQ7VMLDN9zRIbtlSJFm7CboPNSAygzzzaA/RIN/e8MdbZoM
+a8AT9KiAVHEEcw+nWFAatAew5VP9iRZVgrVdWBszuaWOolxnYvpAL45WanqG0eab
+VMe66+rZ8momI0MsM9JcqBwXO+fOf8CrPSO9PL8VFEJXFLZQS7asFStJf2l8msWE
+3IYhvk4B6Nf1R96XzpXLlkOnoGtcnPVAvotrGU/rDfk5i/WF810=
+=mWfF
+-----END PGP SIGNATURE-----
+--=-=-=--
+
+
+--===============8231894308137086149==
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: base64
+Content-Disposition: inline
+
+X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KUGtnLWVtYWNz
+ZW4tYWRkb25zIG1haWxpbmcgbGlzdApQa2ctZW1hY3Nlbi1hZGRvbnNAYWxpb3RoLWxpc3RzLmRl
+Ymlhbi5uZXQKaHR0cHM6Ly9hbGlvdGgtbGlzdHMuZGViaWFuLm5ldC9jZ2ktYmluL21haWxtYW4v
+bGlzdGluZm8vcGtnLWVtYWNzZW4tYWRkb25zCg==
+
+--===============8231894308137086149==--
+
diff --git a/test/corpora/duplicate/msg-3-3:2, b/test/corpora/duplicate/msg-3-3:2,
new file mode 100644
index 00000000..bff2473c
--- /dev/null
+++ b/test/corpora/duplicate/msg-3-3:2,
@@ -0,0 +1,178 @@
+Return-path: <bounces+20181220-bremner=debian.org@tracker.debian.org>
+Envelope-to: david@tethera.net
+Delivery-date: Thu, 20 Dec 2018 13:27:16 -0500
+Received: from muffat.debian.org ([2607:f8f0:614:1::1274:33])
+	by fethera.tethera.net with esmtp (Exim 4.89)
+	(envelope-from <bounces+20181220-bremner=debian.org@tracker.debian.org>)
+	id 1ga32S-0005aw-5h
+	for david@tethera.net; Thu, 20 Dec 2018 13:27:16 -0500
+Received: from ticharich.debian.org ([2001:41c8:1000:21::21:23])
+	from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=ticharich.debian.org,EMAIL=hostmaster@ticharich.debian.org (verified)
+	by muffat.debian.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
+	(Exim 4.89)
+	(envelope-from <bounces+20181220-bremner=debian.org@tracker.debian.org>)
+	id 1ga32R-0008QQ-PL
+	for david@tethera.net; Thu, 20 Dec 2018 18:27:15 +0000
+Received: from localhost ([::1] helo=ticharich.debian.org)
+	by ticharich.debian.org with esmtp (Exim 4.89)
+	(envelope-from <bounces+20181220-bremner=debian.org@tracker.debian.org>)
+	id 1ga32Q-0008BB-Ad
+	for david@tethera.net; Thu, 20 Dec 2018 18:27:14 +0000
+Received: from muffat.debian.org ([2607:f8f0:614:1::1274:33])
+	from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=muffat.debian.org,EMAIL=hostmaster@muffat.debian.org (verified)
+	by ticharich.debian.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
+	(Exim 4.89)
+	(envelope-from <debbugs@buxtehude.debian.org>)
+	id 1ga32Q-0008Ai-2N
+	for dispatch+haskell-mode@tracker.debian.org; Thu, 20 Dec 2018 18:27:14 +0000
+Received: from quantz.debian.org ([2001:41c8:1000:21::21:28])
+	from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=quantz.debian.org,EMAIL=hostmaster@quantz.debian.org (verified)
+	by muffat.debian.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
+	(Exim 4.89)
+	(envelope-from <debbugs@buxtehude.debian.org>)
+	id 1ga32O-0008QE-Eo
+	for dispatch+haskell-mode@tracker.debian.org; Thu, 20 Dec 2018 18:27:12 +0000
+Received: from qa by quantz.debian.org with local (Exim 4.89)
+	(envelope-from <debbugs@buxtehude.debian.org>)
+	id 1ga32M-0006hb-Vn
+	for dispatch+haskell-mode@tracker.debian.org; Thu, 20 Dec 2018 18:27:10 +0000
+Received: from buxtehude.debian.org ([2607:f8f0:614:1::1274:39])
+	from C=NA,ST=NA,L=Ankh Morpork,O=Debian SMTP,OU=Debian SMTP CA,CN=buxtehude.debian.org,EMAIL=hostmaster@buxtehude.debian.org (verified)
+	by quantz.debian.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
+	(Exim 4.89)
+	(envelope-from <debbugs@buxtehude.debian.org>)
+	id 1ga32J-0006gG-1x
+	for haskell-mode@packages.qa.debian.org; Thu, 20 Dec 2018 18:27:07 +0000
+Received: from debbugs by buxtehude.debian.org with local (Exim 4.89)
+	(envelope-from <debbugs@buxtehude.debian.org>)
+	id 1ga32H-0005SF-MF; Thu, 20 Dec 2018 18:27:05 +0000
+X-Loop: owner@bugs.debian.org
+Subject: Bug#916807: Increase severity to 'serious'
+Reply-To: Sean Whitton <spwhitton@spwhitton.name>, 916807@bugs.debian.org
+Resent-From: Sean Whitton <spwhitton@spwhitton.name>
+Resent-To: debian-bugs-dist@lists.debian.org
+Resent-CC: Debian Emacs addons team <pkg-emacsen-addons@lists.alioth.debian.org>
+X-Loop: owner@bugs.debian.org
+Resent-Date: Thu, 20 Dec 2018 18:27:04 +0000
+Resent-Message-ID: <handler.916807.B916807.154533033319820@bugs.debian.org>
+X-Debian-PR-Message: followup 916807
+X-Debian-PR-Package: src:haskell-mode
+X-Debian-PR-Keywords: ftbfs
+References: <87efaeh3zr.fsf@zephyr.silentflame.com>
+X-Debian-PR-Source: haskell-mode
+Received: via spool by 916807-submit@bugs.debian.org id=B916807.154533033319820
+          (code B ref 916807); Thu, 20 Dec 2018 18:27:04 +0000
+Received: (at 916807) by bugs.debian.org; 20 Dec 2018 18:25:33 +0000
+X-Spam-Checker-Version: SpamAssassin 3.4.2-bugs.debian.org_2005_01_02
+	(2018-09-13) on buxtehude.debian.org
+X-Spam-Level: 
+X-Spam-Status: No, score=-11.3 required=4.0 tests=BAYES_00,DKIM_SIGNED,
+	DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,PGPSIGNATURE,RCVD_IN_DNSWL_LOW,
+	SORTED_RECIPS,SPF_HELO_PASS,SPF_PASS,SUSPICIOUS_RECIPS,TXREP
+	autolearn=unavailable autolearn_force=no
+	version=3.4.2-bugs.debian.org_2005_01_02
+X-Spam-Bayes: score:0.0000 Tokens: new, 0; hammy, 115; neutral, 22; spammy, 1.
+	spammytokens:0.902-+--emails hammytokens:0.000-+--HX-ME-Sender:xms,
+	0.000-+--H*RU:10.202.2.43,
+	0.000-+--Hx-spam-relays-external:10.202.2.43,
+	0.000-+--H*F:D*spwhitton.name, 0.000-+--H*F:U*spwhitton
+Received: from wout2-smtp.messagingengine.com ([64.147.123.25])
+	by buxtehude.debian.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
+	(Exim 4.89)
+	(envelope-from <spwhitton@spwhitton.name>)
+	id 1ga30m-00059C-Kv; Thu, 20 Dec 2018 18:25:32 +0000
+Received: from compute3.internal (compute3.nyi.internal [10.202.2.43])
+	by mailout.west.internal (Postfix) with ESMTP id C50B712F6;
+	Thu, 20 Dec 2018 13:25:30 -0500 (EST)
+Received: from mailfrontend1 ([10.202.2.162])
+  by compute3.internal (MEProxy); Thu, 20 Dec 2018 13:25:31 -0500
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=spwhitton.name;
+	 h=from:to:subject:date:message-id:mime-version:content-type; s=
+	fm1; bh=jAd0CK1DR6lBA7NSLH5FsHIYQv3lqnNZlsr/mb10zqE=; b=X9S4kI14
+	zxdg9IKMIyALL2Eao3GTyyojuATJkgCqJvZWd8RWpty6RBStZfyeOqR1L3Gr5m3/
+	EVeiHQyFNnPor2xjMDmblfPS/u09JxVlc0KMpT0XXRfNWsVQn+U40nNRX15kXzZ/
+	D1rYhxpxzKRzU2tByUULCgbGlXAwJQtOXMDw3mpj1BxcoO13H/0H/KQTQ+AcpiOw
+	BV3JFKL/jA+mH8uAPIgNM2mUYZz5REO89eh3lPhLyc7tw745X+4ywZlo/Piqa0+6
+	BCldY9/nDR3csAUKx1+3hkpJPdqFALBWvG3SelGt44BqcoLsOJLB8QH6trCro39o
+	fEnBaUBTAkTAHA==
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=
+	messagingengine.com; h=content-type:date:from:message-id
+	:mime-version:subject:to:x-me-proxy:x-me-proxy:x-me-sender
+	:x-me-sender:x-sasl-enc; s=fm1; bh=jAd0CK1DR6lBA7NSLH5FsHIYQv3lq
+	nNZlsr/mb10zqE=; b=QYqLjUBZtfbO0DUlagvXRP2BPnpTgkvIna9/uCewkdoIH
+	/LuPW6DZUNWQa55qiDquqKXcs0tTODTEzYgeIDgqC+DDBTHnFQvXdWyS1X3o4sLL
+	8dTKk8lv7M1/zKFxyg/ycNvPJGS9m4ZucGbxjwdgAcozhg7W1Qztxt9eVhPVnenS
+	5sdeJ9mjIE7lYkKX4QVsXPOi86j6QlfMNyi/OnBfX2+95QiA/xPE/wEq4MYlLNm7
+	Av1P/8OrI4ImDKkOEivarktL+isYL7OXyGB4GfUTsydiy9dhP7RKPxrai1kJRu5S
+	b2470KXNatu2WkyMFrsdcwrSqyKIe096k5xPfVI2A==
+X-ME-Sender: <xms:mt4bXHFFQvAGVxMhHQP5DBif075kRubHE1KJQrR0OsDN2ClFFtlRXw>
+X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedtkedrudejfedguddugecutefuodetggdotefrod
+    ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfhuthenuceurghilhhouhhtmecu
+    fedttdenucfuohhrthgvugcurhgvtghiphhsucdlgedtmdenucfjughrpefhvffufffkgg
+    gtsehgtderredttddtnecuhfhrohhmpefuvggrnhcuhghhihhtthhonhcuoehsphifhhhi
+    thhtohhnsehsphifhhhithhtohhnrdhnrghmvgeqnecurfgrrhgrmhepmhgrihhlfhhroh
+    hmpehsphifhhhithhtohhnsehsphifhhhithhtohhnrdhnrghmvgenucevlhhushhtvghr
+    ufhiiigvpedt
+X-ME-Proxy: <xmx:mt4bXGqtKYX8StS4oLrucVpNHp3EoaoH6jbQkd2mTFzupx7FwIJ2dQ>
+    <xmx:mt4bXH457xpOO1PnlqWQoPt1r7kL_P9ta064wZO_JDW1QAycFDjIsg>
+    <xmx:mt4bXPQaOrPjDseNXftuMgX1Y9gyHDbVUCYSYNdX6oXwBQhAGwzqIw>
+    <xmx:mt4bXLbmA2mCpvakWE26qsCvS2IOX4eN0KdeU2tQi-SXYEBMLVpE3A>
+From: Sean Whitton <spwhitton@spwhitton.name>
+To: 916805@bugs.debian.org, 916807@bugs.debian.org, 916808@bugs.debian.org, 916809@bugs.debian.org, 916811@bugs.debian.org, 916867@bugs.debian.org, 916869@bugs.debian.org, 916872@bugs.debian.org, 916875@bugs.debian.org, 916876@bugs.debian.org
+Date: Thu, 20 Dec 2018 18:25:26 +0000
+Message-ID: <87r2ecrr6x.fsf@zephyr.silentflame.com>
+MIME-Version: 1.0
+Content-Type: multipart/signed; boundary="=-=-=";
+	micalg=pgp-sha512; protocol="application/pgp-signature"
+X-CrossAssassin-Score: 2
+Delivered-To: haskell-mode@packages.qa.debian.org
+Delivered-To: dispatch+haskell-mode@tracker.debian.org
+X-Loop: dispatch@tracker.debian.org
+X-Distro-Tracker-Keyword: bts
+X-Distro-Tracker-Package: haskell-mode
+List-Id: <haskell-mode.tracker.debian.org>
+X-Debian: tracker.debian.org
+X-Debian-Package: haskell-mode
+X-PTS-Package: haskell-mode
+X-PTS-Keyword: bts
+Precedence: list
+List-Unsubscribe: <mailto:control@tracker.debian.org?body=unsubscribe%20haskell-mode>
+X-Spam_score: 2.8
+X-Spam_score_int: 28
+X-Spam_bar: ++
+
+--=-=-=
+Content-Type: text/plain
+Content-Transfer-Encoding: quoted-printable
+
+control: severity -1 serious
+
+Hello,
+
+Emacs 26.1 has reached Debian unstable (sooner than expected; sorry for
+all the e-mails).
+
+=2D-=20
+Sean Whitton
+
+--=-=-=
+Content-Type: application/pgp-signature; name="signature.asc"
+
+-----BEGIN PGP SIGNATURE-----
+
+iQIzBAEBCgAdFiEEm5FwB64DDjbk/CSLaVt65L8GYkAFAlwb3pYACgkQaVt65L8G
+YkDLrhAAhORxZzZDE5vlXRm89JYA3jd9OyleioZvDDRCrpEd7CQ5AHiMMJizW1lU
+gn6OBIoW4O04TZ5oOuUnDHK/rS0G4zgNCJUyNf06zVECmdvkzspNNpQ3J5aOi4t2
+lhjRIFOKA9ifGsEqYLwP2dork1xFuyHEqHkDH8zpCTvdzkWky1bwAD/Pj5dArd7t
+FeQGsPm7/64H1/rHk8pSP2pQgRsMDX6rIdx3vuQ7r+NssdRq+II4e479l02TiCDi
+FBOX+n3nPXxREPdZ9EKL4SauL/AnRqpeC9GX6fC9OOnQeQ1xVTzNWKa6ixrqkFoH
+TI/vy51p16jFNgdkLkyLtZA8Tq72TIAKWbZC0GFzWJVNASWu7WDIoMn5pgoi454w
+TgsvK9MOnEYeABiDUa1ppaoMiP4+3j5yT0eWttTMSkcKjk1Ap1o+RfUxlIGl0Rog
+ShbG2y6Mv8FERtjzPVQ7VMLDN9zRIbtlSJFm7CboPNSAygzzzaA/RIN/e8MdbZoM
+a8AT9KiAVHEEcw+nWFAatAew5VP9iRZVgrVdWBszuaWOolxnYvpAL45WanqG0eab
+VMe66+rZ8momI0MsM9JcqBwXO+fOf8CrPSO9PL8VFEJXFLZQS7asFStJf2l8msWE
+3IYhvk4B6Nf1R96XzpXLlkOnoGtcnPVAvotrGU/rDfk5i/WF810=
+=mWfF
+-----END PGP SIGNATURE-----
+--=-=-=--
+
diff --git a/test/corpora/duplicate/msg-3-4:2, b/test/corpora/duplicate/msg-3-4:2,
new file mode 100644
index 00000000..861719d1
--- /dev/null
+++ b/test/corpora/duplicate/msg-3-4:2,
@@ -0,0 +1,184 @@
+Return-path: <pkg-emacsen-addons-bounces+bremner=debian.org@alioth-lists.debian.net>
+Envelope-to: david@tethera.net
+Delivery-date: Thu, 20 Dec 2018 13:27:16 -0500
+Received: from mailly.debian.org ([2001:41b8:202:deb:6564:a62:52c3:4b72])
+	by fethera.tethera.net with esmtp (Exim 4.89)
+	(envelope-from <pkg-emacsen-addons-bounces+bremner=debian.org@alioth-lists.debian.net>)
+	id 1ga32S-0005ax-Kz
+	for david@tethera.net; Thu, 20 Dec 2018 13:27:16 -0500
+Received: from alioth-lists-01.debian.net ([2001:ba8:0:2c77:0:4:0:1])
+	by mailly.debian.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
+	(Exim 4.89)
+	(envelope-from <pkg-emacsen-addons-bounces+bremner=debian.org@alioth-lists.debian.net>)
+	id 1ga32S-0004W6-8i
+	for david@tethera.net; Thu, 20 Dec 2018 18:27:16 +0000
+Received: from localhost ([::1] helo=alioth-lists-01.debian.net)
+	by alioth-lists-01.debian.net with esmtp (Exim 4.89)
+	(envelope-from <pkg-emacsen-addons-bounces+bremner=debian.org@alioth-lists.debian.net>)
+	id 1ga32S-0003xQ-0U
+	for bremner@debian.org; Thu, 20 Dec 2018 18:27:16 +0000
+Received: from buxtehude.debian.org ([2607:f8f0:614:1::1274:39])
+ by alioth-lists-01.debian.net with esmtps
+ (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89)
+ (envelope-from <debbugs@buxtehude.debian.org>) id 1ga32Q-0003wj-1x
+ for pkg-emacsen-addons@lists.alioth.debian.org; Thu, 20 Dec 2018 18:27:14 +0000
+Received: from debbugs by buxtehude.debian.org with local (Exim 4.89)
+ (envelope-from <debbugs@buxtehude.debian.org>)
+ id 1ga32O-0005Te-Sa; Thu, 20 Dec 2018 18:27:12 +0000
+X-Loop: owner@bugs.debian.org
+Resent-From: Sean Whitton <spwhitton@spwhitton.name>
+Resent-To: debian-bugs-dist@lists.debian.org
+Resent-CC: Debian Emacs addons team
+ <pkg-emacsen-addons@lists.alioth.debian.org>
+X-Loop: owner@bugs.debian.org
+Resent-Date: Thu, 20 Dec 2018 18:27:11 +0000
+Resent-Message-ID: <handler.916811.B916811.154533033319851@bugs.debian.org>
+X-Debian-PR-Message: followup 916811
+X-Debian-PR-Package: src:weechat-el
+X-Debian-PR-Keywords: ftbfs
+References: <8736quh3la.fsf@zephyr.silentflame.com>
+X-Debian-PR-Source: weechat-el
+Received: via spool by 916811-submit@bugs.debian.org id=B916811.154533033319851
+ (code B ref 916811); Thu, 20 Dec 2018 18:27:11 +0000
+Received: (at 916811) by bugs.debian.org; 20 Dec 2018 18:25:33 +0000
+X-Spam-Checker-Version: SpamAssassin 3.4.2-bugs.debian.org_2005_01_02
+ (2018-09-13) on buxtehude.debian.org
+X-Spam-Level: 
+X-Spam-Status: No, score=-15.2 required=4.0 tests=BAYES_00,DKIM_SIGNED,
+ DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,PGPSIGNATURE,RCVD_IN_DNSWL_LOW,
+ SORTED_RECIPS,SPF_HELO_PASS,SPF_PASS,SUSPICIOUS_RECIPS,TXREP
+ autolearn=unavailable autolearn_force=no
+ version=3.4.2-bugs.debian.org_2005_01_02
+X-Spam-Bayes: score:0.0000 Tokens: new, 0; hammy, 115; neutral, 22; spammy, 1.
+ spammytokens:0.902-+--emails
+ hammytokens:0.000-+--HX-ME-Sender:xms, 
+ 0.000-+--H*RU:10.202.2.43,
+ 0.000-+--Hx-spam-relays-external:10.202.2.43,
+ 0.000-+--H*F:D*spwhitton.name, 0.000-+--H*F:U*spwhitton
+Received: from wout2-smtp.messagingengine.com ([64.147.123.25])
+ by buxtehude.debian.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
+ (Exim 4.89) (envelope-from <spwhitton@spwhitton.name>)
+ id 1ga30m-00059C-Kv; Thu, 20 Dec 2018 18:25:32 +0000
+Received: from compute3.internal (compute3.nyi.internal [10.202.2.43])
+ by mailout.west.internal (Postfix) with ESMTP id C50B712F6;
+ Thu, 20 Dec 2018 13:25:30 -0500 (EST)
+Received: from mailfrontend1 ([10.202.2.162])
+ by compute3.internal (MEProxy); Thu, 20 Dec 2018 13:25:31 -0500
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=spwhitton.name;
+ h=from:to:subject:date:message-id:mime-version:content-type; s=
+ fm1; bh=jAd0CK1DR6lBA7NSLH5FsHIYQv3lqnNZlsr/mb10zqE=; b=X9S4kI14
+ zxdg9IKMIyALL2Eao3GTyyojuATJkgCqJvZWd8RWpty6RBStZfyeOqR1L3Gr5m3/
+ EVeiHQyFNnPor2xjMDmblfPS/u09JxVlc0KMpT0XXRfNWsVQn+U40nNRX15kXzZ/
+ D1rYhxpxzKRzU2tByUULCgbGlXAwJQtOXMDw3mpj1BxcoO13H/0H/KQTQ+AcpiOw
+ BV3JFKL/jA+mH8uAPIgNM2mUYZz5REO89eh3lPhLyc7tw745X+4ywZlo/Piqa0+6
+ BCldY9/nDR3csAUKx1+3hkpJPdqFALBWvG3SelGt44BqcoLsOJLB8QH6trCro39o
+ fEnBaUBTAkTAHA==
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=
+ messagingengine.com; h=content-type:date:from:message-id
+ :mime-version:subject:to:x-me-proxy:x-me-proxy:x-me-sender
+ :x-me-sender:x-sasl-enc; s=fm1; bh=jAd0CK1DR6lBA7NSLH5FsHIYQv3lq
+ nNZlsr/mb10zqE=; b=QYqLjUBZtfbO0DUlagvXRP2BPnpTgkvIna9/uCewkdoIH
+ /LuPW6DZUNWQa55qiDquqKXcs0tTODTEzYgeIDgqC+DDBTHnFQvXdWyS1X3o4sLL
+ 8dTKk8lv7M1/zKFxyg/ycNvPJGS9m4ZucGbxjwdgAcozhg7W1Qztxt9eVhPVnenS
+ 5sdeJ9mjIE7lYkKX4QVsXPOi86j6QlfMNyi/OnBfX2+95QiA/xPE/wEq4MYlLNm7
+ Av1P/8OrI4ImDKkOEivarktL+isYL7OXyGB4GfUTsydiy9dhP7RKPxrai1kJRu5S
+ b2470KXNatu2WkyMFrsdcwrSqyKIe096k5xPfVI2A==
+X-ME-Sender: <xms:mt4bXHFFQvAGVxMhHQP5DBif075kRubHE1KJQrR0OsDN2ClFFtlRXw>
+X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedtkedrudejfedguddugecutefuodetggdotefrod
+ ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfhuthenuceurghilhhouhhtmecu
+ fedttdenucfuohhrthgvugcurhgvtghiphhsucdlgedtmdenucfjughrpefhvffufffkgg
+ gtsehgtderredttddtnecuhfhrohhmpefuvggrnhcuhghhihhtthhonhcuoehsphifhhhi
+ thhtohhnsehsphifhhhithhtohhnrdhnrghmvgeqnecurfgrrhgrmhepmhgrihhlfhhroh
+ hmpehsphifhhhithhtohhnsehsphifhhhithhtohhnrdhnrghmvgenucevlhhushhtvghr
+ ufhiiigvpedt
+X-ME-Proxy: <xmx:mt4bXGqtKYX8StS4oLrucVpNHp3EoaoH6jbQkd2mTFzupx7FwIJ2dQ>
+ <xmx:mt4bXH457xpOO1PnlqWQoPt1r7kL_P9ta064wZO_JDW1QAycFDjIsg>
+ <xmx:mt4bXPQaOrPjDseNXftuMgX1Y9gyHDbVUCYSYNdX6oXwBQhAGwzqIw>
+ <xmx:mt4bXLbmA2mCpvakWE26qsCvS2IOX4eN0KdeU2tQi-SXYEBMLVpE3A>
+From: Sean Whitton <spwhitton@spwhitton.name>
+To: 916805@bugs.debian.org, 916807@bugs.debian.org, 916808@bugs.debian.org,
+ 916809@bugs.debian.org, 916811@bugs.debian.org, 916867@bugs.debian.org,
+ 916869@bugs.debian.org, 916872@bugs.debian.org, 916875@bugs.debian.org,
+ 916876@bugs.debian.org
+Date: Thu, 20 Dec 2018 18:25:26 +0000
+Message-ID: <87r2ecrr6x.fsf@zephyr.silentflame.com>
+MIME-Version: 1.0
+X-CrossAssassin-Score: 5
+Received-SPF: pass client-ip=2607:f8f0:614:1::1274:39;
+ envelope-from=debbugs@buxtehude.debian.org; helo=buxtehude.debian.org
+x-debian-approved: yes
+Subject: [Pkg-emacsen-addons] Bug#916811: Increase severity to 'serious'
+X-BeenThere: pkg-emacsen-addons@alioth-lists.debian.net
+X-Mailman-Version: 2.1.23
+Precedence: list
+List-Id: Maintainers list for Emacs addon packages
+ <pkg-emacsen-addons.alioth-lists.debian.net>
+List-Unsubscribe: <https://alioth-lists.debian.net/cgi-bin/mailman/options/pkg-emacsen-addons>, 
+ <mailto:pkg-emacsen-addons-request@alioth-lists.debian.net?subject=unsubscribe>
+List-Archive: <http://alioth-lists.debian.net/pipermail/pkg-emacsen-addons/>
+List-Post: <mailto:pkg-emacsen-addons@alioth-lists.debian.net>
+List-Help: <mailto:pkg-emacsen-addons-request@alioth-lists.debian.net?subject=help>
+List-Subscribe: <https://alioth-lists.debian.net/cgi-bin/mailman/listinfo/pkg-emacsen-addons>,
+ <mailto:pkg-emacsen-addons-request@alioth-lists.debian.net?subject=subscribe>
+Reply-To: Sean Whitton <spwhitton@spwhitton.name>, 916811@bugs.debian.org
+Content-Type: multipart/mixed; boundary="===============5359377007738902760=="
+Errors-To: pkg-emacsen-addons-bounces+bremner=debian.org@alioth-lists.debian.net
+Sender: "Pkg-emacsen-addons"
+ <pkg-emacsen-addons-bounces+bremner=debian.org@alioth-lists.debian.net>
+X-Spam_score: 2.8
+X-Spam_score_int: 28
+X-Spam_bar: ++
+
+--===============5359377007738902760==
+Content-Type: multipart/signed; boundary="=-=-=";
+	micalg=pgp-sha512; protocol="application/pgp-signature"
+
+--=-=-=
+Content-Type: text/plain
+Content-Transfer-Encoding: quoted-printable
+
+control: severity -1 serious
+
+Hello,
+
+Emacs 26.1 has reached Debian unstable (sooner than expected; sorry for
+all the e-mails).
+
+=2D-=20
+Sean Whitton
+
+--=-=-=
+Content-Type: application/pgp-signature; name="signature.asc"
+
+-----BEGIN PGP SIGNATURE-----
+
+iQIzBAEBCgAdFiEEm5FwB64DDjbk/CSLaVt65L8GYkAFAlwb3pYACgkQaVt65L8G
+YkDLrhAAhORxZzZDE5vlXRm89JYA3jd9OyleioZvDDRCrpEd7CQ5AHiMMJizW1lU
+gn6OBIoW4O04TZ5oOuUnDHK/rS0G4zgNCJUyNf06zVECmdvkzspNNpQ3J5aOi4t2
+lhjRIFOKA9ifGsEqYLwP2dork1xFuyHEqHkDH8zpCTvdzkWky1bwAD/Pj5dArd7t
+FeQGsPm7/64H1/rHk8pSP2pQgRsMDX6rIdx3vuQ7r+NssdRq+II4e479l02TiCDi
+FBOX+n3nPXxREPdZ9EKL4SauL/AnRqpeC9GX6fC9OOnQeQ1xVTzNWKa6ixrqkFoH
+TI/vy51p16jFNgdkLkyLtZA8Tq72TIAKWbZC0GFzWJVNASWu7WDIoMn5pgoi454w
+TgsvK9MOnEYeABiDUa1ppaoMiP4+3j5yT0eWttTMSkcKjk1Ap1o+RfUxlIGl0Rog
+ShbG2y6Mv8FERtjzPVQ7VMLDN9zRIbtlSJFm7CboPNSAygzzzaA/RIN/e8MdbZoM
+a8AT9KiAVHEEcw+nWFAatAew5VP9iRZVgrVdWBszuaWOolxnYvpAL45WanqG0eab
+VMe66+rZ8momI0MsM9JcqBwXO+fOf8CrPSO9PL8VFEJXFLZQS7asFStJf2l8msWE
+3IYhvk4B6Nf1R96XzpXLlkOnoGtcnPVAvotrGU/rDfk5i/WF810=
+=mWfF
+-----END PGP SIGNATURE-----
+--=-=-=--
+
+
+--===============5359377007738902760==
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: base64
+Content-Disposition: inline
+
+X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KUGtnLWVtYWNz
+ZW4tYWRkb25zIG1haWxpbmcgbGlzdApQa2ctZW1hY3Nlbi1hZGRvbnNAYWxpb3RoLWxpc3RzLmRl
+Ymlhbi5uZXQKaHR0cHM6Ly9hbGlvdGgtbGlzdHMuZGViaWFuLm5ldC9jZ2ktYmluL21haWxtYW4v
+bGlzdGluZm8vcGtnLWVtYWNzZW4tYWRkb25zCg==
+
+--===============5359377007738902760==--
+
diff --git a/test/corpora/duplicate/msg-3-5:2, b/test/corpora/duplicate/msg-3-5:2,
new file mode 100644
index 00000000..af26374d
--- /dev/null
+++ b/test/corpora/duplicate/msg-3-5:2,
@@ -0,0 +1,179 @@
+Return-path: <debian-science-maintainers-bounces+david=tethera.net@alioth-lists.debian.net>
+Envelope-to: david@tethera.net
+Delivery-date: Thu, 20 Dec 2018 13:27:21 -0500
+Received: from alioth-lists-01.debian.net ([2001:ba8:0:2c77:0:4:0:1])
+	by fethera.tethera.net with esmtp (Exim 4.89)
+	(envelope-from <debian-science-maintainers-bounces+david=tethera.net@alioth-lists.debian.net>)
+	id 1ga32X-0005bA-Go
+	for david@tethera.net; Thu, 20 Dec 2018 13:27:21 -0500
+Received: from localhost ([::1] helo=alioth-lists-01.debian.net)
+	by alioth-lists-01.debian.net with esmtp (Exim 4.89)
+	(envelope-from <debian-science-maintainers-bounces+david=tethera.net@alioth-lists.debian.net>)
+	id 1ga32U-0003yc-Ai
+	for david@tethera.net; Thu, 20 Dec 2018 18:27:18 +0000
+Received: from buxtehude.debian.org ([2607:f8f0:614:1::1274:39])
+ by alioth-lists-01.debian.net with esmtps
+ (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89)
+ (envelope-from <debbugs@buxtehude.debian.org>) id 1ga32S-0003xN-6J
+ for debian-science-maintainers@lists.alioth.debian.org;
+ Thu, 20 Dec 2018 18:27:16 +0000
+Received: from debbugs by buxtehude.debian.org with local (Exim 4.89)
+ (envelope-from <debbugs@buxtehude.debian.org>)
+ id 1ga32R-0005U9-0Z; Thu, 20 Dec 2018 18:27:15 +0000
+X-Loop: owner@bugs.debian.org
+Subject: Bug#916867: Increase severity to 'serious'
+Resent-From: Sean Whitton <spwhitton@spwhitton.name>
+Resent-To: debian-bugs-dist@lists.debian.org
+Resent-CC: Debian Science Maintainers
+ <debian-science-maintainers@lists.alioth.debian.org>
+X-Loop: owner@bugs.debian.org
+Resent-Date: Thu, 20 Dec 2018 18:27:13 +0000
+Resent-Message-ID: <handler.916867.B916867.154533033319861@bugs.debian.org>
+X-Debian-PR-Message: followup 916867
+X-Debian-PR-Package: src:hkl
+X-Debian-PR-Keywords: ftbfs
+References: <87sgyt2xyg.fsf@zephyr.silentflame.com>
+X-Debian-PR-Source: hkl
+Received: via spool by 916867-submit@bugs.debian.org id=B916867.154533033319861
+ (code B ref 916867); Thu, 20 Dec 2018 18:27:13 +0000
+Received: (at 916867) by bugs.debian.org; 20 Dec 2018 18:25:33 +0000
+X-Spam-Checker-Version: SpamAssassin 3.4.2-bugs.debian.org_2005_01_02
+ (2018-09-13) on buxtehude.debian.org
+X-Spam-Level: 
+X-Spam-Status: No, score=-13.0 required=4.0 tests=BAYES_00,DKIM_SIGNED,
+ DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,PGPSIGNATURE,RCVD_IN_DNSWL_LOW,
+ SORTED_RECIPS,SPF_HELO_PASS,SPF_PASS,SUSPICIOUS_RECIPS,TXREP
+ autolearn=unavailable autolearn_force=no
+ version=3.4.2-bugs.debian.org_2005_01_02
+X-Spam-Bayes: score:0.0000 Tokens: new, 0; hammy, 115; neutral, 22; spammy, 1.
+ spammytokens:0.902-+--emails
+ hammytokens:0.000-+--HX-ME-Sender:xms, 
+ 0.000-+--H*RU:10.202.2.43,
+ 0.000-+--Hx-spam-relays-external:10.202.2.43,
+ 0.000-+--H*F:D*spwhitton.name, 0.000-+--H*F:U*spwhitton
+Received: from wout2-smtp.messagingengine.com ([64.147.123.25])
+ by buxtehude.debian.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)
+ (Exim 4.89) (envelope-from <spwhitton@spwhitton.name>)
+ id 1ga30m-00059C-Kv; Thu, 20 Dec 2018 18:25:32 +0000
+Received: from compute3.internal (compute3.nyi.internal [10.202.2.43])
+ by mailout.west.internal (Postfix) with ESMTP id C50B712F6;
+ Thu, 20 Dec 2018 13:25:30 -0500 (EST)
+Received: from mailfrontend1 ([10.202.2.162])
+ by compute3.internal (MEProxy); Thu, 20 Dec 2018 13:25:31 -0500
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=spwhitton.name;
+ h=from:to:subject:date:message-id:mime-version:content-type; s=
+ fm1; bh=jAd0CK1DR6lBA7NSLH5FsHIYQv3lqnNZlsr/mb10zqE=; b=X9S4kI14
+ zxdg9IKMIyALL2Eao3GTyyojuATJkgCqJvZWd8RWpty6RBStZfyeOqR1L3Gr5m3/
+ EVeiHQyFNnPor2xjMDmblfPS/u09JxVlc0KMpT0XXRfNWsVQn+U40nNRX15kXzZ/
+ D1rYhxpxzKRzU2tByUULCgbGlXAwJQtOXMDw3mpj1BxcoO13H/0H/KQTQ+AcpiOw
+ BV3JFKL/jA+mH8uAPIgNM2mUYZz5REO89eh3lPhLyc7tw745X+4ywZlo/Piqa0+6
+ BCldY9/nDR3csAUKx1+3hkpJPdqFALBWvG3SelGt44BqcoLsOJLB8QH6trCro39o
+ fEnBaUBTAkTAHA==
+DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=
+ messagingengine.com; h=content-type:date:from:message-id
+ :mime-version:subject:to:x-me-proxy:x-me-proxy:x-me-sender
+ :x-me-sender:x-sasl-enc; s=fm1; bh=jAd0CK1DR6lBA7NSLH5FsHIYQv3lq
+ nNZlsr/mb10zqE=; b=QYqLjUBZtfbO0DUlagvXRP2BPnpTgkvIna9/uCewkdoIH
+ /LuPW6DZUNWQa55qiDquqKXcs0tTODTEzYgeIDgqC+DDBTHnFQvXdWyS1X3o4sLL
+ 8dTKk8lv7M1/zKFxyg/ycNvPJGS9m4ZucGbxjwdgAcozhg7W1Qztxt9eVhPVnenS
+ 5sdeJ9mjIE7lYkKX4QVsXPOi86j6QlfMNyi/OnBfX2+95QiA/xPE/wEq4MYlLNm7
+ Av1P/8OrI4ImDKkOEivarktL+isYL7OXyGB4GfUTsydiy9dhP7RKPxrai1kJRu5S
+ b2470KXNatu2WkyMFrsdcwrSqyKIe096k5xPfVI2A==
+X-ME-Sender: <xms:mt4bXHFFQvAGVxMhHQP5DBif075kRubHE1KJQrR0OsDN2ClFFtlRXw>
+X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedtkedrudejfedguddugecutefuodetggdotefrod
+ ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfhuthenuceurghilhhouhhtmecu
+ fedttdenucfuohhrthgvugcurhgvtghiphhsucdlgedtmdenucfjughrpefhvffufffkgg
+ gtsehgtderredttddtnecuhfhrohhmpefuvggrnhcuhghhihhtthhonhcuoehsphifhhhi
+ thhtohhnsehsphifhhhithhtohhnrdhnrghmvgeqnecurfgrrhgrmhepmhgrihhlfhhroh
+ hmpehsphifhhhithhtohhnsehsphifhhhithhtohhnrdhnrghmvgenucevlhhushhtvghr
+ ufhiiigvpedt
+X-ME-Proxy: <xmx:mt4bXGqtKYX8StS4oLrucVpNHp3EoaoH6jbQkd2mTFzupx7FwIJ2dQ>
+ <xmx:mt4bXH457xpOO1PnlqWQoPt1r7kL_P9ta064wZO_JDW1QAycFDjIsg>
+ <xmx:mt4bXPQaOrPjDseNXftuMgX1Y9gyHDbVUCYSYNdX6oXwBQhAGwzqIw>
+ <xmx:mt4bXLbmA2mCpvakWE26qsCvS2IOX4eN0KdeU2tQi-SXYEBMLVpE3A>
+From: Sean Whitton <spwhitton@spwhitton.name>
+To: 916805@bugs.debian.org, 916807@bugs.debian.org, 916808@bugs.debian.org,
+ 916809@bugs.debian.org, 916811@bugs.debian.org, 916867@bugs.debian.org,
+ 916869@bugs.debian.org, 916872@bugs.debian.org, 916875@bugs.debian.org,
+ 916876@bugs.debian.org
+Date: Thu, 20 Dec 2018 18:25:26 +0000
+Message-ID: <87r2ecrr6x.fsf@zephyr.silentflame.com>
+MIME-Version: 1.0
+X-CrossAssassin-Score: 6
+Received-SPF: pass client-ip=2607:f8f0:614:1::1274:39;
+ envelope-from=debbugs@buxtehude.debian.org; helo=buxtehude.debian.org
+x-debian-approved: yes
+X-BeenThere: debian-science-maintainers@alioth-lists.debian.net
+X-Mailman-Version: 2.1.23
+Precedence: list
+List-Id: Mailing list for maintainer discussions and BTS messages
+ <debian-science-maintainers.alioth-lists.debian.net>
+List-Unsubscribe: <https://alioth-lists.debian.net/cgi-bin/mailman/options/debian-science-maintainers>,
+ <mailto:debian-science-maintainers-request@alioth-lists.debian.net?subject=unsubscribe>
+List-Archive: <http://alioth-lists.debian.net/pipermail/debian-science-maintainers/>
+List-Post: <mailto:debian-science-maintainers@alioth-lists.debian.net>
+List-Help: <mailto:debian-science-maintainers-request@alioth-lists.debian.net?subject=help>
+List-Subscribe: <https://alioth-lists.debian.net/cgi-bin/mailman/listinfo/debian-science-maintainers>,
+ <mailto:debian-science-maintainers-request@alioth-lists.debian.net?subject=subscribe>
+Reply-To: Sean Whitton <spwhitton@spwhitton.name>, 916867@bugs.debian.org
+Content-Type: multipart/mixed; boundary="===============7686561040995282884=="
+Errors-To: debian-science-maintainers-bounces+david=tethera.net@alioth-lists.debian.net
+Sender: "debian-science-maintainers"
+ <debian-science-maintainers-bounces+david=tethera.net@alioth-lists.debian.net>
+X-Spam_score: 2.8
+X-Spam_score_int: 28
+X-Spam_bar: ++
+
+--===============7686561040995282884==
+Content-Type: multipart/signed; boundary="=-=-=";
+	micalg=pgp-sha512; protocol="application/pgp-signature"
+
+--=-=-=
+Content-Type: text/plain
+Content-Transfer-Encoding: quoted-printable
+
+control: severity -1 serious
+
+Hello,
+
+Emacs 26.1 has reached Debian unstable (sooner than expected; sorry for
+all the e-mails).
+
+=2D-=20
+Sean Whitton
+
+--=-=-=
+Content-Type: application/pgp-signature; name="signature.asc"
+
+-----BEGIN PGP SIGNATURE-----
+
+iQIzBAEBCgAdFiEEm5FwB64DDjbk/CSLaVt65L8GYkAFAlwb3pYACgkQaVt65L8G
+YkDLrhAAhORxZzZDE5vlXRm89JYA3jd9OyleioZvDDRCrpEd7CQ5AHiMMJizW1lU
+gn6OBIoW4O04TZ5oOuUnDHK/rS0G4zgNCJUyNf06zVECmdvkzspNNpQ3J5aOi4t2
+lhjRIFOKA9ifGsEqYLwP2dork1xFuyHEqHkDH8zpCTvdzkWky1bwAD/Pj5dArd7t
+FeQGsPm7/64H1/rHk8pSP2pQgRsMDX6rIdx3vuQ7r+NssdRq+II4e479l02TiCDi
+FBOX+n3nPXxREPdZ9EKL4SauL/AnRqpeC9GX6fC9OOnQeQ1xVTzNWKa6ixrqkFoH
+TI/vy51p16jFNgdkLkyLtZA8Tq72TIAKWbZC0GFzWJVNASWu7WDIoMn5pgoi454w
+TgsvK9MOnEYeABiDUa1ppaoMiP4+3j5yT0eWttTMSkcKjk1Ap1o+RfUxlIGl0Rog
+ShbG2y6Mv8FERtjzPVQ7VMLDN9zRIbtlSJFm7CboPNSAygzzzaA/RIN/e8MdbZoM
+a8AT9KiAVHEEcw+nWFAatAew5VP9iRZVgrVdWBszuaWOolxnYvpAL45WanqG0eab
+VMe66+rZ8momI0MsM9JcqBwXO+fOf8CrPSO9PL8VFEJXFLZQS7asFStJf2l8msWE
+3IYhvk4B6Nf1R96XzpXLlkOnoGtcnPVAvotrGU/rDfk5i/WF810=
+=mWfF
+-----END PGP SIGNATURE-----
+--=-=-=--
+
+
+--===============7686561040995282884==
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: base64
+Content-Disposition: inline
+
+LS0gCmRlYmlhbi1zY2llbmNlLW1haW50YWluZXJzIG1haWxpbmcgbGlzdApkZWJpYW4tc2NpZW5j
+ZS1tYWludGFpbmVyc0BhbGlvdGgtbGlzdHMuZGViaWFuLm5ldApodHRwczovL2FsaW90aC1saXN0
+cy5kZWJpYW4ubmV0L2NnaS1iaW4vbWFpbG1hbi9saXN0aW5mby9kZWJpYW4tc2NpZW5jZS1tYWlu
+dGFpbmVycw==
+
+--===============7686561040995282884==--
+
-- 
2.35.2

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 4/9] CLI/show: initial support for --duplicate for (raw output only)
  2022-07-01 21:45 Display duplicate messages in emacs front-end David Bremner
                   ` (2 preceding siblings ...)
  2022-07-01 21:45 ` [PATCH 3/9] test: add new corpus of duplicate messages David Bremner
@ 2022-07-01 21:45 ` David Bremner
  2022-07-01 21:45 ` [PATCH 5/9] CLI/show: support --duplicate for structured output David Bremner
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: David Bremner @ 2022-07-01 21:45 UTC (permalink / raw)
  To: notmuch

Add command line argument --duplicate, analogous with that already
supported for notmuch-search.

Use of a seperate function for _get_filename is mainly a form of
documentation at this point.

md5sum is of course a weak hash, but it is good enough for
this (non-adversarial) test suite use.
---
 doc/man1/notmuch-show.rst |  6 ++++++
 notmuch-client.h          |  1 +
 notmuch-show.c            | 21 ++++++++++++++++++++-
 test/T210-raw.sh          | 11 +++++++++++
 4 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/doc/man1/notmuch-show.rst b/doc/man1/notmuch-show.rst
index 55353921..2c0a0de6 100644
--- a/doc/man1/notmuch-show.rst
+++ b/doc/man1/notmuch-show.rst
@@ -27,6 +27,12 @@ Supported options for **show** include
 
 .. program:: show
 
+.. option:: --duplicate=N
+
+   Output duplicate number N. The numbering starts from 1, and matches
+   the order used by :option:`search --duplicate` and
+   :option:`search --output=files <search --output>`
+
 .. option:: --entire-thread=(true|false)
 
    If true, **notmuch show** outputs all messages in the thread of
diff --git a/notmuch-client.h b/notmuch-client.h
index 9f57ac5e..f8f987e7 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -75,6 +75,7 @@ typedef struct notmuch_show_params {
     bool entire_thread;
     bool omit_excluded;
     bool output_body;
+    int duplicate;
     int part;
     _notmuch_crypto_t crypto;
     bool include_html;
diff --git a/notmuch-show.c b/notmuch-show.c
index 6a54d9c1..7b57aab3 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -23,6 +23,20 @@
 #include "sprinter.h"
 #include "zlib-extra.h"
 
+static const char *
+_get_filename (notmuch_message_t *message, int index) {
+    notmuch_filenames_t *filenames = notmuch_message_get_filenames (message);
+    int i=1;
+
+    for (;
+	 notmuch_filenames_valid (filenames);
+	 notmuch_filenames_move_to_next (filenames), i++) {
+	if (i >= index)
+	    return notmuch_filenames_get (filenames);
+    }
+    return NULL;
+}
+
 static const char *
 _get_tags_as_string (const void *ctx, notmuch_message_t *message)
 {
@@ -925,7 +939,7 @@ format_part_raw (unused (const void *ctx), unused (sprinter_t *sp),
 	char buf[4096];
 	notmuch_status_t ret = NOTMUCH_STATUS_FILE_ERROR;
 
-	filename = notmuch_message_get_filename (node->envelope_file);
+	filename = _get_filename (node->envelope_file, params->duplicate);
 	if (filename == NULL) {
 	    fprintf (stderr, "Error: Cannot get message filename.\n");
 	    goto DONE;
@@ -1266,6 +1280,7 @@ notmuch_show_command (notmuch_database_t *notmuch, int argc, char *argv[])
     sprinter_t *sprinter;
     notmuch_show_params_t params = {
 	.part = -1,
+	.duplicate = 0,
 	.omit_excluded = true,
 	.output_body = true,
 	.crypto = { .decrypt = NOTMUCH_DECRYPT_AUTO },
@@ -1306,6 +1321,7 @@ notmuch_show_command (notmuch_database_t *notmuch, int argc, char *argv[])
 	{ .opt_bool = &params.crypto.verify, .name = "verify" },
 	{ .opt_bool = &params.output_body, .name = "body" },
 	{ .opt_bool = &params.include_html, .name = "include-html" },
+	{ .opt_int = &params.duplicate, .name = "duplicate" },
 	{ .opt_inherit = notmuch_shared_options },
 	{ }
     };
@@ -1324,6 +1340,9 @@ notmuch_show_command (notmuch_database_t *notmuch, int argc, char *argv[])
     /* specifying a part implies single message display */
     single_message = params.part >= 0;
 
+    /* specifying a duplicate also implies single message display */
+    single_message = single_message || (params.duplicate>0);
+
     if (format == NOTMUCH_FORMAT_NOT_SPECIFIED) {
 	/* if part was requested and format was not specified, use format=raw */
 	if (params.part >= 0)
diff --git a/test/T210-raw.sh b/test/T210-raw.sh
index e1d50bf9..44082028 100755
--- a/test/T210-raw.sh
+++ b/test/T210-raw.sh
@@ -64,4 +64,15 @@ for pow in {10..20}; do
     test_expect_success "notmuch show --format=raw subject:$size > /dev/null"
 done
 
+add_email_corpus duplicate
+ID=87r2ecrr6x.fsf@zephyr.silentflame.com
+test_begin_subtest "raw content, duplicate files"
+rm -f OUTPUT.raw
+for dup in {1..5}; do
+    notmuch show --format=raw --duplicate=${dup} --format=raw id:${ID} | md5sum | cut -f1 -d' '  >> OUTPUT.raw
+done
+sort OUTPUT.raw > OUTPUT
+notmuch search --output=files id:${ID} | xargs md5sum | cut -f1 -d ' ' | sort > EXPECTED
+test_expect_equal_file_nonempty EXPECTED OUTPUT
+
 test_done
-- 
2.35.2

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 5/9] CLI/show: support --duplicate for structured output
  2022-07-01 21:45 Display duplicate messages in emacs front-end David Bremner
                   ` (3 preceding siblings ...)
  2022-07-01 21:45 ` [PATCH 4/9] CLI/show: initial support for --duplicate for (raw output only) David Bremner
@ 2022-07-01 21:45 ` David Bremner
  2022-07-01 21:45 ` [PATCH 6/9] emacs/show: provide notmuch-show-choose-duplicate David Bremner
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: David Bremner @ 2022-07-01 21:45 UTC (permalink / raw)
  To: notmuch

This introduces a new mandatory key for message structures, namely
"duplicate". Per convention in devel/schemata this does _not_ increase
the format version. This means that clients are responsible for
checking that it exists, and not crashing if it does not.

The main functional change is teaching mime_node_open to understand a
'duplicate' argument.

Support for --duplicate in notmuch-reply would make sense, but we
defer it to a later commit.
---
 devel/schemata    |  1 +
 mime-node.c       | 32 +++++++++++++++++++++++---------
 notmuch-client.h  |  5 ++++-
 notmuch-reply.c   |  4 ++--
 notmuch-show.c    | 12 ++++++++----
 test/T160-json.sh |  4 +++-
 test/T170-sexp.sh |  2 +-
 test/T520-show.sh | 36 ++++++++++++++++++++++++++++++++++++
 test/test-lib.sh  |  2 ++
 9 files changed, 80 insertions(+), 18 deletions(-)

diff --git a/devel/schemata b/devel/schemata
index 01810888..66bcdbed 100644
--- a/devel/schemata
+++ b/devel/schemata
@@ -83,6 +83,7 @@ message = {
 
     headers:        headers,
     crypto:         crypto,
+    duplicate:      integer,
     body?:          [part]    # omitted if --body=false
 }
 
diff --git a/mime-node.c b/mime-node.c
index d29c4e48..890c8a0d 100644
--- a/mime-node.c
+++ b/mime-node.c
@@ -78,13 +78,14 @@ mime_node_get_message_crypto_status (mime_node_t *node)
 
 notmuch_status_t
 mime_node_open (const void *ctx, notmuch_message_t *message,
+		int duplicate,
 		_notmuch_crypto_t *crypto, mime_node_t **root_out)
 {
     const char *filename = notmuch_message_get_filename (message);
     mime_node_context_t *mctx;
     mime_node_t *root;
     notmuch_status_t status;
-    int fd;
+    int fd = -1;
 
     root = talloc_zero (ctx, mime_node_t);
     if (root == NULL) {
@@ -103,20 +104,33 @@ mime_node_open (const void *ctx, notmuch_message_t *message,
     talloc_set_destructor (mctx, _mime_node_context_free);
 
     /* Fast path */
-    fd = open (filename, O_RDONLY);
+    if (duplicate <= 0)
+	fd = open (filename, O_RDONLY);
     if (fd == -1) {
-	/* Slow path - for some reason the first file in the list is
-	 * not available anymore. This is clearly a problem in the
+	/* Slow path - Either we are trying to open a specific file, or
+	 * for some reason the first file in the list is
+	 * not available anymore. The latter is clearly a problem in the
 	 * database, but we are not going to let this problem be a
 	 * show stopper */
 	notmuch_filenames_t *filenames;
+	int i=1;
+
 	for (filenames = notmuch_message_get_filenames (message);
 	     notmuch_filenames_valid (filenames);
-	     notmuch_filenames_move_to_next (filenames)) {
-	    filename = notmuch_filenames_get (filenames);
-	    fd = open (filename, O_RDONLY);
-	    if (fd != -1)
-		break;
+	     notmuch_filenames_move_to_next (filenames), i++) {
+	    if (i>= duplicate) {
+		filename = notmuch_filenames_get (filenames);
+		fd = open (filename, O_RDONLY);
+		if (fd != -1) {
+		    break;
+		} else {
+		    if (duplicate > 0) {
+			fprintf (stderr, "Error opening %s: %s\n", filename, strerror (errno));
+			status = NOTMUCH_STATUS_FILE_ERROR;
+			goto DONE;
+		    }
+		}
+	    }
 	}
 
 	talloc_free (filenames);
diff --git a/notmuch-client.h b/notmuch-client.h
index f8f987e7..21b49908 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -230,6 +230,7 @@ show_one_part (const char *filename, int part);
 
 void
 format_part_sprinter (const void *ctx, struct sprinter *sp, mime_node_t *node,
+		      int duplicate,
 		      bool output_body,
 		      bool include_html);
 
@@ -389,7 +390,8 @@ struct mime_node {
 };
 
 /* Construct a new MIME node pointing to the root message part of
- * message. If crypto->verify is true, signed child parts will be
+ * message. Use the duplicate-th filename if that parameter is
+ * positive. If crypto->verify is true, signed child parts will be
  * verified. If crypto->decrypt is NOTMUCH_DECRYPT_TRUE, encrypted
  * child parts will be decrypted using either stored session keys or
  * asymmetric crypto.  If crypto->decrypt is NOTMUCH_DECRYPT_AUTO,
@@ -407,6 +409,7 @@ struct mime_node {
  */
 notmuch_status_t
 mime_node_open (const void *ctx, notmuch_message_t *message,
+		int duplicate,
 		_notmuch_crypto_t *crypto, mime_node_t **node_out);
 
 /* Return a new MIME node for the requested child part of parent.
diff --git a/notmuch-reply.c b/notmuch-reply.c
index 9fca22db..40576f19 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -663,7 +663,7 @@ do_reply (notmuch_database_t *notmuch,
 	 notmuch_messages_move_to_next (messages)) {
 	message = notmuch_messages_get (messages);
 
-	if (mime_node_open (notmuch, message, &params->crypto, &node))
+	if (mime_node_open (notmuch, message, -1, &params->crypto, &node))
 	    return 1;
 
 	reply = create_reply_message (notmuch, message,
@@ -683,7 +683,7 @@ do_reply (notmuch_database_t *notmuch,
 
 	    /* Start the original */
 	    sp->map_key (sp, "original");
-	    format_part_sprinter (notmuch, sp, node, true, false);
+	    format_part_sprinter (notmuch, sp, node, -1, true, false);
 
 	    /* End */
 	    sp->end (sp);
diff --git a/notmuch-show.c b/notmuch-show.c
index 7b57aab3..c162cc57 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -672,6 +672,7 @@ format_omitted_part_meta_sprinter (sprinter_t *sp, GMimeObject *meta, GMimePart
 
 void
 format_part_sprinter (const void *ctx, sprinter_t *sp, mime_node_t *node,
+		      int duplicate,
 		      bool output_body,
 		      bool include_html)
 {
@@ -683,10 +684,13 @@ format_part_sprinter (const void *ctx, sprinter_t *sp, mime_node_t *node,
 	sp->begin_map (sp);
 	format_message_sprinter (sp, node->envelope_file);
 
+	sp->map_key (sp, "duplicate");
+	sp->integer (sp, duplicate > 0 ? duplicate : 1);
+
 	if (output_body) {
 	    sp->map_key (sp, "body");
 	    sp->begin_list (sp);
-	    format_part_sprinter (ctx, sp, mime_node_child (node, 0), true, include_html);
+	    format_part_sprinter (ctx, sp, mime_node_child (node, 0), -1, true, include_html);
 	    sp->end (sp);
 	}
 
@@ -850,7 +854,7 @@ format_part_sprinter (const void *ctx, sprinter_t *sp, mime_node_t *node,
     }
 
     for (i = 0; i < node->nchildren; i++)
-	format_part_sprinter (ctx, sp, mime_node_child (node, i), true, include_html);
+	format_part_sprinter (ctx, sp, mime_node_child (node, i), -1, true, include_html);
 
     /* Close content structures */
     for (i = 0; i < nclose; i++)
@@ -864,7 +868,7 @@ format_part_sprinter_entry (const void *ctx, sprinter_t *sp,
 			    mime_node_t *node, unused (int indent),
 			    const notmuch_show_params_t *params)
 {
-    format_part_sprinter (ctx, sp, node, params->output_body, params->include_html);
+    format_part_sprinter (ctx, sp, node, params->duplicate, params->output_body, params->include_html);
 
     return NOTMUCH_STATUS_SUCCESS;
 }
@@ -1018,7 +1022,7 @@ show_message (void *ctx,
 	session_key_count_error = notmuch_message_count_properties (message, "session-key",
 								    &session_keys);
 
-    status = mime_node_open (local, message, &(params->crypto), &root);
+    status = mime_node_open (local, message, params->duplicate, &(params->crypto), &root);
     if (status)
 	goto DONE;
     part = mime_node_seek_dfs (root, (params->part < 0 ? 0 : params->part));
diff --git a/test/T160-json.sh b/test/T160-json.sh
index e1252353..4a797f6a 100755
--- a/test/T160-json.sh
+++ b/test/T160-json.sh
@@ -49,7 +49,7 @@ output=$(notmuch show --format=json "id:$id")
 filename=$(notmuch search --output=files "id:$id")
 # Get length of README after base64-encoding, minus additional newline.
 attachment_length=$(( $(base64 $NOTMUCH_SRCDIR/test/README | wc -c) - 1 ))
-test_expect_equal_json "$output" "[[[{\"id\": \"$id\",  \"crypto\": {}, \"match\": true, \"excluded\": false, \"filename\": [\"$filename\"], \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\"], \"headers\": {\"Subject\": \"$subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"test_suite@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"multipart/mixed\", \"content\": [{\"id\": 2, \"content-type\": \"text/plain\", \"content\": \"This is a test message with inline attachment with a filename\"}, {\"id\": 3, \"content-type\": \"application/octet-stream\", \"content-length\": $attachment_length, \"content-transfer-encoding\": \"base64\", \"content-disposition\": \"inline\", \"filename\": \"README\"}]}]}, []]]]"
+test_expect_equal_json "$output" "[[[{\"id\": \"$id\", \"duplicate\": 1, \"crypto\": {}, \"match\": true, \"excluded\": false, \"filename\": [\"$filename\"], \"timestamp\": 946728000, \"date_relative\": \"2000-01-01\", \"tags\": [\"inbox\"], \"headers\": {\"Subject\": \"$subject\", \"From\": \"Notmuch Test Suite <test_suite@notmuchmail.org>\", \"To\": \"test_suite@notmuchmail.org\", \"Date\": \"Sat, 01 Jan 2000 12:00:00 +0000\"}, \"body\": [{\"id\": 1, \"content-type\": \"multipart/mixed\", \"content\": [{\"id\": 2, \"content-type\": \"text/plain\", \"content\": \"This is a test message with inline attachment with a filename\"}, {\"id\": 3, \"content-type\": \"application/octet-stream\", \"content-length\": $attachment_length, \"content-transfer-encoding\": \"base64\", \"content-disposition\": \"inline\", \"filename\": \"README\"}]}]}, []]]]"
 
 test_begin_subtest "Search message: json, utf-8"
 add_message "[subject]=\"json-search-utf8-body-sübjéct\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[body]=\"jsön-search-méssage\""
@@ -97,6 +97,7 @@ cat <<EOF > EXPECTED
         [
             {
                 "date_relative": "2001-01-05",
+		"duplicate": 1,
                 "excluded": false,
                 "filename": [
                     "${MAIL_DIR}/copy1",
@@ -132,6 +133,7 @@ cat <<EOF > EXPECTED
         [
             {
                 "date_relative": "2001-01-05",
+		"duplicate": 1,
                 "excluded": false,
                 "filename": "${MAIL_DIR}/copy1",
                 "headers": {
diff --git a/test/T170-sexp.sh b/test/T170-sexp.sh
index 76e07481..0be94bd2 100755
--- a/test/T170-sexp.sh
+++ b/test/T170-sexp.sh
@@ -45,7 +45,7 @@ output=$(notmuch show --format=sexp "id:$id")
 filename=$(notmuch search --output=files "id:$id")
 # Get length of README after base64-encoding, minus additional newline.
 attachment_length=$(( $(base64 $NOTMUCH_SRCDIR/test/README | wc -c) - 1 ))
-test_expect_equal "$output" "((((:id \"$id\" :match t :excluded nil :filename (\"$filename\") :timestamp 946728000 :date_relative \"2000-01-01\" :tags (\"inbox\") :body ((:id 1 :content-type \"multipart/mixed\" :content ((:id 2 :content-type \"text/plain\" :content \"This is a test message with inline attachment with a filename\") (:id 3 :content-type \"application/octet-stream\" :content-disposition \"inline\" :filename \"README\" :content-transfer-encoding \"base64\" :content-length $attachment_length)))) :crypto () :headers (:Subject \"sexp-show-inline-attachment-filename\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"test_suite@notmuchmail.org\" :Date \"Sat, 01 Jan 2000 12:00:00 +0000\")) ())))"
+test_expect_equal "$output" "((((:id \"$id\" :match t :excluded nil :filename (\"$filename\") :timestamp 946728000 :date_relative \"2000-01-01\" :tags (\"inbox\") :duplicate 1 :body ((:id 1 :content-type \"multipart/mixed\" :content ((:id 2 :content-type \"text/plain\" :content \"This is a test message with inline attachment with a filename\") (:id 3 :content-type \"application/octet-stream\" :content-disposition \"inline\" :filename \"README\" :content-transfer-encoding \"base64\" :content-length $attachment_length)))) :crypto () :headers (:Subject \"sexp-show-inline-attachment-filename\" :From \"Notmuch Test Suite <test_suite@notmuchmail.org>\" :To \"test_suite@notmuchmail.org\" :Date \"Sat, 01 Jan 2000 12:00:00 +0000\")) ())))"
 
 test_begin_subtest "show extra headers"
 add_message "[subject]=\"extra-headers\"" "[date]=\"Sat, 01 Jan 2000 12:00:00 -0000\"" "[in-reply-to]=\"<parent@notmuch-test-suite>\"" "[body]=\"extra-headers test\""\
diff --git a/test/T520-show.sh b/test/T520-show.sh
index 12bde6c7..c7b73a6d 100755
--- a/test/T520-show.sh
+++ b/test/T520-show.sh
@@ -45,4 +45,40 @@ if [ $NOTMUCH_HAVE_SFSEXP -eq 1 ]; then
 
 fi
 
+add_email_corpus duplicate
+
+ID1=debian/2.6.1.dfsg-4-1-g87ea161@87ea161e851dfb1ea324af00e4ecfccc18875e15
+
+test_begin_subtest "format json, --duplicate=2, duplicate key"
+output=$(notmuch show --format=json --duplicate=2 id:${ID1})
+test_json_nodes <<<"$output" "dup:['duplicate']=2"
+
+test_begin_subtest "format json, subject, --duplicate=1"
+output=$(notmuch show --format=json --duplicate=1 id:${ID1})
+file=$(notmuch search --output=files id:${ID1} | head -n 1)
+subject=$(sed -n 's/^Subject: \(.*\)$/\1/p' < $file)
+test_json_nodes <<<"$output" "subject:['headers']['Subject']=\"$subject\""
+
+test_begin_subtest "format json, subject, --duplicate=2"
+output=$(notmuch show --format=json --duplicate=2 id:${ID1})
+file=$(notmuch search --output=files id:${ID1} | tail -n 1)
+subject=$(sed -n 's/^Subject: \(.*\)$/\1/p' < $file)
+test_json_nodes <<<"$output" "subject:['headers']['Subject']=\"$subject\""
+
+ID2=87r2geywh9.fsf@tethera.net
+for dup in {1..2}; do
+    test_begin_subtest "format json, body, --duplicate=${dup}"
+    output=$(notmuch show --format=json --duplicate=${dup} id:${ID2} | \
+	     $NOTMUCH_PYTHON -B "$NOTMUCH_SRCDIR"/test/json_check_nodes.py "body:['body'][0]['content']" | \
+	     grep '^# body')
+    test_expect_equal "$output" "# body ${dup}"
+done
+
+ID3=87r2ecrr6x.fsf@zephyr.silentflame.com
+for dup in {1..5}; do
+    test_begin_subtest "format json, --duplicate=${dup}, 'duplicate' key"
+    output=$(notmuch show --format=json --duplicate=${dup} id:${ID3})
+    test_json_nodes <<<"$output" "dup:['duplicate']=${dup}"
+done
+
 test_done
diff --git a/test/test-lib.sh b/test/test-lib.sh
index 4eb58ea0..95411fdc 100644
--- a/test/test-lib.sh
+++ b/test/test-lib.sh
@@ -522,6 +522,7 @@ notmuch_json_show_sanitize () {
 	-e 's|"id": "[^"]*",|"id": "XXXXX",|g' \
 	-e 's|"Date": "Fri, 05 Jan 2001 [^"]*0000"|"Date": "GENERATED_DATE"|g' \
 	-e 's|"filename": "signature.asc",||g' \
+	-e 's|"duplicate": 1,||g' \
 	-e 's|"filename": \["/[^"]*"\],|"filename": \["YYYYY"\],|g' \
 	-e 's|"timestamp": 97.......|"timestamp": 42|g' \
 	-e 's|"content-length": [1-9][0-9]*|"content-length": "NONZERO"|g'
@@ -532,6 +533,7 @@ notmuch_sexp_show_sanitize () {
 	-e 's|:id "[^"]*"|:id "XXXXX"|g' \
 	-e 's|:Date "Sat, 01 Jan 2000 [^"]*0000"|:Date "GENERATED_DATE"|g' \
 	-e 's|:filename "signature.asc"||g' \
+	-e 's|:duplicate 1 ||g' \
 	-e 's|:filename ("/[^"]*")|:filename ("YYYYY")|g' \
 	-e 's|:timestamp 9........|:timestamp 42|g' \
 	-e 's|:content-length [1-9][0-9]*|:content-length "NONZERO"|g'
-- 
2.35.2
\r

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 6/9] emacs/show: provide notmuch-show-choose-duplicate
  2022-07-01 21:45 Display duplicate messages in emacs front-end David Bremner
                   ` (4 preceding siblings ...)
  2022-07-01 21:45 ` [PATCH 5/9] CLI/show: support --duplicate for structured output David Bremner
@ 2022-07-01 21:45 ` David Bremner
  2022-07-01 21:45 ` [PATCH 7/9] emacs/show: display count of duplicates in headerline David Bremner
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: David Bremner @ 2022-07-01 21:45 UTC (permalink / raw)
  To: notmuch

This new command allows the user to interactively choose a different
duplicate (file) to display for a given message in
notmuch-show-mode. Since both tree and unthreaded view use
notmuch-show-mode, this provides the same facility there.
---
 devel/emacs-keybindings.org   |  1 +
 emacs/notmuch-lib.el          |  4 +++-
 emacs/notmuch-show.el         | 25 +++++++++++++++++++++++++
 test/T450-emacs-show.sh       | 29 +++++++++++++++++++++++++++++
 test/T460-emacs-tree.sh       | 14 ++++++++++++++
 test/T465-emacs-unthreaded.sh | 15 +++++++++++++++
 6 files changed, 87 insertions(+), 1 deletion(-)

diff --git a/devel/emacs-keybindings.org b/devel/emacs-keybindings.org
index 00977bc3..ad7f72ef 100644
--- a/devel/emacs-keybindings.org
+++ b/devel/emacs-keybindings.org
@@ -40,6 +40,7 @@
 | Z            | notmuch-tree-from-search-current-query | notmuch-tree-from-show-current-query                  |                                         |
 | =!=          |                                        | notmuch-show-toggle-elide-non-matching                |                                         |
 | =#=          |                                        | notmuch-show-print-message                            |                                         |
+| =%=          |                                        | notmuch-show-replace-msg                              |                                         |
 | =$=          |                                        | notmuch-show-toggle-process-crypto                    |                                         |
 | =*=          | notmuch-search-tag-all                 | notmuch-show-tag-all                                  | notmuch-tree-tag-thread                 |
 | +            | notmuch-search-add-tag                 | notmuch-show-add-tag                                  | notmuch-tree-add-tag                    |
diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el
index cc706924..84ba8c5e 100644
--- a/emacs/notmuch-lib.el
+++ b/emacs/notmuch-lib.el
@@ -1029,7 +1029,7 @@ status."
 
 (defvar-local notmuch-show-process-crypto nil)
 
-(defun notmuch--run-show (search-terms)
+(defun notmuch--run-show (search-terms &optional duplicate)
   "Return a list of threads of messages matching SEARCH-TERMS.
 
 A thread is a forest or list of trees. A tree is a two element
@@ -1038,6 +1038,8 @@ is a possibly empty forest of replies."
   (let ((args '("show" "--format=sexp" "--format-version=5")))
     (when notmuch-show-process-crypto
       (setq args (append args '("--decrypt=true"))))
+    (when duplicate
+      (setq args (append args (list (format "--duplicate=%d" duplicate)))))
     (setq args (append args search-terms))
     (apply #'notmuch-call-notmuch-sexp args)))
 
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 53493785..020a7dca 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -1127,6 +1127,30 @@ is t, hide the part initially and show the button."
 (defvar notmuch-show-previous-subject "")
 (make-variable-buffer-local 'notmuch-show-previous-subject)
 
+(defun notmuch-show-choose-duplicate (duplicate)
+  (interactive "Nduplicate: ")
+  (let ((count (length (notmuch-show-get-prop :filename))))
+    (when (or (> duplicate count)
+	      (< duplicate 1))
+      (error "Duplicate %d out of range [1,%d]" duplicate count)))
+  (notmuch-show-move-to-message-top)
+  (save-excursion
+    (let* ((extent (notmuch-show-message-extent))
+	   (id (notmuch-show-get-message-id))
+	   (depth (notmuch-show-get-depth))
+	   (inhibit-read-only t)
+	   (new-msg (notmuch--run-show (list id) duplicate)))
+      ;; clean up existing overlays to avoid extending them.
+      (dolist (o (overlays-in (car extent) (cdr extent)))
+	(delete-overlay o))
+      ;; pretend insertion is happening at end of buffer
+      (narrow-to-region (point-min) (car extent))
+      ;; Insert first, then delete, to avoid marker for start of next
+      ;; message being in same place as the start of this one.
+      (notmuch-show-insert-msg new-msg depth)
+      (widen)
+      (delete-region (point) (cdr extent)))))
+
 (defun notmuch-show-insert-msg (msg depth)
   "Insert the message MSG at depth DEPTH in the current thread."
   (let* ((headers (plist-get msg :headers))
@@ -1583,6 +1607,7 @@ reset based on the original query."
     (define-key map "#" 'notmuch-show-print-message)
     (define-key map "!" 'notmuch-show-toggle-elide-non-matching)
     (define-key map "$" 'notmuch-show-toggle-process-crypto)
+    (define-key map "%" 'notmuch-show-choose-duplicate)
     (define-key map "<" 'notmuch-show-toggle-thread-indentation)
     (define-key map "t" 'toggle-truncate-lines)
     (define-key map "." 'notmuch-show-part-map)
diff --git a/test/T450-emacs-show.sh b/test/T450-emacs-show.sh
index 64f174cf..9cc90d91 100755
--- a/test/T450-emacs-show.sh
+++ b/test/T450-emacs-show.sh
@@ -338,4 +338,33 @@ when we detect the word "attachment" and there's no attach? :p
 EOF
 test_expect_equal_file EXPECTED OUTPUT
 
+add_email_corpus duplicate
+
+ID3=87r2ecrr6x.fsf@zephyr.silentflame.com
+test_begin_subtest "duplicate=3"
+test_emacs "(notmuch-show \"id:${ID3}\")
+	   (notmuch-show-choose-duplicate 3)
+	   (test-visible-output \"OUTPUT\")"
+output=$(grep "Subject:" OUTPUT)
+file=$(notmuch search --output=files id:${ID3} | head -n 3 | tail -n 1)
+subject=$(grep '^Subject:' $file)
+test_expect_equal "$output" "$subject"
+
+test_begin_subtest "duplicate=0"
+test_emacs "(test-log-error
+	      (notmuch-show \"id:${ID3}\")
+	      (notmuch-show-choose-duplicate 0))"
+cat <<EOF > EXPECTED
+(error Duplicate 0 out of range [1,5])
+EOF
+test_expect_equal_file EXPECTED MESSAGES
+
+test_begin_subtest "duplicate=1000"
+test_emacs "(test-log-error
+	      (notmuch-show \"id:${ID3}\")
+	      (notmuch-show-choose-duplicate 1000))"
+cat <<EOF > EXPECTED
+(error Duplicate 1000 out of range [1,5])
+EOF
+test_expect_equal_file EXPECTED MESSAGES
 test_done
diff --git a/test/T460-emacs-tree.sh b/test/T460-emacs-tree.sh
index 0f23b418..bae26e3b 100755
--- a/test/T460-emacs-tree.sh
+++ b/test/T460-emacs-tree.sh
@@ -200,4 +200,18 @@ test_emacs '(test-log-error
 	        (notmuch-tree "*")))'
 test_expect_equal "$(cat MESSAGES)" "COMPLETE"
 
+add_email_corpus duplicate
+
+ID3=87r2ecrr6x.fsf@zephyr.silentflame.com
+test_begin_subtest "duplicate=3"
+test_emacs "(notmuch-tree \"id:${ID3}\")
+	   (notmuch-test-wait)
+	   (notmuch-tree-show-message t)
+	   (notmuch-show-choose-duplicate 3)
+	   (test-visible-output \"OUTPUT\")"
+output=$(grep "Subject:" OUTPUT)
+file=$(notmuch search --output=files id:${ID3} | head -n 3 | tail -n 1)
+subject=$(grep '^Subject:' $file)
+test_expect_equal "$output" "$subject"
+
 test_done
diff --git a/test/T465-emacs-unthreaded.sh b/test/T465-emacs-unthreaded.sh
index e7bc1439..9b96c7d7 100755
--- a/test/T465-emacs-unthreaded.sh
+++ b/test/T465-emacs-unthreaded.sh
@@ -57,4 +57,19 @@ test_emacs '(test-log-error
 	        (notmuch-unthreaded "*")))'
 test_expect_equal "$(cat MESSAGES)" "COMPLETE"
 
+add_email_corpus duplicate
+
+ID3=87r2ecrr6x.fsf@zephyr.silentflame.com
+test_begin_subtest "duplicate=3"
+test_emacs "(let ((notmuch-tree-show-out t))
+	      (notmuch-unthreaded \"id:${ID3}\")
+	      (notmuch-test-wait)
+	      (notmuch-tree-show-message nil)
+	      (notmuch-show-choose-duplicate 3)
+	      (test-visible-output \"OUTPUT\"))"
+output=$(grep "Subject:" OUTPUT)
+file=$(notmuch search --output=files id:${ID3} | head -n 3 | tail -n 1)
+subject=$(grep '^Subject:' $file)
+test_expect_equal "$output" "$subject"
+
 test_done
-- 
2.35.2

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 7/9] emacs/show: display count of duplicates in headerline
  2022-07-01 21:45 Display duplicate messages in emacs front-end David Bremner
                   ` (5 preceding siblings ...)
  2022-07-01 21:45 ` [PATCH 6/9] emacs/show: provide notmuch-show-choose-duplicate David Bremner
@ 2022-07-01 21:45 ` David Bremner
  2022-07-01 21:45 ` [PATCH 8/9] CLI/reply: support --duplicate argument David Bremner
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: David Bremner @ 2022-07-01 21:45 UTC (permalink / raw)
  To: notmuch

There is no real cost here, except screen real estate. Some people
might prefer hiding the duplicate count, but we leave that for a
future commit.
---
 emacs/notmuch-show.el                         | 15 +++++++++++---
 test/T450-emacs-show.sh                       |  8 +++++++-
 test/T460-emacs-tree.sh                       | 10 +++++++++-
 test/T465-emacs-unthreaded.sh                 | 12 ++++++++++-
 .../notmuch-show-duplicate-4                  | 20 +++++++++++++++++++
 5 files changed, 59 insertions(+), 6 deletions(-)
 create mode 100644 test/emacs-show.expected-output/notmuch-show-duplicate-4

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 020a7dca..edf39674 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -530,7 +530,7 @@ Return unchanged ADDRESS if parsing fails."
 	  (plist-put msg :height height)
 	  height))))
 
-(defun notmuch-show-insert-headerline (headers date tags depth)
+(defun notmuch-show-insert-headerline (headers date tags depth duplicate file-count)
   "Insert a notmuch style headerline based on HEADERS for a
 message at DEPTH in the current thread."
   (let ((start (point))
@@ -550,7 +550,14 @@ message at DEPTH in the current thread."
 	    date
 	    ") ("
 	    (notmuch-tag-format-tags tags tags)
-	    ")\n")
+	    ")")
+    (insert
+     (if (> file-count 1)
+	 (let ((txt (format "%d/%d\n" duplicate file-count)))
+	   (concat
+	    (notmuch-show-spaces-n (- (window-width) (+ (current-column) (length txt))))
+	    txt))
+       "\n"))
     (overlay-put (make-overlay start (point))
 		 'face 'notmuch-message-summary-face)))
 
@@ -1154,6 +1161,8 @@ is t, hide the part initially and show the button."
 (defun notmuch-show-insert-msg (msg depth)
   "Insert the message MSG at depth DEPTH in the current thread."
   (let* ((headers (plist-get msg :headers))
+	 (duplicate (or (plist-get msg :duplicate) 0))
+	 (files (length (plist-get msg :filename)))
 	 ;; Indentation causes the buffer offset of the start/end
 	 ;; points to move, so we must use markers.
 	 message-start message-end
@@ -1165,7 +1174,7 @@ is t, hide the part initially and show the button."
 				    (or (and notmuch-show-relative-dates
 					     (plist-get msg :date_relative))
 					(plist-get headers :Date))
-				    (plist-get msg :tags) depth)
+				    (plist-get msg :tags) depth duplicate files)
     (setq content-start (point-marker))
     ;; Set `headers-start' to point after the 'Subject:' header to be
     ;; compatible with the existing implementation. This just sets it
diff --git a/test/T450-emacs-show.sh b/test/T450-emacs-show.sh
index 9cc90d91..37940c96 100755
--- a/test/T450-emacs-show.sh
+++ b/test/T450-emacs-show.sh
@@ -341,7 +341,7 @@ test_expect_equal_file EXPECTED OUTPUT
 add_email_corpus duplicate
 
 ID3=87r2ecrr6x.fsf@zephyr.silentflame.com
-test_begin_subtest "duplicate=3"
+test_begin_subtest "duplicate=3, subject"
 test_emacs "(notmuch-show \"id:${ID3}\")
 	   (notmuch-show-choose-duplicate 3)
 	   (test-visible-output \"OUTPUT\")"
@@ -367,4 +367,10 @@ cat <<EOF > EXPECTED
 (error Duplicate 1000 out of range [1,5])
 EOF
 test_expect_equal_file EXPECTED MESSAGES
+test_begin_subtest "duplicate=4"
+test_emacs "(notmuch-show \"id:${ID3}\")
+	   (notmuch-show-choose-duplicate 4)
+	   (test-visible-output \"OUTPUT\")"
+test_expect_equal_file_nonempty $EXPECTED/notmuch-show-duplicate-4 OUTPUT
+
 test_done
diff --git a/test/T460-emacs-tree.sh b/test/T460-emacs-tree.sh
index bae26e3b..3a1c449e 100755
--- a/test/T460-emacs-tree.sh
+++ b/test/T460-emacs-tree.sh
@@ -203,7 +203,7 @@ test_expect_equal "$(cat MESSAGES)" "COMPLETE"
 add_email_corpus duplicate
 
 ID3=87r2ecrr6x.fsf@zephyr.silentflame.com
-test_begin_subtest "duplicate=3"
+test_begin_subtest "duplicate=3, subject"
 test_emacs "(notmuch-tree \"id:${ID3}\")
 	   (notmuch-test-wait)
 	   (notmuch-tree-show-message t)
@@ -214,4 +214,12 @@ file=$(notmuch search --output=files id:${ID3} | head -n 3 | tail -n 1)
 subject=$(grep '^Subject:' $file)
 test_expect_equal "$output" "$subject"
 
+test_begin_subtest "duplicate=4"
+test_emacs "(notmuch-show \"id:${ID3}\")
+	   (notmuch-test-wait)
+	   (notmuch-tree-show-message t)
+	   (notmuch-show-choose-duplicate 4)
+	   (test-visible-output \"OUTPUT\")"
+test_expect_equal_file_nonempty $NOTMUCH_SRCDIR/test/emacs-show.expected-output/notmuch-show-duplicate-4 OUTPUT
+
 test_done
diff --git a/test/T465-emacs-unthreaded.sh b/test/T465-emacs-unthreaded.sh
index 9b96c7d7..a3ff85fd 100755
--- a/test/T465-emacs-unthreaded.sh
+++ b/test/T465-emacs-unthreaded.sh
@@ -60,7 +60,7 @@ test_expect_equal "$(cat MESSAGES)" "COMPLETE"
 add_email_corpus duplicate
 
 ID3=87r2ecrr6x.fsf@zephyr.silentflame.com
-test_begin_subtest "duplicate=3"
+test_begin_subtest "duplicate=3, subject"
 test_emacs "(let ((notmuch-tree-show-out t))
 	      (notmuch-unthreaded \"id:${ID3}\")
 	      (notmuch-test-wait)
@@ -72,4 +72,14 @@ file=$(notmuch search --output=files id:${ID3} | head -n 3 | tail -n 1)
 subject=$(grep '^Subject:' $file)
 test_expect_equal "$output" "$subject"
 
+test_begin_subtest "duplicate=4"
+test_emacs "(let ((notmuch-tree-show-out t))
+	      (notmuch-unthreaded \"id:${ID3}\")
+	      (notmuch-test-wait)
+	      (notmuch-tree-show-message nil)
+	      (notmuch-show-choose-duplicate 4)
+	      (test-visible-output \"OUTPUT\"))"
+test_expect_equal_file_nonempty $NOTMUCH_SRCDIR/test/emacs-show.expected-output/notmuch-show-duplicate-4 OUTPUT
+
+
 test_done
diff --git a/test/emacs-show.expected-output/notmuch-show-duplicate-4 b/test/emacs-show.expected-output/notmuch-show-duplicate-4
new file mode 100644
index 00000000..6bf49d81
--- /dev/null
+++ b/test/emacs-show.expected-output/notmuch-show-duplicate-4
@@ -0,0 +1,20 @@
+Sean Whitton <spwhitton@spwhitton.name> (2018-12-20) (inbox signed)         4/5
+Subject: [Pkg-emacsen-addons] Bug#916811: Increase severity to 'serious'
+To: 916805@bugs.debian.org, 916807@bugs.debian.org, 916808@bugs.debian.org, 916809@bugs.debian.org, 916811@bugs.debian.org, 916867@bugs.debian.org, 916869@bugs.debian.org, 916872@bugs.debian.org, 916875@bugs.debian.org, 916876@bugs.debian.org
+Date: Thu, 20 Dec 2018 18:25:26 +0000
+
+[ multipart/mixed ]
+[ multipart/signed ]
+[ Unknown key ID 0x695B7AE4BF066240 or unsupported algorithm ]
+[ text/plain ]
+control: severity -1 serious
+
+Hello,
+
+Emacs 26.1 has reached Debian unstable (sooner than expected; sorry for
+all the e-mails).
+
+[ 2-line signature. Click/Enter to show. ]
+[ signature.asc: application/pgp-signature ]
+[ text/plain ]
+[ 4-line signature. Click/Enter to show. ]
-- 
2.35.2

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 8/9] CLI/reply: support --duplicate argument
  2022-07-01 21:45 Display duplicate messages in emacs front-end David Bremner
                   ` (6 preceding siblings ...)
  2022-07-01 21:45 ` [PATCH 7/9] emacs/show: display count of duplicates in headerline David Bremner
@ 2022-07-01 21:45 ` David Bremner
  2022-07-01 21:45 ` [PATCH 9/9] emacs/reply: reply to correct duplicate David Bremner
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 17+ messages in thread
From: David Bremner @ 2022-07-01 21:45 UTC (permalink / raw)
  To: notmuch

We want the reply used to match that shown e.g. in the emacs
interface. As a first step provide that functionality on the command
line.

Schema does not need updating as the duplicate key was already
present (with a constant value of 1).
---
 doc/man1/notmuch-reply.rst |  6 ++++++
 emacs/notmuch-show.el      |  2 +-
 notmuch-reply.c            |  6 ++++--
 test/T220-reply.sh         | 36 ++++++++++++++++++++++++++++++++++++
 4 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/doc/man1/notmuch-reply.rst b/doc/man1/notmuch-reply.rst
index fa0371f9..4f39a959 100644
--- a/doc/man1/notmuch-reply.rst
+++ b/doc/man1/notmuch-reply.rst
@@ -38,6 +38,12 @@ Supported options for **reply** include
 
 .. program:: reply
 
+.. option:: --duplicate=N
+
+   Reply to duplicate number N. The numbering starts from 1, and
+   matches the order used by :option:`show --duplicate` and
+   :option:`search --output=files <search --output>`.
+
 .. option:: --format=(default|json|sexp|headers-only)
 
    default
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index edf39674..ee01e470 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -555,7 +555,7 @@ message at DEPTH in the current thread."
      (if (> file-count 1)
 	 (let ((txt (format "%d/%d\n" duplicate file-count)))
 	   (concat
-	    (notmuch-show-spaces-n (- (window-width) (+ (current-column) (length txt))))
+	    (notmuch-show-spaces-n (max 0 (- (window-width) (+ (current-column) (length txt)))))
 	    txt))
        "\n"))
     (overlay-put (make-overlay start (point))
diff --git a/notmuch-reply.c b/notmuch-reply.c
index 40576f19..44297251 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -663,7 +663,7 @@ do_reply (notmuch_database_t *notmuch,
 	 notmuch_messages_move_to_next (messages)) {
 	message = notmuch_messages_get (messages);
 
-	if (mime_node_open (notmuch, message, -1, &params->crypto, &node))
+	if (mime_node_open (notmuch, message, params->duplicate, &params->crypto, &node))
 	    return 1;
 
 	reply = create_reply_message (notmuch, message,
@@ -683,7 +683,7 @@ do_reply (notmuch_database_t *notmuch,
 
 	    /* Start the original */
 	    sp->map_key (sp, "original");
-	    format_part_sprinter (notmuch, sp, node, -1, true, false);
+	    format_part_sprinter (notmuch, sp, node, params->duplicate, true, false);
 
 	    /* End */
 	    sp->end (sp);
@@ -715,6 +715,7 @@ notmuch_reply_command (notmuch_database_t *notmuch, int argc, char *argv[])
     int opt_index;
     notmuch_show_params_t params = {
 	.part = -1,
+	.duplicate = 0,
 	.crypto = { .decrypt = NOTMUCH_DECRYPT_AUTO },
     };
     int format = FORMAT_DEFAULT;
@@ -739,6 +740,7 @@ notmuch_reply_command (notmuch_database_t *notmuch, int argc, char *argv[])
 				      { "auto", NOTMUCH_DECRYPT_AUTO },
 				      { "true", NOTMUCH_DECRYPT_NOSTASH },
 				      { 0, 0 } } },
+	{ .opt_int = &params.duplicate, .name = "duplicate" },
 	{ .opt_inherit = notmuch_shared_options },
 	{ }
     };
diff --git a/test/T220-reply.sh b/test/T220-reply.sh
index 50179efc..207f5788 100755
--- a/test/T220-reply.sh
+++ b/test/T220-reply.sh
@@ -353,4 +353,40 @@ On Thu, 16 Jun 2016 22:14:41 -0400, Alice <alice@example.org> wrote:
 > Note the Cc: and cc: headers.
 OK"
 
+add_email_corpus duplicate
+
+ID1=debian/2.6.1.dfsg-4-1-g87ea161@87ea161e851dfb1ea324af00e4ecfccc18875e15
+
+test_begin_subtest "format json, --duplicate=2, duplicate key"
+output=$(notmuch reply --format=json --duplicate=2 id:${ID1})
+test_json_nodes <<<"$output" "dup:['original']['duplicate']=2"
+
+test_begin_subtest "format json, subject, --duplicate=1"
+output=$(notmuch reply --format=json --duplicate=1 id:${ID1})
+file=$(notmuch search --output=files id:${ID1} | head -n 1)
+subject=$(sed -n 's/^Subject: \(.*\)$/\1/p' < $file)
+test_json_nodes <<<"$output" "subject:['reply-headers']['Subject']=\"Re: $subject\""
+
+test_begin_subtest "format json, subject, --duplicate=2"
+output=$(notmuch reply --format=json --duplicate=2 id:${ID1})
+file=$(notmuch search --output=files id:${ID1} | tail -n 1)
+subject=$(sed -n 's/^Subject: \(.*\)$/\1/p' < $file)
+test_json_nodes <<<"$output" "subject:['reply-headers']['Subject']=\"Re: $subject\""
+
+ID2=87r2geywh9.fsf@tethera.net
+for dup in {1..2}; do
+    test_begin_subtest "format json, body, --duplicate=${dup}"
+    output=$(notmuch reply --format=json --duplicate=${dup} id:${ID2} | \
+	     $NOTMUCH_PYTHON -B "$NOTMUCH_SRCDIR"/test/json_check_nodes.py "body:['original']['body'][0]['content']" | \
+	     grep '^# body')
+    test_expect_equal "$output" "# body ${dup}"
+done
+
+ID3=87r2ecrr6x.fsf@zephyr.silentflame.com
+for dup in {1..5}; do
+    test_begin_subtest "format json, --duplicate=${dup}, 'duplicate' key"
+    output=$(notmuch reply --format=json --duplicate=${dup} id:${ID3})
+    test_json_nodes <<<"$output" "dup:['original']['duplicate']=${dup}"
+done
+
 test_done
-- 
2.35.2

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH 9/9] emacs/reply: reply to correct duplicate
  2022-07-01 21:45 Display duplicate messages in emacs front-end David Bremner
                   ` (7 preceding siblings ...)
  2022-07-01 21:45 ` [PATCH 8/9] CLI/reply: support --duplicate argument David Bremner
@ 2022-07-01 21:45 ` David Bremner
  2022-07-30 11:50   ` David Bremner
  2022-07-02  1:47 ` Display duplicate messages in emacs front-end David Bremner
  2022-11-09 14:53 ` Daniel Kahn Gillmor
  10 siblings, 1 reply; 17+ messages in thread
From: David Bremner @ 2022-07-01 21:45 UTC (permalink / raw)
  To: notmuch

Essentially we just need to arrange to pass the right --duplicate
argument to notmuch reply.

As a side-effect, correct the previously unused value of EXPECTED in
T453-emacs-reply.sh.
---
 emacs/notmuch-mua.el                          | 18 +++++----
 emacs/notmuch-show.el                         |  6 ++-
 test/T453-emacs-reply.sh                      | 39 ++++++++++++++++++-
 .../notmuch-reply-duplicate-4                 | 21 ++++++++++
 4 files changed, 73 insertions(+), 11 deletions(-)
 create mode 100644 test/emacs-reply.expected-output/notmuch-reply-duplicate-4

diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index 0f9ef3c2..ac878a61 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -237,11 +237,12 @@ Typically this is added to `notmuch-mua-send-hook'."
 
 ;;; Mua reply
 
-(defun notmuch-mua-reply (query-string &optional sender reply-all)
-  (let ((args '("reply" "--format=sexp" "--format-version=5"))
-	(process-crypto notmuch-show-process-crypto)
-	reply
-	original)
+(defun notmuch-mua-reply (query-string &optional sender reply-all duplicate)
+  (let* ((duparg (and duplicate (list (format "--duplicate=%d" duplicate))))
+	 (args `("reply" "--format=sexp" "--format-version=5" ,@duparg))
+	 (process-crypto notmuch-show-process-crypto)
+	 reply
+	 original)
     (when process-crypto
       (setq args (append args '("--decrypt=true"))))
     (if reply-all
@@ -540,12 +541,13 @@ the From: address."
       (message-hide-headers)
       (set-buffer-modified-p nil))))
 
-(defun notmuch-mua-new-reply (query-string &optional prompt-for-sender reply-all)
+(defun notmuch-mua-new-reply (query-string &optional prompt-for-sender reply-all duplicate)
   "Compose a reply to the message identified by QUERY-STRING.
 
 If PROMPT-FOR-SENDER is non-nil, the user will be prompted for
 the From: address first.  If REPLY-ALL is non-nil, the message
-will be addressed to all recipients of the source message."
+will be addressed to all recipients of the source message.  If
+DUPLICATE is non-nil, based the reply on that duplicate file"
   ;; `select-active-regions' is t by default. The reply insertion code
   ;; sets the region to the quoted message to make it easy to delete
   ;; (kill-region or C-w). These two things combine to put the quoted
@@ -560,7 +562,7 @@ will be addressed to all recipients of the source message."
   (let ((sender (and prompt-for-sender
 		     (notmuch-mua-prompt-for-sender)))
 	(select-active-regions nil))
-    (notmuch-mua-reply query-string sender reply-all)
+    (notmuch-mua-reply query-string sender reply-all duplicate)
     (deactivate-mark)))
 
 ;;; Checks
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index ee01e470..cc34876b 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -2020,13 +2020,15 @@ any effects from previous calls to
 (defun notmuch-show-reply (&optional prompt-for-sender)
   "Reply to the sender and all recipients of the current message."
   (interactive "P")
-  (notmuch-mua-new-reply (notmuch-show-get-message-id) prompt-for-sender t))
+  (notmuch-mua-new-reply (notmuch-show-get-message-id) prompt-for-sender t
+			 (notmuch-show-get-prop :duplicate)))
 
 (put 'notmuch-show-reply-sender 'notmuch-prefix-doc "... and prompt for sender")
 (defun notmuch-show-reply-sender (&optional prompt-for-sender)
   "Reply to the sender of the current message."
   (interactive "P")
-  (notmuch-mua-new-reply (notmuch-show-get-message-id) prompt-for-sender nil))
+  (notmuch-mua-new-reply (notmuch-show-get-message-id) prompt-for-sender nil
+			 (notmuch-show-get-prop :duplicate)))
 
 (put 'notmuch-show-forward-message 'notmuch-prefix-doc
      "... and prompt for sender")
diff --git a/test/T453-emacs-reply.sh b/test/T453-emacs-reply.sh
index c26c4473..0a27d066 100755
--- a/test/T453-emacs-reply.sh
+++ b/test/T453-emacs-reply.sh
@@ -4,7 +4,7 @@ test_description="emacs reply"
 . $(dirname "$0")/test-lib.sh || exit 1
 . $NOTMUCH_SRCDIR/test/test-lib-emacs.sh || exit 1
 
-EXPECTED=$NOTMUCH_SRCDIR/test/emacs-show.expected-output
+EXPECTED=$NOTMUCH_SRCDIR/test/emacs-reply.expected-output
 
 test_require_emacs
 
@@ -31,4 +31,41 @@ EOF
 notmuch_dir_sanitize < OUTPUT.raw > OUTPUT
 test_expect_equal_file EXPECTED OUTPUT
 
+add_email_corpus duplicate
+
+ID2=87r2geywh9.fsf@tethera.net
+for dup in {1..2}; do
+    test_begin_subtest "body, duplicate=${dup}"
+    test_emacs "(notmuch-show \"id:${ID2}\")
+	   (notmuch-test-wait)
+	   (notmuch-show-choose-duplicate $dup)
+	   (notmuch-test-wait)
+	   (notmuch-show-reply)
+	   (test-visible-output \"OUTPUT.raw\")"
+    output=$(grep '^> # body' OUTPUT.raw)
+    test_expect_equal "$output" "> # body ${dup}"
+done
+
+ID3=87r2ecrr6x.fsf@zephyr.silentflame.com
+test_begin_subtest "duplicate=3, subject"
+test_emacs "(notmuch-show \"id:${ID3}\")
+	   (notmuch-test-wait)
+	   (notmuch-show-choose-duplicate 3)
+	   (notmuch-test-wait)
+	   (notmuch-show-reply)
+	   (test-visible-output \"OUTPUT\")"
+output=$(sed -n 's/^Subject: //p' OUTPUT)
+file=$(notmuch search --output=files id:${ID3} | head -n 3 | tail -n 1)
+subject=$(sed -n 's/^Subject: //p' $file)
+test_expect_equal "$output" "Re: $subject"
+
+test_begin_subtest "duplicate=4"
+test_emacs "(notmuch-show \"id:${ID3}\")
+	   (notmuch-show-choose-duplicate 4)
+	   (notmuch-test-wait)
+	   (notmuch-show-reply)
+	   (test-visible-output \"OUTPUT.raw\")"
+notmuch_dir_sanitize < OUTPUT.raw > OUTPUT
+test_expect_equal_file_nonempty $EXPECTED/notmuch-reply-duplicate-4 OUTPUT
+
 test_done
diff --git a/test/emacs-reply.expected-output/notmuch-reply-duplicate-4 b/test/emacs-reply.expected-output/notmuch-reply-duplicate-4
new file mode 100644
index 00000000..836f77b1
--- /dev/null
+++ b/test/emacs-reply.expected-output/notmuch-reply-duplicate-4
@@ -0,0 +1,21 @@
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: Sean Whitton <spwhitton@spwhitton.name>, 916811@bugs.debian.org, 916805@bugs.debian.org, 916807@bugs.debian.org, 916808@bugs.debian.org, 916809@bugs.debian.org, 916811@bugs.debian.org, 916867@bugs.debian.org, 916869@bugs.debian.org, 916872@bugs.debian.org, 916875@bugs.debian.org, 916876@bugs.debian.org
+Subject: Re: [Pkg-emacsen-addons] Bug#916811: Increase severity to 'serious'
+In-Reply-To: <87r2ecrr6x.fsf@zephyr.silentflame.com>
+Fcc: MAIL_DIR/sent
+--text follows this line--
+Sean Whitton <spwhitton@spwhitton.name> writes:
+
+> control: severity -1 serious
+>
+> Hello,
+>
+> Emacs 26.1 has reached Debian unstable (sooner than expected; sorry for
+> all the e-mails).
+>
+> -- 
+> Sean Whitton
+> _______________________________________________
+> Pkg-emacsen-addons mailing list
+> Pkg-emacsen-addons@alioth-lists.debian.net
+> https://alioth-lists.debian.net/cgi-bin/mailman/listinfo/pkg-emacsen-addons
-- 
2.35.2

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: Display duplicate messages in emacs front-end
  2022-07-01 21:45 Display duplicate messages in emacs front-end David Bremner
                   ` (8 preceding siblings ...)
  2022-07-01 21:45 ` [PATCH 9/9] emacs/reply: reply to correct duplicate David Bremner
@ 2022-07-02  1:47 ` David Bremner
  2022-11-09 14:53 ` Daniel Kahn Gillmor
  10 siblings, 0 replies; 17+ messages in thread
From: David Bremner @ 2022-07-02  1:47 UTC (permalink / raw)
  To: notmuch

David Bremner <david@tethera.net> writes:

> This obsoletes the WIP series [1]. Compared to that series, this one
> includes somewhat improved documentation, better error handling, and
> implements the --duplicate argument for notmuch-reply, and uses it in
> the emacs front end.
>
> [1]: id:20220619232152.846823-1-david@tethera.net

I should mention that this branch applies on top of branch "next". There
are several emacs related changes in progress at the moment, and it's a
bit tricky to avoid conflicts, so I've pushed version of the lazy-show
changes (plus some other housekeeping) to the "next" branch (in the
usual repo).

d

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 3/9] test: add new corpus of duplicate messages
  2022-07-01 21:45 ` [PATCH 3/9] test: add new corpus of duplicate messages David Bremner
@ 2022-07-05 10:07   ` David Bremner
  0 siblings, 0 replies; 17+ messages in thread
From: David Bremner @ 2022-07-05 10:07 UTC (permalink / raw)
  To: notmuch

David Bremner <david@tethera.net> writes:

> This corpus will be used to test a new --duplicate option for notmuch-show

first 3 patches of this series applied to master.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 9/9] emacs/reply: reply to correct duplicate
  2022-07-01 21:45 ` [PATCH 9/9] emacs/reply: reply to correct duplicate David Bremner
@ 2022-07-30 11:50   ` David Bremner
  0 siblings, 0 replies; 17+ messages in thread
From: David Bremner @ 2022-07-30 11:50 UTC (permalink / raw)
  To: notmuch

David Bremner <david@tethera.net> writes:

> Essentially we just need to arrange to pass the right --duplicate
> argument to notmuch reply.
>
> As a side-effect, correct the previously unused value of EXPECTED in
> T453-emacs-reply.sh.

remainder of series applied to master.

d

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Display duplicate messages in emacs front-end
  2022-07-01 21:45 Display duplicate messages in emacs front-end David Bremner
                   ` (9 preceding siblings ...)
  2022-07-02  1:47 ` Display duplicate messages in emacs front-end David Bremner
@ 2022-11-09 14:53 ` Daniel Kahn Gillmor
  2022-11-09 16:55   ` Daniel Kahn Gillmor
  10 siblings, 1 reply; 17+ messages in thread
From: Daniel Kahn Gillmor @ 2022-11-09 14:53 UTC (permalink / raw)
  To: notmuch


[-- Attachment #1.1: Type: text/plain, Size: 799 bytes --]

On Fri 2022-07-01 18:45:39 -0300, David Bremner wrote:
> This obsoletes the WIP series [1]. Compared to that series, this one
> includes somewhat improved documentation, better error handling, and
> implements the --duplicate argument for notmuch-reply, and uses it in
> the emacs front end.
>
> [1]: id:20220619232152.846823-1-david@tethera.net

I wanted to send a (belated) thanks for this series!

The functionality here, switching between duplicates in the emacs
frontend, is great.  I needed to use it today, because i had two copies
of an e-mail message, one with a valid signature and one with a damaged
signature.  It Just Worked™ to let me switch between the different
variants.

Many thanks for having taken the time and effort to get this thing
right.

       --dkg

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 227 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Display duplicate messages in emacs front-end
  2022-11-09 14:53 ` Daniel Kahn Gillmor
@ 2022-11-09 16:55   ` Daniel Kahn Gillmor
  2022-11-09 20:58     ` Jameson Graef Rollins
  0 siblings, 1 reply; 17+ messages in thread
From: Daniel Kahn Gillmor @ 2022-11-09 16:55 UTC (permalink / raw)
  To: notmuch


[-- Attachment #1.1: Type: text/plain, Size: 1664 bytes --]

On Wed 2022-11-09 09:53:26 -0500, Daniel Kahn Gillmor wrote:
> The functionality here, switching between duplicates in the emacs
> frontend, is great.  I needed to use it today, because i had two copies
> of an e-mail message, one with a valid signature and one with a damaged
> signature.  It Just Worked™ to let me switch between the different
> variants.

Now that i'm playing with this feature specifically, it occurs to me
that the primary use case is likely to be where there are two or maybe 3
duplicates of a given message.

In this use case, the emacs bindings could be a bit more ergonomic.

The current binding is '%', which then prompts the user for "duplicate:"
and the user is obliged to type in the number of the duplicate that they
want.

When i'm looking at duplicate 1/2, the obvious answer is i want 2/2.
when i'm looking at 2/2, i want 1/2.  The current interface, while nice
and fully flexible makes me do extra work :)

Here's a proposed update:

 - '%' on its own moves to duplicate n+1 (wrapping around from the max
   back to 1)

 - prefixed '%' (that is, 'C-u %') yields the current behavior where the
   user can enter which specific duplicate they want.

My elisp remains rudimentary at best, so i don't know that i know how to
make this fix (in particular, i'm not sure how i retrieve the current
values N/M, in order to calculate mod_M(N)+1), but i'd be happy to test
any patch that does this.

I don't know how people feel about changing the default keybindings on a
relatively recent feature -- would it be upsetting to users if the
behavior of % changed in this subtle way?

         --dkg

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 227 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Display duplicate messages in emacs front-end
  2022-11-09 16:55   ` Daniel Kahn Gillmor
@ 2022-11-09 20:58     ` Jameson Graef Rollins
  2022-11-10  4:57       ` Daniel Kahn Gillmor
  0 siblings, 1 reply; 17+ messages in thread
From: Jameson Graef Rollins @ 2022-11-09 20:58 UTC (permalink / raw)
  To: Daniel Kahn Gillmor, notmuch

On Wed, Nov 09 2022, Daniel Kahn Gillmor <dkg@fifthhorseman.net> wrote:
> On Wed 2022-11-09 09:53:26 -0500, Daniel Kahn Gillmor wrote:
>> The functionality here, switching between duplicates in the emacs
>> frontend, is great.  I needed to use it today, because i had two copies
>> of an e-mail message, one with a valid signature and one with a damaged
>> signature.  It Just Worked™ to let me switch between the different
>> variants.
>
> Now that i'm playing with this feature specifically, it occurs to me
> that the primary use case is likely to be where there are two or maybe 3
> duplicates of a given message.
>
> In this use case, the emacs bindings could be a bit more ergonomic.
>
> The current binding is '%', which then prompts the user for "duplicate:"
> and the user is obliged to type in the number of the duplicate that they
> want.
>
> When i'm looking at duplicate 1/2, the obvious answer is i want 2/2.
> when i'm looking at 2/2, i want 1/2.  The current interface, while nice
> and fully flexible makes me do extra work :)
>
> Here's a proposed update:
>
>  - '%' on its own moves to duplicate n+1 (wrapping around from the max
>    back to 1)
>
>  - prefixed '%' (that is, 'C-u %') yields the current behavior where the
>    user can enter which specific duplicate they want.
>
> My elisp remains rudimentary at best, so i don't know that i know how to
> make this fix (in particular, i'm not sure how i retrieve the current
> values N/M, in order to calculate mod_M(N)+1), but i'd be happy to test
> any patch that does this.
>
> I don't know how people feel about changing the default keybindings on a
> relatively recent feature -- would it be upsetting to users if the
> behavior of % changed in this subtle way?

Personally I think it would make sense to have % cycle through
duplicates, with some indicator of which duplicate we're currently on.
I wouldn't even bother with the suggested prefixed behavior if we just
had the cycle behavior.

Also thanks to folks for working on this.

jamie.\r

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Display duplicate messages in emacs front-end
  2022-11-09 20:58     ` Jameson Graef Rollins
@ 2022-11-10  4:57       ` Daniel Kahn Gillmor
  0 siblings, 0 replies; 17+ messages in thread
From: Daniel Kahn Gillmor @ 2022-11-10  4:57 UTC (permalink / raw)
  To: Jameson Graef Rollins, notmuch


[-- Attachment #1.1: Type: text/plain, Size: 1137 bytes --]

On Wed 2022-11-09 12:58:18 -0800, Jameson Graef Rollins wrote:
> Personally I think it would make sense to have % cycle through
> duplicates, with some indicator of which duplicate we're currently on.
> I wouldn't even bother with the suggested prefixed behavior if we just
> had the cycle behavior.

In my notmuch-show buffer, there already is an indicator in the
right-hand side of any message that has duplicates, so that part doesn't
require any extra work.

In the event that i get a malicious load of dozens of duplicates and i
identify that one of them is of particular interest, i might want the
current behavior available so that i can get back to "duplicate 17"
without hitting '%' 16 times in a row.  But i haven't had that situation
happen yet -- the other situation with a pair of dups is much more
common.

it even happened with this message i'm replying to here, b/c one copy of
the message came straight from Jamie's MUA and the other was routed
through the mailing list.  It'd be kind of nice in a nerdy way to make
the mailman footer disappear and reappear just by hitting '%' ☺

        --dkg

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 227 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2022-11-10  5:05 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-01 21:45 Display duplicate messages in emacs front-end David Bremner
2022-07-01 21:45 ` [PATCH 1/9] test: use notmuch_json_show_sanitize more places David Bremner
2022-07-01 21:45 ` [PATCH 2/9] test: define and use notmuch_sexp_*_sanitize functions David Bremner
2022-07-01 21:45 ` [PATCH 3/9] test: add new corpus of duplicate messages David Bremner
2022-07-05 10:07   ` David Bremner
2022-07-01 21:45 ` [PATCH 4/9] CLI/show: initial support for --duplicate for (raw output only) David Bremner
2022-07-01 21:45 ` [PATCH 5/9] CLI/show: support --duplicate for structured output David Bremner
2022-07-01 21:45 ` [PATCH 6/9] emacs/show: provide notmuch-show-choose-duplicate David Bremner
2022-07-01 21:45 ` [PATCH 7/9] emacs/show: display count of duplicates in headerline David Bremner
2022-07-01 21:45 ` [PATCH 8/9] CLI/reply: support --duplicate argument David Bremner
2022-07-01 21:45 ` [PATCH 9/9] emacs/reply: reply to correct duplicate David Bremner
2022-07-30 11:50   ` David Bremner
2022-07-02  1:47 ` Display duplicate messages in emacs front-end David Bremner
2022-11-09 14:53 ` Daniel Kahn Gillmor
2022-11-09 16:55   ` Daniel Kahn Gillmor
2022-11-09 20:58     ` Jameson Graef Rollins
2022-11-10  4:57       ` Daniel Kahn Gillmor

Code repositories for project(s) associated with this public inbox

	https://yhetil.org/notmuch.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).