[PATCH] windows: switch the console encoding into an encoding actually used (issue2926)

Andrei Polushin polushin at gmail.com
Thu Jul 28 15:52:45 CDT 2011


# HG changeset patch
# User Andrei Polushin <polushin at gmail.com>
# Date 1311886282 -25200
# Branch stable
# Node ID 61ace80f43d6144bef600d7ebe05f75f80fd0fe3
# Parent  56848e2bb0c5a43b580dd2ca7ce1e781d4e75b2b
windows: switch the console encoding into an encoding actually used (issue2926)

The encoding of the console is switched temporarily, for the time the Mercurial
is running, and restored to the previous value on exit.
This solution is backward compatible, it changes almost nothing, i.e. neither
stdout/pipe encoding, nor internal string handling are affected anyway.

One problem still remains: `hg log | more' doesn't produce readable output on
OEM console, I've found no way to change the console encoding when redirected.

One problem possibly introduced: killing hg process may not restore previous
console encoding. I'm unable to reproduce the problem, however.

diff -r 56848e2bb0c5 -r 61ace80f43d6 mercurial/osutil.c
--- a/mercurial/osutil.c	Fri Jul 22 20:31:15 2011 -0300
+++ b/mercurial/osutil.c	Fri Jul 29 03:51:22 2011 +0700
@@ -402,6 +402,36 @@
 }
 
 #ifdef _WIN32
+static UINT inputcp;
+static UINT outputcp;
+
+static void restoreconsoleencoding(void)
+{
+	SetConsoleCP(inputcp);
+	SetConsoleOutputCP(outputcp);
+}
+
+static PyObject *forceconsoleencoding(PyObject *self, PyObject *args)
+{
+	int cp;
+
+	if (!PyArg_ParseTuple(args, "i", &cp))
+		return NULL;
+
+	if (!inputcp && !outputcp && IsValidCodePage(cp)) {
+		inputcp = GetConsoleCP();
+		outputcp = GetConsoleOutputCP();
+
+		SetConsoleCP(cp);
+		SetConsoleOutputCP(cp);
+
+		atexit(restoreconsoleencoding);
+		return Py_True;
+	}
+
+	return Py_False;
+}
+
 static PyObject *posixfile(PyObject *self, PyObject *args, PyObject *kwds)
 {
 	static char *kwlist[] = {"name", "mode", "buffering", NULL};
@@ -536,6 +566,8 @@
 	{"listdir", (PyCFunction)listdir, METH_VARARGS | METH_KEYWORDS,
 	 "list a directory\n"},
 #ifdef _WIN32
+	{"forceconsoleencoding", forceconsoleencoding, METH_VARARGS,
+	 "Temporarily switch the console encoding, restored on exit.\n"},
 	{"posixfile", (PyCFunction)posixfile, METH_VARARGS | METH_KEYWORDS,
 	 "Open a file with POSIX-like semantics.\n"
 "On error, this function may raise either a WindowsError or an IOError."},
diff -r 56848e2bb0c5 -r 61ace80f43d6 mercurial/windows.py
--- a/mercurial/windows.py	Fri Jul 22 20:31:15 2011 -0300
+++ b/mercurial/windows.py	Fri Jul 29 03:51:22 2011 +0700
@@ -8,6 +8,16 @@
 from i18n import _
 import osutil
 import errno, msvcrt, os, re, sys
+import codecs, encoding
+
+# Temporarily switch the console encoding into an encoding actually used.
+try:
+    cp = codecs.lookup(encoding.encoding).name
+    if cp.startswith('cp'):
+        cp = int(cp[2:])
+        osutil.forceconsoleencoding(cp)
+except LookupError, ValueError:
+    pass
 
 nulldev = 'NUL:'
 umask = 002


More information about the Mercurial-devel mailing list