--- 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
--- 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