# HG changeset patch # User Augie Fackler # Date 1593184858 14400 # Node ID 05277278f1774d2147eadff91d93bd5c77f9c1a2 # Parent d2227d4c9e6b97b84b5c0c24b00f6ac3330be3fa# Parent 2632c1ed8f34988fc918d70ccc40b01c20c08a53 merge with stable diff -r d2227d4c9e6b -r 05277278f177 mercurial/hgweb/request.py --- a/mercurial/hgweb/request.py Fri Jun 26 09:37:34 2020 +0200 +++ b/mercurial/hgweb/request.py Fri Jun 26 11:20:58 2020 -0400 @@ -12,6 +12,7 @@ from ..thirdparty import attr from .. import ( + encoding, error, pycompat, util, @@ -162,11 +163,19 @@ # strings on Python 3 must be between \00000-\000FF. We deal with bytes # in Mercurial, so mass convert string keys and values to bytes. if pycompat.ispy3: - env = {k.encode('latin-1'): v for k, v in pycompat.iteritems(env)} - env = { - k: v.encode('latin-1') if isinstance(v, str) else v - for k, v in pycompat.iteritems(env) - } + + def tobytes(s): + if not isinstance(s, str): + return s + if pycompat.iswindows: + # This is what mercurial.encoding does for os.environ on + # Windows. + return encoding.strtolocal(s) + else: + # This is what is documented to be used for os.environ on Unix. + return pycompat.fsencode(s) + + env = {tobytes(k): tobytes(v) for k, v in pycompat.iteritems(env)} # Some hosting solutions are emulating hgwebdir, and dispatching directly # to an hgweb instance using this environment variable. This was always diff -r d2227d4c9e6b -r 05277278f177 tests/test-wsgirequest.py --- a/tests/test-wsgirequest.py Fri Jun 26 09:37:34 2020 +0200 +++ b/tests/test-wsgirequest.py Fri Jun 26 11:20:58 2020 -0400 @@ -3,7 +3,7 @@ import unittest from mercurial.hgweb import request as requestmod -from mercurial import error +from mercurial import error, pycompat DEFAULT_ENV = { 'REQUEST_METHOD': 'GET', @@ -432,6 +432,18 @@ self.assertEqual(r.dispatchpath, b'path1/path2') self.assertEqual(r.reponame, b'repo') + def testenvencoding(self): + if pycompat.iswindows: + # On Windows, we can't generally know which non-ASCII characters + # are supported. + r = parse(DEFAULT_ENV, extra={'foo': 'bar'}) + self.assertEqual(r.rawenv[b'foo'], b'bar') + else: + # Unix is byte-based. Therefore we test all possible bytes. + b = b''.join(pycompat.bytechr(i) for i in range(256)) + r = parse(DEFAULT_ENV, extra={'foo': pycompat.fsdecode(b)}) + self.assertEqual(r.rawenv[b'foo'], b) + if __name__ == '__main__': import silenttestrunner