diff hgext/win32text.py @ 5675:a5fe27b83a4a

Issue 882: add standard hook to reject text files with CRLF. While the win32text extension does LF <-> CRLF conversion, and will issue a warning in case a file already in the repository uses CRLF, it provides no mechanism for verifying that incoming changes use LF. In a large development team with some Windows users, it is virtually guaranteed that someone will forget to set up the encode filter correctly and accidentally check in a file using CRLF, which can cause warnings for other Windows users when they next fetch changes. Since this is a general problem it is desirable to have a pre-commit (or -push) hook available to reject such accidents earlier rather than trying to fix them up after the fact.
author Jesse Glick <jesse.glick@sun.com>
date Wed, 19 Dec 2007 17:02:31 -0500
parents 8c5aca855b5d
children 11af38a592ae
line wrap: on
line diff
--- a/hgext/win32text.py	Sun Dec 16 22:55:23 2007 +0100
+++ b/hgext/win32text.py	Wed Dec 19 17:02:31 2007 -0500
@@ -1,5 +1,30 @@
+# win32text.py - LF <-> CRLF translation utilities for Windows users
+#
+# This software may be used and distributed according to the terms
+# of the GNU General Public License, incorporated herein by reference.
+#
+# To perform automatic newline conversion, use:
+#
+# [extensions]
+# hgext.win32text =
+# [encode]
+# ** = cleverencode:
+# [decode]
+# ** = cleverdecode:
+#
+# If not doing conversion, to make sure you do not commit CRLF by accident:
+#
+# [hooks]
+# pretxncommit.crlf = python:hgext.win32text.forbidcrlf
+#
+# To do the same check on a server to prevent CRLF from being pushed or pulled:
+#
+# [hooks]
+# pretxnchangegroup.crlf = python:hgext.win32text.forbidcrlf
+
 from mercurial import util, ui
 from mercurial.i18n import gettext as _
+from mercurial.node import *
 import re
 
 # regexp for single LF without CR preceding.
@@ -43,3 +68,34 @@
     'cleverdecode:': cleverdecode,
     'cleverencode:': cleverencode,
     })
+
+def forbidcrlf(ui, repo, hooktype, node, **kwargs):
+    halt = False
+    for rev in xrange(repo.changelog.rev(bin(node)), repo.changelog.count()):
+        c = repo.changectx(rev)
+        for f in c.files():
+            if f not in c:
+                continue
+            data = c[f].data()
+            if '\0' not in data and '\r\n' in data:
+                if not halt:
+                    ui.warn(_('Attempt to commit or push text file(s) '
+                              'using CRLF line endings\n'))
+                ui.warn(_('in %s: %s\n') % (short(c.node()), f))
+                halt = True
+    if halt and hooktype == 'pretxnchangegroup':
+        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'
+                  '\n'
+                  'and also consider adding:\n'
+                  '\n'
+                  '[extensions]\n'
+                  'hgext.win32text =\n'
+                  '[encode]\n'
+                  '** = cleverencode:\n'
+                  '[decode]\n'
+                  '** = cleverdecode:\n'))
+    return halt