Raman Gupta wrote:
> Romulo A. Ceccon wrote:
>> On Dec 7, 2007 11:19 PM, Raman Gupta <[EMAIL PROTECTED]> wrote:
>>> It would be really helpful if you could create a test in
>>> svnmerge_test.py. That would make it easier for people to test this
>>> cross-platform.
>> Ok. The patch is attached.
>>
>> Note that I had to change TestCase_SvnMerge.svnmerge to use a
>> different StringIO object, since it replaces sys.stdout with a version
>> which doesn't provide the "encoding" property. That property is
>> required by svnmerge.py in my proposed patch.
> 
> Awesome, thanks for the test case!
> 
> Note that the patch causes 13 tests to fail on my machine. I believe
> the reason is that svnmerge.py currently sets os.environ["LC_ALL"] =
> "C" and that, at least on my machine, causes
> locale.getdefaultlocale()[1] to return None, which then causes the
> call to encode to fail:
> 
> Python 2.5.1 (r251:54863, Oct 30 2007, 13:45:26)
> [GCC 4.1.2 20070925 (Red Hat 4.1.2-33)] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
> >>> import os, locale
> >>> locale.getdefaultlocale()[1]
> 'UTF8'
> >>> locale.setlocale(locale.LC_ALL, '')
> 'en_US.UTF-8'
> >>> locale.getdefaultlocale()[1]
> 'UTF8'
> >>> locale.setlocale(locale.LC_ALL, 'C')
> 'C'
> >>> locale.getdefaultlocale()[1]
> 'UTF8'
> >>> os.environ["LC_ALL"] = "C"
> >>> locale.getdefaultlocale()[1]
> >>>
> 
> So it seems to be specifically the os.environ setting (added in rev
> 23305) that is causing problems on my machine, whereas the
> "equivalent" python call to setlocale 'C' is ok. I think os.environ is
> needed for svn though, so... anybody out there that understands what
> is going on?

I spoke to Daniel Shahaf on #svn, and I got a slightly better
understanding of svn behavior related to LC_ALL and commit log messages.

The attached patch is a slightly modified version of Romulo's that,
allows svnmerge.py and svn to use the locale set by the user's
environment, instead of trying to use the 'C' locale.

Could everyone (especially people in non-english locations) test it
and verify it works in their environment?

Cheers,
Raman Gupta
Index: svnmerge_test.py
===================================================================
--- svnmerge_test.py	(revision 29395)
+++ svnmerge_test.py	(working copy)
@@ -20,12 +20,13 @@
 import types
 import re
 import unittest
-from cStringIO import StringIO
+from StringIO import StringIO
 import shutil
 import svnmerge
 import stat
 import atexit
 import getopt
+import locale
 
 ####
 # IMPORTANT NOTE TO TEST AUTHORS
@@ -48,6 +49,11 @@
 except NameError:
     True, False = 1, 0
 
+class StringIOWithEncoding(StringIO):
+    def __init__(self):
+        StringIO.__init__(self)
+        self.encoding = sys.stdout.encoding
+    
 class TestCase_kwextract(unittest.TestCase):
     def test_basic(self):
         self.assertEqual(svnmerge.kwextract("$Rev: 134 rasky $"), "134 rasky")
@@ -195,7 +201,9 @@
         return self.svnmerge2(cmds.split(), *args, **kwargs)
 
     def svnmerge2(self, args, error=False, match=None, nonmatch=None):
-        out = StringIO()
+        # svnmerge's get_commit_log method needs the "encoding" method of
+        # sys.stdout, which is not provided by StringIO
+        out = StringIOWithEncoding()
         sys.stdout = sys.stderr = out
         try:
             try:
@@ -1242,6 +1250,50 @@
         except AssertionError:
             self.assert_(os.path.isfile("dir_conflicts.prej"))
 
