comparison 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
comparison
equal deleted inserted replaced
5674:659955e2e366 5675:a5fe27b83a4a
1 # win32text.py - LF <-> CRLF translation utilities for Windows users
2 #
3 # This software may be used and distributed according to the terms
4 # of the GNU General Public License, incorporated herein by reference.
5 #
6 # To perform automatic newline conversion, use:
7 #
8 # [extensions]
9 # hgext.win32text =
10 # [encode]
11 # ** = cleverencode:
12 # [decode]
13 # ** = cleverdecode:
14 #
15 # If not doing conversion, to make sure you do not commit CRLF by accident:
16 #
17 # [hooks]
18 # pretxncommit.crlf = python:hgext.win32text.forbidcrlf
19 #
20 # To do the same check on a server to prevent CRLF from being pushed or pulled:
21 #
22 # [hooks]
23 # pretxnchangegroup.crlf = python:hgext.win32text.forbidcrlf
24
1 from mercurial import util, ui 25 from mercurial import util, ui
2 from mercurial.i18n import gettext as _ 26 from mercurial.i18n import gettext as _
27 from mercurial.node import *
3 import re 28 import re
4 29
5 # regexp for single LF without CR preceding. 30 # regexp for single LF without CR preceding.
6 re_single_lf = re.compile('(^|[^\r])\n', re.MULTILINE) 31 re_single_lf = re.compile('(^|[^\r])\n', re.MULTILINE)
7 32
41 'dumbdecode:': dumbdecode, 66 'dumbdecode:': dumbdecode,
42 'dumbencode:': dumbencode, 67 'dumbencode:': dumbencode,
43 'cleverdecode:': cleverdecode, 68 'cleverdecode:': cleverdecode,
44 'cleverencode:': cleverencode, 69 'cleverencode:': cleverencode,
45 }) 70 })
71
72 def forbidcrlf(ui, repo, hooktype, node, **kwargs):
73 halt = False
74 for rev in xrange(repo.changelog.rev(bin(node)), repo.changelog.count()):
75 c = repo.changectx(rev)
76 for f in c.files():
77 if f not in c:
78 continue
79 data = c[f].data()
80 if '\0' not in data and '\r\n' in data:
81 if not halt:
82 ui.warn(_('Attempt to commit or push text file(s) '
83 'using CRLF line endings\n'))
84 ui.warn(_('in %s: %s\n') % (short(c.node()), f))
85 halt = True
86 if halt and hooktype == 'pretxnchangegroup':
87 ui.warn(_('\nTo prevent this mistake in your local repository,\n'
88 'add to Mercurial.ini or .hg/hgrc:\n'
89 '\n'
90 '[hooks]\n'
91 'pretxncommit.crlf = python:hgext.win32text.forbidcrlf\n'
92 '\n'
93 'and also consider adding:\n'
94 '\n'
95 '[extensions]\n'
96 'hgext.win32text =\n'
97 '[encode]\n'
98 '** = cleverencode:\n'
99 '[decode]\n'
100 '** = cleverdecode:\n'))
101 return halt