py3: enable legacy stdio mode in exewrapper
This drops the test failure count from 166 to 117. The failures were typically
in the form of `hg serve -d` spawning but crashing immediately, leaving clients
with "bad http status" lines, connection refusals, and so forth. The underlying
message on the server side was either "OSError: [WinError 6] The handle is
invalid" or "OSError: [WinError 1] Incorrect function". Additionally, no output
was rendered if the pager was activated. Thanks to Yuya for diagnosing the
problem.
The failure count drops to 107 when PYTHONLEGACYWINDOWSSTDIO=1 is defined in the
environment. These failures seem to revolve around the dummyssh server process,
and dumbhttp.py. So I'll probably add that to the test runner.
One small regression here (only in py3) is that if hg.exe is already built, a
messagebox appears when building it again saying that python37.dll can't be
loaded. Python3 isn't in PATH by default, and setup.py tries running bare `hg`
first. But MSYS prepends '.' to PATH, so it runs the local hg, but can't find
the library. It falls back to the python used to invoke setup.py, so ultimately
it works. I'm not sure if it's better to strip '.' from PATH or just skip right
to `sys.executable hg` on Windows.
Also, something seems to be wrong with run-tests._usecorrectpython(). I
accidentially left off the 'PYTHON="py -3"' when building (thus making py2
stuff), and yet managed to invoke run-tests.py with "py -3". (And that only had
67 failures.)
# commitextras.py
#
# Copyright 2013 Facebook, Inc.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
'''adds a new flag extras to commit (ADVANCED)'''
from __future__ import absolute_import
import re
from mercurial.i18n import _
from mercurial import (
commands,
error,
extensions,
registrar,
util,
)
cmdtable = {}
command = registrar.command(cmdtable)
testedwith = 'ships-with-hg-core'
usedinternally = {
'amend_source',
'branch',
'close',
'histedit_source',
'topic',
'rebase_source',
'intermediate-source',
'__touch-noise__',
'source',
'transplant_source',
}
def extsetup(ui):
entry = extensions.wrapcommand(commands.table, 'commit', _commit)
options = entry[1]
options.append(('', 'extra', [],
_('set a changeset\'s extra values'), _("KEY=VALUE")))
def _commit(orig, ui, repo, *pats, **opts):
if util.safehasattr(repo, 'unfiltered'):
repo = repo.unfiltered()
class repoextra(repo.__class__):
def commit(self, *innerpats, **inneropts):
extras = opts.get(r'extra')
for raw in extras:
if '=' not in raw:
msg = _("unable to parse '%s', should follow "
"KEY=VALUE format")
raise error.Abort(msg % raw)
k, v = raw.split('=', 1)
if not k:
msg = _("unable to parse '%s', keys can't be empty")
raise error.Abort(msg % raw)
if re.search('[^\w-]', k):
msg = _("keys can only contain ascii letters, digits,"
" '_' and '-'")
raise error.Abort(msg)
if k in usedinternally:
msg = _("key '%s' is used internally, can't be set "
"manually")
raise error.Abort(msg % k)
inneropts[r'extra'][k] = v
return super(repoextra, self).commit(*innerpats, **inneropts)
repo.__class__ = repoextra
return orig(ui, repo, *pats, **opts)