Merge with macencode branch
authorPatrick Mezard <pmezard@gmail.com>
Sat, 05 Apr 2008 19:33:34 +0200
changeset 6484 ab8038bf5127
parent 6480 ee7762515a41 (current diff)
parent 6483 0a803195bb29 (diff)
child 6485 938319418d8c
Merge with macencode branch
hgext/win32text.py
--- a/hgext/win32text.py	Sat Apr 05 18:19:49 2008 +0200
+++ b/hgext/win32text.py	Sat Apr 05 19:33:34 2008 +0200
@@ -1,4 +1,4 @@
-# win32text.py - LF <-> CRLF translation utilities for Windows users
+# win32text.py - LF <-> CRLF/CR translation utilities for Windows/Mac users
 #
 # This software may be used and distributed according to the terms
 # of the GNU General Public License, incorporated herein by reference.
@@ -9,18 +9,23 @@
 # hgext.win32text =
 # [encode]
 # ** = cleverencode:
+# # or ** = macencode:
 # [decode]
 # ** = cleverdecode:
+# # or ** = macdecode:
 #
-# If not doing conversion, to make sure you do not commit CRLF by accident:
+# If not doing conversion, to make sure you do not commit CRLF/CR by accident:
 #
 # [hooks]
 # pretxncommit.crlf = python:hgext.win32text.forbidcrlf
+# # or pretxncommit.cr = python:hgext.win32text.forbidcr
 #
-# To do the same check on a server to prevent CRLF from being pushed or pulled:
+# To do the same check on a server to prevent CRLF/CR from being pushed or
+# pulled:
 #
 # [hooks]
 # pretxnchangegroup.crlf = python:hgext.win32text.forbidcrlf
+# # or pretxnchangegroup.cr = python:hgext.win32text.forbidcr
 
 from mercurial.i18n import gettext as _
 from mercurial.node import bin, short
@@ -29,23 +34,36 @@
 # regexp for single LF without CR preceding.
 re_single_lf = re.compile('(^|[^\r])\n', re.MULTILINE)
 
-def dumbdecode(s, cmd, ui=None, repo=None, filename=None, **kwargs):
-    # warn if already has CRLF in repository.
+newlinestr = {'\r\n': 'CRLF', '\r': 'CR'}
+filterstr = {'\r\n': 'clever', '\r': 'mac'}
+
+def checknewline(s, newline, ui=None, repo=None, filename=None):
+    # warn if already has 'newline' in repository.
     # it might cause unexpected eol conversion.
     # see issue 302:
     #   http://www.selenic.com/mercurial/bts/issue302
-    if '\r\n' in s and ui and filename and repo:
-        ui.warn(_('WARNING: %s already has CRLF line endings\n'
+    if newline in s and ui and filename and repo:
+        ui.warn(_('WARNING: %s already has %s 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')))
+                (filename, newlinestr[newline], repo.join('hgrc')))
+
+def dumbdecode(s, cmd, **kwargs):
+    checknewline(s, '\r\n', **kwargs)
     # replace single LF to CRLF
     return re_single_lf.sub('\\1\r\n', s)
 
 def dumbencode(s, cmd):
     return s.replace('\r\n', '\n')
 
+def macdumbdecode(s, cmd, **kwargs):
+    checknewline(s, '\r', **kwargs)
+    return s.replace('\n', '\r')
+
+def macdumbencode(s, cmd):
+    return s.replace('\r', '\n')
+
 def clevertest(s, cmd):
     if '\0' in s: return False
     return True
@@ -60,14 +78,28 @@
         return dumbencode(s, cmd)
     return s
 
+def macdecode(s, cmd, **kwargs):
+    if clevertest(s, cmd):
+        return macdumbdecode(s, cmd, **kwargs)
+    return s
+
+def macencode(s, cmd):
+    if clevertest(s, cmd):
+        return macdumbencode(s, cmd)
+    return s
+
 _filters = {
     'dumbdecode:': dumbdecode,
     'dumbencode:': dumbencode,
     'cleverdecode:': cleverdecode,
     'cleverencode:': cleverencode,
+    'macdumbdecode:': macdumbdecode,
+    'macdumbencode:': macdumbencode,
+    'macdecode:': macdecode,
+    'macencode:': macencode,
     }
 
-def forbidcrlf(ui, repo, hooktype, node, **kwargs):
+def forbidnewline(ui, repo, hooktype, node, newline, **kwargs):
     halt = False
     for rev in xrange(repo.changelog.rev(bin(node)), repo.changelog.count()):
         c = repo.changectx(rev)
@@ -75,29 +107,38 @@
             if f not in c:
                 continue
             data = c[f].data()
-            if '\0' not in data and '\r\n' in data:
+            if '\0' not in data and newline in data:
                 if not halt:
                     ui.warn(_('Attempt to commit or push text file(s) '
-                              'using CRLF line endings\n'))
+                              'using %s line endings\n') %
+                              newlinestr[newline])
                 ui.warn(_('in %s: %s\n') % (short(c.node()), f))
                 halt = True
     if halt and hooktype == 'pretxnchangegroup':
+        crlf = newlinestr[newline].lower()
+        filter = filterstr[newline]
         ui.warn(_('\nTo prevent this mistake in your local repository,\n'
                   'add to Mercurial.ini or .hg/hgrc:\n'
                   '\n'
                   '[hooks]\n'
-                  'pretxncommit.crlf = python:hgext.win32text.forbidcrlf\n'
+                  'pretxncommit.%s = python:hgext.win32text.forbid%s\n'
                   '\n'
                   'and also consider adding:\n'
                   '\n'
                   '[extensions]\n'
                   'hgext.win32text =\n'
                   '[encode]\n'
-                  '** = cleverencode:\n'
+                  '** = %sencode:\n'
                   '[decode]\n'
-                  '** = cleverdecode:\n'))
+                  '** = %sdecode:\n') % (crlf, crlf, filter, filter))
     return halt
 
+def forbidcrlf(ui, repo, hooktype, node, **kwargs):
+    return forbidnewline(ui, repo, hooktype, node, '\r\n', **kwargs)
+
+def forbidcr(ui, repo, hooktype, node, **kwargs):
+    return forbidnewline(ui, repo, hooktype, node, '\r', **kwargs)
+
 def reposetup(ui, repo):
     if not repo.local():
         return
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-mactext	Sat Apr 05 19:33:34 2008 +0200
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+cat > unix2mac.py <<EOF
+import sys
+
+for path in sys.argv[1:]:
+    data = file(path, 'rb').read()
+    data = data.replace('\n', '\r')
+    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
+echo '[hooks]' >> .hg/hgrc
+echo 'pretxncommit.cr = python:hgext.win32text.forbidcr' >> .hg/hgrc
+echo 'pretxnchangegroup.cr = python:hgext.win32text.forbidcr' >> .hg/hgrc
+cat .hg/hgrc
+echo
+
+echo hello > f
+hg add f
+hg ci -m 1 -d'0 0'
+echo
+
+python unix2mac.py f
+hg ci -m 2 -d'0 0'
+hg cat f | python print.py
+cat f | python print.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-mactext.out	Sat Apr 05 19:33:34 2008 +0200
@@ -0,0 +1,12 @@
+[hooks]
+pretxncommit.cr = python:hgext.win32text.forbidcr
+pretxnchangegroup.cr = python:hgext.win32text.forbidcr
+
+
+Attempt to commit or push text file(s) using CR line endings
+in dea860dc51ec: f
+transaction abort!
+rollback completed
+abort: pretxncommit.cr hook failed
+hello<LF>
+hello<CR>