##// END OF EJS Templates
win32text: Add macencode/macdecode
OHASHI Hideya -
r6481:e837dded default
parent child Browse files
Show More
@@ -0,0 +1,115
1 #!/bin/sh
2
3 cat > unix2mac.py <<EOF
4 import sys
5
6 for path in sys.argv[1:]:
7 data = file(path, 'rb').read()
8 data = data.replace('\n', '\r')
9 file(path, 'wb').write(data)
10 EOF
11
12 cat > print.py <<EOF
13 import sys
14 print(sys.stdin.read().replace('\n', '<LF>').replace('\r', '<CR>').replace('\0', '<NUL>'))
15 EOF
16
17 hg init
18 echo '[hooks]' >> .hg/hgrc
19 echo 'pretxncommit.cr = python:hgext.win32text.forbidcr' >> .hg/hgrc
20 echo 'pretxnchangegroup.cr = python:hgext.win32text.forbidcr' >> .hg/hgrc
21 cat .hg/hgrc
22 echo
23
24 echo hello > f
25 hg add f
26 hg ci -m 1 -d'0 0'
27 echo
28
29 python unix2mac.py f
30 hg ci -m 2 -d'0 0'
31 hg revert -a
32 echo
33
34 mkdir d
35 echo hello > d/f2
36 python unix2mac.py d/f2
37 hg add d/f2
38 hg ci -m 3 -d'0 0'
39 hg revert -a
40 rm d/f2
41 echo
42
43 hg rem f
44 hg ci -m 4 -d'0 0'
45 echo
46
47 python -c 'file("bin", "wb").write("hello\x00\x0D")'
48 hg add bin
49 hg ci -m 5 -d'0 0'
50 hg log -v
51 echo
52
53 hg clone . dupe
54 echo
55 for x in a b c d; do echo content > dupe/$x; done
56 hg -R dupe add
57 python unix2mac.py dupe/b dupe/c dupe/d
58 hg -R dupe ci -m a -d'0 0' dupe/a
59 hg -R dupe ci -m b/c -d'0 0' dupe/[bc]
60 hg -R dupe ci -m d -d'0 0' dupe/d
61 hg -R dupe log -v
62 echo
63
64 hg pull dupe
65 echo
66
67 hg log -v
68 echo
69
70 rm .hg/hgrc
71 (echo some; echo text) > f3
72 python -c 'file("f4.bat", "wb").write("rem empty\x0D")'
73 hg add f3 f4.bat
74 hg ci -m 6 -d'0 0'
75
76 python print.py < bin
77 python print.py < f3
78 python print.py < f4.bat
79 echo
80
81 echo '[extensions]' >> .hg/hgrc
82 echo 'win32text = ' >> .hg/hgrc
83 echo '[decode]' >> .hg/hgrc
84 echo '** = macdecode:' >> .hg/hgrc
85 echo '[encode]' >> .hg/hgrc
86 echo '** = macencode:' >> .hg/hgrc
87 cat .hg/hgrc
88 echo
89
90 rm f3 f4.bat bin
91 hg co 2>&1 | python -c 'import sys, os; sys.stdout.write(sys.stdin.read().replace(os.getcwd(), "...."))'
92 python print.py < bin
93 python print.py < f3
94 python print.py < f4.bat
95 echo
96
97 python -c 'file("f5.sh", "wb").write("# empty\x0D")'
98 hg add f5.sh
99 hg ci -m 7 -d'0 0'
100 python print.py < f5.sh
101 hg cat f5.sh | python print.py
102
103 echo '% just linefeed' > linefeed
104 hg ci -qAm 8 linefeed
105 python print.py < linefeed
106 hg cat linefeed | python print.py
107 hg st -q
108 hg revert -a linefeed
109 python print.py < linefeed
110 hg st -q
111 echo modified >> linefeed
112 hg st -q
113 hg revert -a
114 hg st -q
115 python print.py < linefeed
@@ -0,0 +1,187
1 [hooks]
2 pretxncommit.cr = python:hgext.win32text.forbidcr
3 pretxnchangegroup.cr = python:hgext.win32text.forbidcr
4
5
6 Attempt to commit or push text file(s) using CR line endings
7 in dea860dc51ec: f
8 transaction abort!
9 rollback completed
10 abort: pretxncommit.cr hook failed
11 reverting f
12
13 Attempt to commit or push text file(s) using CR line endings
14 in 8aa1d87b4e2f: d/f2
15 transaction abort!
16 rollback completed
17 abort: pretxncommit.cr hook failed
18 forgetting d/f2
19
20
21 changeset: 2:d7599e43717c
22 tag: tip
23 user: test
24 date: Thu Jan 01 00:00:00 1970 +0000
25 files: bin
26 description:
27 5
28
29
30 changeset: 1:c72a7d1d0907
31 user: test
32 date: Thu Jan 01 00:00:00 1970 +0000
33 files: f
34 description:
35 4
36
37
38 changeset: 0:fcf06d5c4e1d
39 user: test
40 date: Thu Jan 01 00:00:00 1970 +0000
41 files: f
42 description:
43 1
44
45
46
47 updating working directory
48 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
49
50 adding dupe/a
51 adding dupe/b
52 adding dupe/c
53 adding dupe/d
54 changeset: 5:ebbcbe52b20e
55 tag: tip
56 user: test
57 date: Thu Jan 01 00:00:00 1970 +0000
58 files: d
59 description:
60 d
61
62
63 changeset: 4:ceeb93d6508a
64 user: test
65 date: Thu Jan 01 00:00:00 1970 +0000
66 files: b c
67 description:
68 b/c
69
70
71 changeset: 3:c5404edbb872
72 user: test
73 date: Thu Jan 01 00:00:00 1970 +0000
74 files: a
75 description:
76 a
77
78
79 changeset: 2:d7599e43717c
80 user: test
81 date: Thu Jan 01 00:00:00 1970 +0000
82 files: bin
83 description:
84 5
85
86
87 changeset: 1:c72a7d1d0907
88 user: test
89 date: Thu Jan 01 00:00:00 1970 +0000
90 files: f
91 description:
92 4
93
94
95 changeset: 0:fcf06d5c4e1d
96 user: test
97 date: Thu Jan 01 00:00:00 1970 +0000
98 files: f
99 description:
100 1
101
102
103
104 pulling from dupe
105 searching for changes
106 adding changesets
107 adding manifests
108 adding file changes
109 added 3 changesets with 4 changes to 4 files
110 Attempt to commit or push text file(s) using CR line endings
111 in ceeb93d6508a: b
112 in ceeb93d6508a: c
113 in ebbcbe52b20e: d
114
115 To prevent this mistake in your local repository,
116 add to Mercurial.ini or .hg/hgrc:
117
118 [hooks]
119 pretxncommit.cr = python:hgext.win32text.forbidcr
120
121 and also consider adding:
122
123 [extensions]
124 hgext.win32text =
125 [encode]
126 ** = macencode:
127 [decode]
128 ** = macdecode:
129 transaction abort!
130 rollback completed
131 abort: pretxnchangegroup.cr hook failed
132
133 changeset: 2:d7599e43717c
134 tag: tip
135 user: test
136 date: Thu Jan 01 00:00:00 1970 +0000
137 files: bin
138 description:
139 5
140
141
142 changeset: 1:c72a7d1d0907
143 user: test
144 date: Thu Jan 01 00:00:00 1970 +0000
145 files: f
146 description:
147 4
148
149
150 changeset: 0:fcf06d5c4e1d
151 user: test
152 date: Thu Jan 01 00:00:00 1970 +0000
153 files: f
154 description:
155 1
156
157
158
159 hello<NUL><CR>
160 some<LF>text<LF>
161 rem empty<CR>
162
163 [extensions]
164 win32text =
165 [decode]
166 ** = macdecode:
167 [encode]
168 ** = macencode:
169
170 WARNING: f4.bat already has CR line endings
171 and does not need EOL conversion by the win32text plugin.
172 Before your next commit, please reconsider your encode/decode settings in
173 Mercurial.ini or ..../.hg/hgrc.
174 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
175 hello<NUL><CR>
176 some<CR>text<CR>
177 rem empty<CR>
178
179 # empty<CR>
180 # empty<LF>
181 % just linefeed<LF>
182 % just linefeed<LF>
183 no changes needed to linefeed
184 % just linefeed<LF>
185 M linefeed
186 reverting linefeed
187 % just linefeed<CR>
@@ -1,103 +1,144
1 # win32text.py - LF <-> CRLF translation utilities for Windows users
1 # win32text.py - LF <-> CRLF/CR translation utilities for Windows/Mac users
2 2 #
3 3 # This software may be used and distributed according to the terms
4 4 # of the GNU General Public License, incorporated herein by reference.
5 5 #
6 6 # To perform automatic newline conversion, use:
7 7 #
8 8 # [extensions]
9 9 # hgext.win32text =
10 10 # [encode]
11 11 # ** = cleverencode:
12 # # or ** = macencode:
12 13 # [decode]
13 14 # ** = cleverdecode:
15 # # or ** = macdecode:
14 16 #
15 # If not doing conversion, to make sure you do not commit CRLF by accident:
17 # If not doing conversion, to make sure you do not commit CRLF/CR by accident:
16 18 #
17 19 # [hooks]
18 20 # pretxncommit.crlf = python:hgext.win32text.forbidcrlf
21 # # or pretxncommit.cr = python:hgext.win32text.forbidcr
19 22 #
20 # To do the same check on a server to prevent CRLF from being pushed or pulled:
23 # To do the same check on a server to prevent CRLF/CR from being pushed or
24 # pulled:
21 25 #
22 26 # [hooks]
23 27 # pretxnchangegroup.crlf = python:hgext.win32text.forbidcrlf
28 # # or pretxnchangegroup.cr = python:hgext.win32text.forbidcr
24 29
25 30 from mercurial import util
26 31 from mercurial.i18n import gettext as _
27 32 from mercurial.node import bin, short
28 33 import re
29 34
30 35 # regexp for single LF without CR preceding.
31 36 re_single_lf = re.compile('(^|[^\r])\n', re.MULTILINE)
32 37
33 def dumbdecode(s, cmd, ui=None, repo=None, filename=None, **kwargs):
34 # warn if already has CRLF in repository.
38 newlinestr = {'\r\n': 'CRLF', '\r': 'CR'}
39 filterstr = {'\r\n': 'clever', '\r': 'mac'}
40
41 def checknewline(s, newline, ui=None, repo=None, filename=None):
42 # warn if already has 'newline' in repository.
35 43 # it might cause unexpected eol conversion.
36 44 # see issue 302:
37 45 # http://www.selenic.com/mercurial/bts/issue302
38 if '\r\n' in s and ui and filename and repo:
39 ui.warn(_('WARNING: %s already has CRLF line endings\n'
46 if newline in s and ui and filename and repo:
47 ui.warn(_('WARNING: %s already has %s line endings\n'
40 48 'and does not need EOL conversion by the win32text plugin.\n'
41 49 'Before your next commit, please reconsider your '
42 50 'encode/decode settings in \nMercurial.ini or %s.\n') %
43 (filename, repo.join('hgrc')))
51 (filename, newlinestr[newline], repo.join('hgrc')))
52
53 def dumbdecode(s, cmd, **kwargs):
54 checknewline(s, '\r\n', **kwargs)
44 55 # replace single LF to CRLF
45 56 return re_single_lf.sub('\\1\r\n', s)
46 57
47 58 def dumbencode(s, cmd):
48 59 return s.replace('\r\n', '\n')
49 60
61 def macdumbdecode(s, cmd, **kwargs):
62 checknewline(s, '\r', **kwargs)
63 return s.replace('\n', '\r')
64
65 def macdumbencode(s, cmd):
66 return s.replace('\r', '\n')
67
50 68 def cleverdecode(s, cmd, **kwargs):
51 69 if util.binary(s):
52 70 return s
53 71 return dumbdecode(s, cmd, **kwargs)
54 72
55 73 def cleverencode(s, cmd):
56 74 if util.binary(s):
57 75 return s
58 76 return dumbencode(s, cmd)
59 77
78 def macdecode(s, cmd, **kwargs):
79 if util.binary(s):
80 return s
81 return macdumbdecode(s, cmd, **kwargs)
82
83 def macencode(s, cmd):
84 if util.binary(s):
85 return s
86 return macdumbencode(s, cmd)
87
60 88 _filters = {
61 89 'dumbdecode:': dumbdecode,
62 90 'dumbencode:': dumbencode,
63 91 'cleverdecode:': cleverdecode,
64 92 'cleverencode:': cleverencode,
93 'macdumbdecode:': macdumbdecode,
94 'macdumbencode:': macdumbencode,
95 'macdecode:': macdecode,
96 'macencode:': macencode,
65 97 }
66 98
67 def forbidcrlf(ui, repo, hooktype, node, **kwargs):
99 def forbidcrlforcr(ui, repo, hooktype, node, newline, **kwargs):
68 100 halt = False
69 101 for rev in xrange(repo.changelog.rev(bin(node)), repo.changelog.count()):
70 102 c = repo.changectx(rev)
71 103 for f in c.files():
72 104 if f not in c:
73 105 continue
74 106 data = c[f].data()
75 if not util.binary(data) and '\r\n' in data:
107 if not util.binary(data) and newline in data:
76 108 if not halt:
77 109 ui.warn(_('Attempt to commit or push text file(s) '
78 'using CRLF line endings\n'))
110 'using %s line endings\n') %
111 newlinestr[newline])
79 112 ui.warn(_('in %s: %s\n') % (short(c.node()), f))
80 113 halt = True
81 114 if halt and hooktype == 'pretxnchangegroup':
115 crlf = newlinestr[newline].lower()
116 filter = filterstr[newline]
82 117 ui.warn(_('\nTo prevent this mistake in your local repository,\n'
83 118 'add to Mercurial.ini or .hg/hgrc:\n'
84 119 '\n'
85 120 '[hooks]\n'
86 'pretxncommit.crlf = python:hgext.win32text.forbidcrlf\n'
121 'pretxncommit.%s = python:hgext.win32text.forbid%s\n'
87 122 '\n'
88 123 'and also consider adding:\n'
89 124 '\n'
90 125 '[extensions]\n'
91 126 'hgext.win32text =\n'
92 127 '[encode]\n'
93 '** = cleverencode:\n'
128 '** = %sencode:\n'
94 129 '[decode]\n'
95 '** = cleverdecode:\n'))
130 '** = %sdecode:\n') % (crlf, crlf, filter, filter))
96 131 return halt
97 132
133 def forbidcrlf(ui, repo, hooktype, node, **kwargs):
134 return forbidcrlforcr(ui, repo, hooktype, node, '\r\n', **kwargs)
135
136 def forbidcr(ui, repo, hooktype, node, **kwargs):
137 return forbidcrlforcr(ui, repo, hooktype, node, '\r', **kwargs)
138
98 139 def reposetup(ui, repo):
99 140 if not repo.local():
100 141 return
101 142 for name, fn in _filters.iteritems():
102 143 repo.adddatafilter(name, fn)
103 144
General Comments 0
You need to be logged in to leave comments. Login now