##// END OF EJS Templates
win32text: word-wrap help texts at 70 characters
Martin Geisler -
r8002:36a23a18 default
parent child Browse files
Show More
@@ -1,144 +1,145 b''
1 # win32text.py - LF <-> CRLF/CR translation utilities for Windows/Mac users
1 # win32text.py - LF <-> CRLF/CR translation utilities for Windows/Mac users
2 #
2 #
3 # This software may be used and distributed according to the terms
3 # This software may be used and distributed according to the terms
4 # of the GNU General Public License, incorporated herein by reference.
4 # of the GNU General Public License, incorporated herein by reference.
5 #
5 #
6 # To perform automatic newline conversion, use:
6 # To perform automatic newline conversion, use:
7 #
7 #
8 # [extensions]
8 # [extensions]
9 # hgext.win32text =
9 # hgext.win32text =
10 # [encode]
10 # [encode]
11 # ** = cleverencode:
11 # ** = cleverencode:
12 # # or ** = macencode:
12 # # or ** = macencode:
13 # [decode]
13 # [decode]
14 # ** = cleverdecode:
14 # ** = cleverdecode:
15 # # or ** = macdecode:
15 # # or ** = macdecode:
16 #
16 #
17 # If not doing conversion, to make sure you do not commit CRLF/CR by accident:
17 # If not doing conversion, to make sure you do not commit CRLF/CR by
18 # accident:
18 #
19 #
19 # [hooks]
20 # [hooks]
20 # pretxncommit.crlf = python:hgext.win32text.forbidcrlf
21 # pretxncommit.crlf = python:hgext.win32text.forbidcrlf
21 # # or pretxncommit.cr = python:hgext.win32text.forbidcr
22 # # or pretxncommit.cr = python:hgext.win32text.forbidcr
22 #
23 #
23 # To do the same check on a server to prevent CRLF/CR from being pushed or
24 # To do the same check on a server to prevent CRLF/CR from being
24 # pulled:
25 # pushed or pulled:
25 #
26 #
26 # [hooks]
27 # [hooks]
27 # pretxnchangegroup.crlf = python:hgext.win32text.forbidcrlf
28 # pretxnchangegroup.crlf = python:hgext.win32text.forbidcrlf
28 # # or pretxnchangegroup.cr = python:hgext.win32text.forbidcr
29 # # or pretxnchangegroup.cr = python:hgext.win32text.forbidcr
29
30
30 from mercurial.i18n import _
31 from mercurial.i18n import _
31 from mercurial.node import short
32 from mercurial.node import short
32 from mercurial import util
33 from mercurial import util
33 import re
34 import re
34
35
35 # regexp for single LF without CR preceding.
36 # regexp for single LF without CR preceding.
36 re_single_lf = re.compile('(^|[^\r])\n', re.MULTILINE)
37 re_single_lf = re.compile('(^|[^\r])\n', re.MULTILINE)
37
38
38 newlinestr = {'\r\n': 'CRLF', '\r': 'CR'}
39 newlinestr = {'\r\n': 'CRLF', '\r': 'CR'}
39 filterstr = {'\r\n': 'clever', '\r': 'mac'}
40 filterstr = {'\r\n': 'clever', '\r': 'mac'}
40
41
41 def checknewline(s, newline, ui=None, repo=None, filename=None):
42 def checknewline(s, newline, ui=None, repo=None, filename=None):
42 # warn if already has 'newline' in repository.
43 # warn if already has 'newline' in repository.
43 # it might cause unexpected eol conversion.
44 # it might cause unexpected eol conversion.
44 # see issue 302:
45 # see issue 302:
45 # http://www.selenic.com/mercurial/bts/issue302
46 # http://www.selenic.com/mercurial/bts/issue302
46 if newline in s and ui and filename and repo:
47 if newline in s and ui and filename and repo:
47 ui.warn(_('WARNING: %s already has %s line endings\n'
48 ui.warn(_('WARNING: %s already has %s line endings\n'
48 'and does not need EOL conversion by the win32text plugin.\n'
49 'and does not need EOL conversion by the win32text plugin.\n'
49 'Before your next commit, please reconsider your '
50 'Before your next commit, please reconsider your '
50 'encode/decode settings in \nMercurial.ini or %s.\n') %
51 'encode/decode settings in \nMercurial.ini or %s.\n') %
51 (filename, newlinestr[newline], repo.join('hgrc')))
52 (filename, newlinestr[newline], repo.join('hgrc')))
52
53
53 def dumbdecode(s, cmd, **kwargs):
54 def dumbdecode(s, cmd, **kwargs):
54 checknewline(s, '\r\n', **kwargs)
55 checknewline(s, '\r\n', **kwargs)
55 # replace single LF to CRLF
56 # replace single LF to CRLF
56 return re_single_lf.sub('\\1\r\n', s)
57 return re_single_lf.sub('\\1\r\n', s)
57
58
58 def dumbencode(s, cmd):
59 def dumbencode(s, cmd):
59 return s.replace('\r\n', '\n')
60 return s.replace('\r\n', '\n')
60
61
61 def macdumbdecode(s, cmd, **kwargs):
62 def macdumbdecode(s, cmd, **kwargs):
62 checknewline(s, '\r', **kwargs)
63 checknewline(s, '\r', **kwargs)
63 return s.replace('\n', '\r')
64 return s.replace('\n', '\r')
64
65
65 def macdumbencode(s, cmd):
66 def macdumbencode(s, cmd):
66 return s.replace('\r', '\n')
67 return s.replace('\r', '\n')
67
68
68 def cleverdecode(s, cmd, **kwargs):
69 def cleverdecode(s, cmd, **kwargs):
69 if not util.binary(s):
70 if not util.binary(s):
70 return dumbdecode(s, cmd, **kwargs)
71 return dumbdecode(s, cmd, **kwargs)
71 return s
72 return s
72
73
73 def cleverencode(s, cmd):
74 def cleverencode(s, cmd):
74 if not util.binary(s):
75 if not util.binary(s):
75 return dumbencode(s, cmd)
76 return dumbencode(s, cmd)
76 return s
77 return s
77
78
78 def macdecode(s, cmd, **kwargs):
79 def macdecode(s, cmd, **kwargs):
79 if not util.binary(s):
80 if not util.binary(s):
80 return macdumbdecode(s, cmd, **kwargs)
81 return macdumbdecode(s, cmd, **kwargs)
81 return s
82 return s
82
83
83 def macencode(s, cmd):
84 def macencode(s, cmd):
84 if not util.binary(s):
85 if not util.binary(s):
85 return macdumbencode(s, cmd)
86 return macdumbencode(s, cmd)
86 return s
87 return s
87
88
88 _filters = {
89 _filters = {
89 'dumbdecode:': dumbdecode,
90 'dumbdecode:': dumbdecode,
90 'dumbencode:': dumbencode,
91 'dumbencode:': dumbencode,
91 'cleverdecode:': cleverdecode,
92 'cleverdecode:': cleverdecode,
92 'cleverencode:': cleverencode,
93 'cleverencode:': cleverencode,
93 'macdumbdecode:': macdumbdecode,
94 'macdumbdecode:': macdumbdecode,
94 'macdumbencode:': macdumbencode,
95 'macdumbencode:': macdumbencode,
95 'macdecode:': macdecode,
96 'macdecode:': macdecode,
96 'macencode:': macencode,
97 'macencode:': macencode,
97 }
98 }
98
99
99 def forbidnewline(ui, repo, hooktype, node, newline, **kwargs):
100 def forbidnewline(ui, repo, hooktype, node, newline, **kwargs):
100 halt = False
101 halt = False
101 for rev in xrange(repo[node].rev(), len(repo)):
102 for rev in xrange(repo[node].rev(), len(repo)):
102 c = repo[rev]
103 c = repo[rev]
103 for f in c.files():
104 for f in c.files():
104 if f not in c:
105 if f not in c:
105 continue
106 continue
106 data = c[f].data()
107 data = c[f].data()
107 if not util.binary(data) and newline in data:
108 if not util.binary(data) and newline in data:
108 if not halt:
109 if not halt:
109 ui.warn(_('Attempt to commit or push text file(s) '
110 ui.warn(_('Attempt to commit or push text file(s) '
110 'using %s line endings\n') %
111 'using %s line endings\n') %
111 newlinestr[newline])
112 newlinestr[newline])
112 ui.warn(_('in %s: %s\n') % (short(c.node()), f))
113 ui.warn(_('in %s: %s\n') % (short(c.node()), f))
113 halt = True
114 halt = True
114 if halt and hooktype == 'pretxnchangegroup':
115 if halt and hooktype == 'pretxnchangegroup':
115 crlf = newlinestr[newline].lower()
116 crlf = newlinestr[newline].lower()
116 filter = filterstr[newline]
117 filter = filterstr[newline]
117 ui.warn(_('\nTo prevent this mistake in your local repository,\n'
118 ui.warn(_('\nTo prevent this mistake in your local repository,\n'
118 'add to Mercurial.ini or .hg/hgrc:\n'
119 'add to Mercurial.ini or .hg/hgrc:\n'
119 '\n'
120 '\n'
120 '[hooks]\n'
121 '[hooks]\n'
121 'pretxncommit.%s = python:hgext.win32text.forbid%s\n'
122 'pretxncommit.%s = python:hgext.win32text.forbid%s\n'
122 '\n'
123 '\n'
123 'and also consider adding:\n'
124 'and also consider adding:\n'
124 '\n'
125 '\n'
125 '[extensions]\n'
126 '[extensions]\n'
126 'hgext.win32text =\n'
127 'hgext.win32text =\n'
127 '[encode]\n'
128 '[encode]\n'
128 '** = %sencode:\n'
129 '** = %sencode:\n'
129 '[decode]\n'
130 '[decode]\n'
130 '** = %sdecode:\n') % (crlf, crlf, filter, filter))
131 '** = %sdecode:\n') % (crlf, crlf, filter, filter))
131 return halt
132 return halt
132
133
133 def forbidcrlf(ui, repo, hooktype, node, **kwargs):
134 def forbidcrlf(ui, repo, hooktype, node, **kwargs):
134 return forbidnewline(ui, repo, hooktype, node, '\r\n', **kwargs)
135 return forbidnewline(ui, repo, hooktype, node, '\r\n', **kwargs)
135
136
136 def forbidcr(ui, repo, hooktype, node, **kwargs):
137 def forbidcr(ui, repo, hooktype, node, **kwargs):
137 return forbidnewline(ui, repo, hooktype, node, '\r', **kwargs)
138 return forbidnewline(ui, repo, hooktype, node, '\r', **kwargs)
138
139
139 def reposetup(ui, repo):
140 def reposetup(ui, repo):
140 if not repo.local():
141 if not repo.local():
141 return
142 return
142 for name, fn in _filters.iteritems():
143 for name, fn in _filters.iteritems():
143 repo.adddatafilter(name, fn)
144 repo.adddatafilter(name, fn)
144
145
General Comments 0
You need to be logged in to leave comments. Login now