+    def testCommitMessageEncoding(self):
+        """Init svnmerge, modify source head and commit with a message
+        containing non-ASCII caracters, merge, commit, and verify the commit
+        message was correctly encoded."""
+
+        # Initialize svnmerge
+        self.svnmerge2(["init", self.test_repo_url + "/trunk"])
+        self.launch("svn commit -F svnmerge-commit-message.txt",
+                    match = r"Committed revision 14")
+        os.remove("svnmerge-commit-message.txt")
+
+        commit_msg = u"adição no repositório"
+        input_encoding = locale.getdefaultlocale()[1]
+        output_encoding = sys.stdout.encoding
+
+        # Create a file
+        os.chdir("../trunk")
+        open("newfile", "w").close()
+
+        # Create a message containing non-ASCII caracters. The message will be
+        # kept inside a file, so we don't need to worry about Python or the OS
+        # converting the command line before it's sent to svn
+        msg_file = open('msg.txt', 'w')
+        msg_file.write(commit_msg.encode(input_encoding))
+        msg_file.close()
+
+        # Add the file and commit with the message above
+        self.launch("svn add newfile")
+        self.launch('svn commit -F msg.txt', match="Committed revision 15")
+        os.remove('msg.txt')
+        # Check the message was properly encoded by svn (this will currently
+        # only work if the user config file does not override log-encoding
+        self.launch('svn log -r 15', match=commit_msg.encode(output_encoding))
+
+        # Merge changes into the branch commiting with the message provided by
+        # svnmerge
+        os.chdir("../test-branch")
+        self.svnmerge("merge")
+        self.launch("svn commit -F svnmerge-commit-message.txt",
+                    match="Committed revision 16")
+        # The procedure above should have not misenconded the message 
+        self.launch('svn log -r 16', match=commit_msg.encode(output_encoding))
+
+
 if __name__ == "__main__":
     # If an existing template repository and working copy for testing
     # exists, then always remove it.  This prevents any problems if
Index: svnmerge.py
===================================================================
--- svnmerge.py	(revision 29395)
+++ svnmerge.py	(working copy)
@@ -68,7 +68,7 @@
 #  A "target" is generally user-specified, and may be a working copy or
 #  a URL.
 
-import sys, os, getopt, re, types, tempfile, time, popen2
+import sys, os, getopt, re, types, tempfile, time, popen2, locale
 from bisect import bisect
 from xml.dom import pulldom
 
@@ -89,8 +89,11 @@
 # Each line of the embedded log messages will be prefixed by LOG_LINE_PREFIX.
 LOG_LINE_PREFIX = 2 * ' '
 
-# We expect non-localized output from SVN
-os.environ["LC_ALL"] = "C"
+# Set python to the default locale as per environment settings, same as svn
+# TODO we should really parse config and if log-encoding is specified, set
+# the locale to match that encoding (assuming that log-encoding overrides
+# LANG/LC_ALL and not the other way around -- need to verify)
+locale.setlocale(locale.LC_ALL, '')
 
 ###############################################################################
 # Support for older Python versions
@@ -208,6 +211,10 @@
     assert lines[-1] == "\n"
     return prefix + lines[:-1].replace("\n", "\n"+prefix) + "\n"
 
+def recode_stdout_to_file(s):
+    u = s.decode(sys.stdout.encoding)
+    return u.encode(locale.getdefaultlocale()[1])
+
 class LaunchError(Exception):
     """Signal a failure in execution of an external command. Parameters are the
     exit code of the process, the original command line, and the output of the
@@ -933,7 +940,7 @@
     """Return the log message for a specific integer revision
     number."""
     out = launchsvn("log --incremental -r%d %s" % (revnum, url))
-    return "".join(out[1:])
+    return recode_stdout_to_file("".join(out[1:]))
 
 def construct_merged_log_message(url, revnums):
     """Return a commit log message containing all the commit messages
_______________________________________________
Svnmerge mailing list
[email protected]
http://www.orcaware.com/mailman/listinfo/svnmerge

Reply via email to