mercurial/mail.py
changeset 30089 040f23ed6963
parent 30072 87b8e40eb812
child 30335 f6369544bf85
--- a/mercurial/mail.py	Sat Oct 08 02:26:48 2016 -0700
+++ b/mercurial/mail.py	Wed Oct 05 13:45:22 2016 +0200
@@ -8,6 +8,7 @@
 from __future__ import absolute_import, print_function
 
 import email
+import email.charset
 import email.header
 import os
 import quopri
@@ -204,24 +205,33 @@
             raise error.Abort(_('%r specified as email transport, '
                                'but not in PATH') % method)
 
+def codec2iana(cs):
+    ''''''
+    cs = email.charset.Charset(cs).input_charset.lower()
+
+    # "latin1" normalizes to "iso8859-1", standard calls for "iso-8859-1"
+    if cs.startswith("iso") and not cs.startswith("iso-"):
+        return "iso-" + cs[3:]
+    return cs
+
 def mimetextpatch(s, subtype='plain', display=False):
     '''Return MIME message suitable for a patch.
-    Charset will be detected as utf-8 or (possibly fake) us-ascii.
+    Charset will be detected by first trying to decode as us-ascii, then utf-8,
+    and finally the global encodings. If all those fail, fall back to
+    ISO-8859-1, an encoding with that allows all byte sequences.
     Transfer encodings will be used if necessary.'''
 
-    cs = 'us-ascii'
-    if not display:
+    cs = ['us-ascii', 'utf-8', encoding.encoding, encoding.fallbackencoding]
+    if display:
+        return mimetextqp(s, subtype, 'us-ascii')
+    for charset in cs:
         try:
-            s.decode('us-ascii')
+            s.decode(charset)
+            return mimetextqp(s, subtype, codec2iana(charset))
         except UnicodeDecodeError:
-            try:
-                s.decode('utf-8')
-                cs = 'utf-8'
-            except UnicodeDecodeError:
-                # We'll go with us-ascii as a fallback.
-                pass
+            pass
 
-    return mimetextqp(s, subtype, cs)
+    return mimetextqp(s, subtype, "iso-8859-1")
 
 def mimetextqp(body, subtype, charset):
     '''Return MIME message.