[PATCH] Provide better context for custom Python encode/decode filters

Jesse Glick Jesse.Glick at Sun.COM
Fri Dec 21 22:24:35 CST 2007


# HG changeset patch
# User Jesse Glick <jesse.glick at sun.com>
# Date 1198297277 18000
# Node ID dbf62abe9c0fba6559c226ded72251507e742891
# Parent  1b4ed187319a26c2a6f01836266a8e9ae32705cc
Provide better context for custom Python encode/decode filters.
While some can function with just some text and an optional command name,
others may want a repository object, a ui object, and a file path.
Use the enhanced information to good effect in win32text.dumbdecode's warning.

diff -r 1b4ed187319a -r dbf62abe9c0f hgext/win32text.py
--- a/hgext/win32text.py	Fri Dec 21 19:48:11 2007 -0500
+++ b/hgext/win32text.py	Fri Dec 21 23:21:17 2007 -0500
@@ -30,18 +30,17 @@ import re
 # regexp for single LF without CR preceding.
 re_single_lf = re.compile('(^|[^\r])\n', re.MULTILINE)
 
-def dumbdecode(s, cmd):
+def dumbdecode(s, cmd, ui=None, filename=None, repo=None, **kwargs):
     # warn if already has CRLF in repository.
     # it might cause unexpected eol conversion.
     # see issue 302:
     #   http://www.selenic.com/mercurial/bts/issue302
-    if '\r\n' in s:
-        u = ui.ui()
-        u.warn(_('WARNING: file in repository already has CRLF line ending \n'
-                 ' which does not need eol conversion by win32text plugin.\n'
-                 ' Please reconsider encode/decode setting in'
-                 ' mercurial.ini or .hg/hgrc\n'
-                 ' before next commit.\n'))
+    if '\r\n' in s and ui and filename and repo:
+        ui.warn(_('WARNING: %s already has CRLF line endings\n'
+                  'and does not need EOL conversion by the win32text plugin.\n'
+                  'Before your next commit, please reconsider your '
+                  'encode/decode settings in \nMercurial.ini or %s.\n') %
+                (filename, repo.join('hgrc')))
     # replace single LF to CRLF
     return re_single_lf.sub('\\1\r\n', s)
 
@@ -52,9 +51,9 @@ def clevertest(s, cmd):
     if '\0' in s: return False
     return True
 
-def cleverdecode(s, cmd):
+def cleverdecode(s, cmd, **kwargs):
     if clevertest(s, cmd):
-        return dumbdecode(s, cmd)
+        return dumbdecode(s, cmd, **kwargs)
     return s
 
 def cleverencode(s, cmd):
diff -r 1b4ed187319a -r dbf62abe9c0f mercurial/localrepo.py
--- a/mercurial/localrepo.py	Fri Dec 21 19:48:11 2007 -0500
+++ b/mercurial/localrepo.py	Fri Dec 21 23:21:17 2007 -0500
@@ -491,7 +491,8 @@ class localrepository(repo.repository):
         for mf, cmd in self.filterpats[filter]:
             if mf(filename):
                 self.ui.debug(_("filtering %s through %s\n") % (filename, cmd))
-                data = util.filter(data, cmd)
+                data = util.filter(data, cmd,
+                                   repo=self, ui=self.ui, filename=filename)
                 break
 
         return data
diff -r 1b4ed187319a -r dbf62abe9c0f mercurial/util.py
--- a/mercurial/util.py	Fri Dec 21 19:48:11 2007 -0500
+++ b/mercurial/util.py	Fri Dec 21 23:21:17 2007 -0500
@@ -16,6 +16,7 @@ import cStringIO, errno, getpass, popen2
 import cStringIO, errno, getpass, popen2, re, shutil, sys, tempfile, strutil
 import os, stat, threading, time, calendar, ConfigParser, locale, glob, osutil
 import re, urlparse
+import inspect
 
 try:
     set = set
@@ -221,11 +222,15 @@ filtertable = {
     'pipe:': pipefilter,
     }
 
-def filter(s, cmd):
+def filter(s, cmd, **kwargs):
     "filter a string through a command that transforms its input to its output"
     for name, fn in filtertable.iteritems():
         if cmd.startswith(name):
-            return fn(s, cmd[len(name):].lstrip())
+            cmd = cmd[len(name):].lstrip()
+            if inspect.getargspec(fn)[2]:
+                return fn(s, cmd, **kwargs)
+            else: # compatibility for old hooks not expecting kwargs
+                return fn(s, cmd)
     return pipefilter(s, cmd)
 
 def binary(s):
diff -r 1b4ed187319a -r dbf62abe9c0f tests/test-win32text
--- a/tests/test-win32text	Fri Dec 21 19:48:11 2007 -0500
+++ b/tests/test-win32text	Fri Dec 21 23:21:17 2007 -0500
@@ -7,6 +7,11 @@ for path in sys.argv[1:]:
     data = file(path, 'rb').read()
     data = data.replace('\n', '\r\n')
     file(path, 'wb').write(data)
+EOF
+
+cat > print.py <<EOF
+import sys
+print(sys.stdin.read().replace('\n', '<LF>').replace('\r', '<CR>').replace('\0', '<NUL>'))
 EOF
 
 hg init
@@ -62,4 +67,35 @@ hg log -v
 hg log -v
 echo
 
-# XXX missing tests for encode/decode hooks
+rm .hg/hgrc
+(echo some; echo text) > f3
+python -c 'file("f4.bat", "wb").write("rem empty\x0D\x0A")'
+hg add f3 f4.bat
+hg ci -m 6 -d'0 0'
+
+python print.py < bin
+python print.py < f3
+python print.py < f4.bat
+echo
+
+echo '[extensions]' >> .hg/hgrc
+echo 'win32text = ' >> .hg/hgrc
+echo '[decode]' >> .hg/hgrc
+echo '** = cleverdecode:' >> .hg/hgrc
+echo '[encode]' >> .hg/hgrc
+echo '** = cleverencode:' >> .hg/hgrc
+cat .hg/hgrc
+echo
+
+rm f3 f4.bat bin
+hg co 2>&1 | python -c 'import sys, os; sys.stdout.write(sys.stdin.read().replace(os.getcwd(), "...."))'
+python print.py < bin
+python print.py < f3
+python print.py < f4.bat
+echo
+
+python -c 'file("f5.sh", "wb").write("# empty\x0D\x0A")'
+hg add f5.sh
+hg ci -m 7 -d'0 0'
+python print.py < f5.sh
+hg cat f5.sh | python print.py
diff -r 1b4ed187319a -r dbf62abe9c0f tests/test-win32text.out
--- a/tests/test-win32text.out	Fri Dec 21 19:48:11 2007 -0500
+++ b/tests/test-win32text.out	Fri Dec 21 23:21:17 2007 -0500
@@ -155,3 +155,25 @@ 1
 
 
 
+hello<NUL><CR><LF>
+some<LF>text<LF>
+rem empty<CR><LF>
+
+[extensions]
+win32text = 
+[decode]
+** = cleverdecode:
+[encode]
+** = cleverencode:
+
+WARNING: f4.bat already has CRLF line endings
+and does not need EOL conversion by the win32text plugin.
+Before your next commit, please reconsider your encode/decode settings in 
+Mercurial.ini or ..../.hg/hgrc.
+3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+hello<NUL><CR><LF>
+some<CR><LF>text<CR><LF>
+rem empty<CR><LF>
+
+# empty<CR><LF>
+# empty<LF>


More information about the Mercurial-devel mailing list