mercurial/encoding.py
changeset 16274 5d75eb8568d1
parent 16133 84c58da3a1f8
child 16387 c481761033bd
--- a/mercurial/encoding.py	Thu Mar 15 16:57:19 2012 +0100
+++ b/mercurial/encoding.py	Thu Mar 22 16:54:46 2012 -0500
@@ -92,24 +92,32 @@
     'foo: \\xc3\\xa4'
     """
 
-    for e in ('UTF-8', fallbackencoding):
+    try:
         try:
-            u = s.decode(e) # attempt strict decoding
+            # make sure string is actually stored in UTF-8
+            u = s.decode('UTF-8')
+            if encoding == 'UTF-8':
+                # fast path
+                return s
             r = u.encode(encoding, "replace")
             if u == r.decode(encoding):
                 # r is a safe, non-lossy encoding of s
                 return r
-            elif e == 'UTF-8':
-                return localstr(s, r)
-            else:
+            return localstr(s, r)
+        except UnicodeDecodeError:
+            # we should only get here if we're looking at an ancient changeset
+            try:
+                u = s.decode(fallbackencoding)
+                r = u.encode(encoding, "replace")
+                if u == r.decode(encoding):
+                    # r is a safe, non-lossy encoding of s
+                    return r
                 return localstr(u.encode('UTF-8'), r)
-
-        except LookupError, k:
-            raise error.Abort(k, hint="please check your locale settings")
-        except UnicodeDecodeError:
-            pass
-    u = s.decode("utf-8", "replace") # last ditch
-    return u.encode(encoding, "replace") # can't round-trip
+            except UnicodeDecodeError:
+                u = s.decode("utf-8", "replace") # last ditch
+                return u.encode(encoding, "replace") # can't round-trip
+    except LookupError, k:
+        raise error.Abort(k, hint="please check your locale settings")
 
 def fromlocal(s):
     """