encoding: add a way to change HGENCODING at runtime

Summary:
Make it possible to change the internal state of HGENCODING so we can run hg
logic within a single process without shelling out in the new dott test
framework.

Update testutil/dott to use it.

Reviewed By: xavierd

Differential Revision: D16452925

fbshipit-source-id: d21329854eeee171cc5d02d4f42f11dd273f2150
This commit is contained in:
Jun Wu 2019-07-24 14:15:16 -07:00 committed by Facebook Github Bot
parent 5dbb19b028
commit 6cd7d1799c
2 changed files with 41 additions and 34 deletions

View File

@ -59,18 +59,43 @@ def hfsignoreclean(s):
return s
# encoding.environ is provided read-only, which may not be used to modify
# the process environment
_nativeenviron = not pycompat.ispy3 or os.supports_bytes_environ
if not pycompat.ispy3:
environ = os.environ # re-exports
elif _nativeenviron:
environ = os.environb # re-exports
else:
# preferred encoding isn't known yet; use utf-8 to avoid unicode error
# and recreate it once encoding is settled
items = os.environ.items() # re-exports
environ = dict((k.encode(u"utf-8"), v.encode(u"utf-8")) for k, v in items)
def setfromenviron():
"""Reset encoding states from environment variables"""
global encoding, encodingmode, environ, _wide
# encoding.environ is provided read-only, which may not be used to modify
# the process environment
_nativeenviron = not pycompat.ispy3 or os.supports_bytes_environ
if not pycompat.ispy3:
environ = os.environ # re-exports
elif _nativeenviron:
environ = os.environb # re-exports
else:
# preferred encoding isn't known yet; use utf-8 to avoid unicode error
# and recreate it once encoding is settled
items = os.environ.items() # re-exports
environ = dict((k.encode(u"utf-8"), v.encode(u"utf-8")) for k, v in items)
try:
encoding = environ.get("HGENCODING") or "ascii"
if not encoding:
encoding = locale.getpreferredencoding().encode("ascii") or "ascii"
encoding = _encodingfixers.get(encoding, lambda: encoding)()
except locale.Error:
encoding = "ascii"
encodingmode = environ.get("HGENCODINGMODE", "strict")
if not _nativeenviron:
# now encoding and helper functions are available, recreate the environ
# dict to be exported to other modules
items = os.environ.items() # re-exports
environ = dict(
(tolocal(k.encode(u"utf-8")), tolocal(v.encode(u"utf-8"))) for k, v in items
)
# How to treat ambiguous-width characters. Set to 'wide' to treat as wide.
_wide = _sysstr(
environ.get("HGENCODINGAMBIGUOUS", "narrow") == "wide" and "WFA" or "WF"
)
_encodingfixers = {"646": lambda: "ascii", "ANSI_X3.4-1968": lambda: "ascii"}
@ -80,14 +105,8 @@ _encodingfixers = {"646": lambda: "ascii", "ANSI_X3.4-1968": lambda: "ascii"}
if pycompat.iswindows and not pycompat.ispy3:
_encodingfixers["cp65001"] = lambda: "utf-8"
try:
encoding = environ.get("HGENCODING")
if not encoding:
encoding = locale.getpreferredencoding().encode("ascii") or "ascii"
encoding = _encodingfixers.get(encoding, lambda: encoding)()
except locale.Error:
encoding = "ascii"
encodingmode = environ.get("HGENCODINGMODE", "strict")
environ = encoding = encodingmode = _wide = None
setfromenviron()
fallbackencoding = "ISO-8859-1"
@ -229,19 +248,6 @@ else:
strfromlocal = pycompat.identity
strmethod = pycompat.identity
if not _nativeenviron:
# now encoding and helper functions are available, recreate the environ
# dict to be exported to other modules
items = os.environ.items() # re-exports
environ = dict(
(tolocal(k.encode(u"utf-8")), tolocal(v.encode(u"utf-8"))) for k, v in items
)
# How to treat ambiguous-width characters. Set to 'wide' to treat as wide.
_wide = _sysstr(
environ.get("HGENCODINGAMBIGUOUS", "narrow") == "wide" and "WFA" or "WF"
)
def colwidth(s):
"Find the column width of a string for display in the local encoding"

View File

@ -64,7 +64,7 @@ else:
try:
from edenscm.mercurial import dispatch, ui as uimod, util
from edenscm.mercurial import dispatch, encoding, ui as uimod, util
except ImportError:
raise RuntimeError("Cannot find edenscm")
@ -231,6 +231,7 @@ globals()["."] = source
def hg(*args, **kwargs):
stdin = kwargs.get("stdin")
ui = uimod.ui()
encoding.setfromenviron()
if "HGRCPATH" in os.environ:
ui.readconfig(os.environ["HGRCPATH"])
fout = util.stringio()