##// END OF EJS Templates
chg: fix chg to work with py3.7+ "coercing" the locale...
Kyle Lippincott -
r44312:5e0f6451 default
parent child Browse files
Show More
@@ -549,6 +549,41 class chgcmdserver(commandserver.server)
549 except ValueError:
549 except ValueError:
550 raise ValueError(b'unexpected value in setenv request')
550 raise ValueError(b'unexpected value in setenv request')
551 self.ui.log(b'chgserver', b'setenv: %r\n', sorted(newenv.keys()))
551 self.ui.log(b'chgserver', b'setenv: %r\n', sorted(newenv.keys()))
552
553 # Python3 has some logic to "coerce" the C locale to a UTF-8 capable
554 # one, and it sets LC_CTYPE in the environment to C.UTF-8 if none of
555 # 'LC_CTYPE', 'LC_ALL' or 'LANG' are set (to any value). This can be
556 # disabled with PYTHONCOERCECLOCALE=0 in the environment.
557 #
558 # When fromui is called via _inithashstate, python has already set
559 # this, so that's in the environment right when we start up the hg
560 # process. Then chg will call us and tell us to set the environment to
561 # the one it has; this might NOT have LC_CTYPE, so we'll need to
562 # carry-forward the LC_CTYPE that was coerced in these situations.
563 #
564 # If this is not handled, we will fail config+env validation and fail
565 # to start chg. If this is just ignored instead of carried forward, we
566 # may have different behavior between chg and non-chg.
567 if pycompat.ispy3:
568 # Rename for wordwrapping purposes
569 oldenv = encoding.environ
570 if not any(
571 e.get(b'PYTHONCOERCECLOCALE') == b'0' for e in [oldenv, newenv]
572 ):
573 keys = [b'LC_CTYPE', b'LC_ALL', b'LANG']
574 old_keys = [k for k, v in oldenv.items() if k in keys and v]
575 new_keys = [k for k, v in newenv.items() if k in keys and v]
576 # If the user's environment (from chg) doesn't have ANY of the
577 # keys that python looks for, and the environment (from
578 # initialization) has ONLY LC_CTYPE and it's set to C.UTF-8,
579 # carry it forward.
580 if (
581 not new_keys
582 and old_keys == [b'LC_CTYPE']
583 and oldenv[b'LC_CTYPE'] == b'C.UTF-8'
584 ):
585 newenv[b'LC_CTYPE'] = oldenv[b'LC_CTYPE']
586
552 encoding.environ.clear()
587 encoding.environ.clear()
553 encoding.environ.update(newenv)
588 encoding.environ.update(newenv)
554
589
@@ -331,3 +331,25 check server log:
331 YYYY/MM/DD HH:MM:SS (PID)> loaded repo into cache: $TESTTMP/cached2 (in ...s)
331 YYYY/MM/DD HH:MM:SS (PID)> loaded repo into cache: $TESTTMP/cached2 (in ...s)
332 YYYY/MM/DD HH:MM:SS (PID)> log -R cached
332 YYYY/MM/DD HH:MM:SS (PID)> log -R cached
333 YYYY/MM/DD HH:MM:SS (PID)> loaded repo into cache: $TESTTMP/cached (in ...s)
333 YYYY/MM/DD HH:MM:SS (PID)> loaded repo into cache: $TESTTMP/cached (in ...s)
334
335 Test that chg works even when python "coerces" the locale (py3.7+, which is done
336 by default if none of LC_ALL, LC_CTYPE, or LANG are set in the environment)
337
338 $ cat > $TESTTMP/debugenv.py <<EOF
339 > from mercurial import encoding
340 > from mercurial import registrar
341 > cmdtable = {}
342 > command = registrar.command(cmdtable)
343 > @command(b'debugenv', [], b'', norepo=True)
344 > def debugenv(ui):
345 > for k in [b'LC_ALL', b'LC_CTYPE', b'LANG']:
346 > v = encoding.environ.get(k)
347 > if v is not None:
348 > ui.write(b'%s=%s\n' % (k, encoding.environ[k]))
349 > EOF
350 $ LANG= LC_ALL= LC_CTYPE= chg \
351 > --config extensions.debugenv=$TESTTMP/debugenv.py debugenv
352 LC_ALL=
353 LC_CTYPE=C.UTF-8 (py37 !)
354 LC_CTYPE= (no-py37 !)
355 LANG=
General Comments 0
You need to be logged in to leave comments. Login now