diff -r 12e3f93b1cbc -r 5d75eb8568d1 mercurial/encoding.py --- 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): """