##// END OF EJS Templates
win32text: drop the `changing_parents` context in revert upgrade...
marmoute -
r50908:05a2f65c default
parent child Browse files
Show More
@@ -1,249 +1,248
1 1 # win32text.py - LF <-> CRLF/CR translation utilities for Windows/Mac users
2 2 #
3 3 # Copyright 2005, 2007-2009 Olivia Mackall <olivia@selenic.com> and others
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 '''perform automatic newline conversion (DEPRECATED)
9 9
10 10 Deprecation: The win32text extension requires each user to configure
11 11 the extension again and again for each clone since the configuration
12 12 is not copied when cloning.
13 13
14 14 We have therefore made the ``eol`` as an alternative. The ``eol``
15 15 uses a version controlled file for its configuration and each clone
16 16 will therefore use the right settings from the start.
17 17
18 18 To perform automatic newline conversion, use::
19 19
20 20 [extensions]
21 21 win32text =
22 22 [encode]
23 23 ** = cleverencode:
24 24 # or ** = macencode:
25 25
26 26 [decode]
27 27 ** = cleverdecode:
28 28 # or ** = macdecode:
29 29
30 30 If not doing conversion, to make sure you do not commit CRLF/CR by accident::
31 31
32 32 [hooks]
33 33 pretxncommit.crlf = python:hgext.win32text.forbidcrlf
34 34 # or pretxncommit.cr = python:hgext.win32text.forbidcr
35 35
36 36 To do the same check on a server to prevent CRLF/CR from being
37 37 pushed or pulled::
38 38
39 39 [hooks]
40 40 pretxnchangegroup.crlf = python:hgext.win32text.forbidcrlf
41 41 # or pretxnchangegroup.cr = python:hgext.win32text.forbidcr
42 42 '''
43 43
44 44
45 45 import re
46 46 from mercurial.i18n import _
47 47 from mercurial.node import short
48 48 from mercurial import (
49 49 cmdutil,
50 50 extensions,
51 51 registrar,
52 52 )
53 53 from mercurial.utils import stringutil
54 54
55 55 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
56 56 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
57 57 # be specifying the version(s) of Mercurial they are tested with, or
58 58 # leave the attribute unspecified.
59 59 testedwith = b'ships-with-hg-core'
60 60
61 61 configtable = {}
62 62 configitem = registrar.configitem(configtable)
63 63
64 64 configitem(
65 65 b'win32text',
66 66 b'warn',
67 67 default=True,
68 68 )
69 69
70 70 # regexp for single LF without CR preceding.
71 71 re_single_lf = re.compile(b'(^|[^\r])\n', re.MULTILINE)
72 72
73 73 newlinestr = {b'\r\n': b'CRLF', b'\r': b'CR'}
74 74 filterstr = {b'\r\n': b'clever', b'\r': b'mac'}
75 75
76 76
77 77 def checknewline(s, newline, ui=None, repo=None, filename=None):
78 78 # warn if already has 'newline' in repository.
79 79 # it might cause unexpected eol conversion.
80 80 # see issue 302:
81 81 # https://bz.mercurial-scm.org/302
82 82 if newline in s and ui and filename and repo:
83 83 ui.warn(
84 84 _(
85 85 b'WARNING: %s already has %s line endings\n'
86 86 b'and does not need EOL conversion by the win32text plugin.\n'
87 87 b'Before your next commit, please reconsider your '
88 88 b'encode/decode settings in \nMercurial.ini or %s.\n'
89 89 )
90 90 % (filename, newlinestr[newline], repo.vfs.join(b'hgrc'))
91 91 )
92 92
93 93
94 94 def dumbdecode(s, cmd, **kwargs):
95 95 checknewline(s, b'\r\n', **kwargs)
96 96 # replace single LF to CRLF
97 97 return re_single_lf.sub(b'\\1\r\n', s)
98 98
99 99
100 100 def dumbencode(s, cmd):
101 101 return s.replace(b'\r\n', b'\n')
102 102
103 103
104 104 def macdumbdecode(s, cmd, **kwargs):
105 105 checknewline(s, b'\r', **kwargs)
106 106 return s.replace(b'\n', b'\r')
107 107
108 108
109 109 def macdumbencode(s, cmd):
110 110 return s.replace(b'\r', b'\n')
111 111
112 112
113 113 def cleverdecode(s, cmd, **kwargs):
114 114 if not stringutil.binary(s):
115 115 return dumbdecode(s, cmd, **kwargs)
116 116 return s
117 117
118 118
119 119 def cleverencode(s, cmd):
120 120 if not stringutil.binary(s):
121 121 return dumbencode(s, cmd)
122 122 return s
123 123
124 124
125 125 def macdecode(s, cmd, **kwargs):
126 126 if not stringutil.binary(s):
127 127 return macdumbdecode(s, cmd, **kwargs)
128 128 return s
129 129
130 130
131 131 def macencode(s, cmd):
132 132 if not stringutil.binary(s):
133 133 return macdumbencode(s, cmd)
134 134 return s
135 135
136 136
137 137 _filters = {
138 138 b'dumbdecode:': dumbdecode,
139 139 b'dumbencode:': dumbencode,
140 140 b'cleverdecode:': cleverdecode,
141 141 b'cleverencode:': cleverencode,
142 142 b'macdumbdecode:': macdumbdecode,
143 143 b'macdumbencode:': macdumbencode,
144 144 b'macdecode:': macdecode,
145 145 b'macencode:': macencode,
146 146 }
147 147
148 148
149 149 def forbidnewline(ui, repo, hooktype, node, newline, **kwargs):
150 150 halt = False
151 151 seen = set()
152 152 # we try to walk changesets in reverse order from newest to
153 153 # oldest, so that if we see a file multiple times, we take the
154 154 # newest version as canonical. this prevents us from blocking a
155 155 # changegroup that contains an unacceptable commit followed later
156 156 # by a commit that fixes the problem.
157 157 tip = repo[b'tip']
158 158 for rev in range(repo.changelog.tiprev(), repo[node].rev() - 1, -1):
159 159 c = repo[rev]
160 160 for f in c.files():
161 161 if f in seen or f not in tip or f not in c:
162 162 continue
163 163 seen.add(f)
164 164 data = c[f].data()
165 165 if not stringutil.binary(data) and newline in data:
166 166 if not halt:
167 167 ui.warn(
168 168 _(
169 169 b'attempt to commit or push text file(s) '
170 170 b'using %s line endings\n'
171 171 )
172 172 % newlinestr[newline]
173 173 )
174 174 ui.warn(_(b'in %s: %s\n') % (short(c.node()), f))
175 175 halt = True
176 176 if halt and hooktype == b'pretxnchangegroup':
177 177 crlf = newlinestr[newline].lower()
178 178 filter = filterstr[newline]
179 179 ui.warn(
180 180 _(
181 181 b'\nTo prevent this mistake in your local repository,\n'
182 182 b'add to Mercurial.ini or .hg/hgrc:\n'
183 183 b'\n'
184 184 b'[hooks]\n'
185 185 b'pretxncommit.%s = python:hgext.win32text.forbid%s\n'
186 186 b'\n'
187 187 b'and also consider adding:\n'
188 188 b'\n'
189 189 b'[extensions]\n'
190 190 b'win32text =\n'
191 191 b'[encode]\n'
192 192 b'** = %sencode:\n'
193 193 b'[decode]\n'
194 194 b'** = %sdecode:\n'
195 195 )
196 196 % (crlf, crlf, filter, filter)
197 197 )
198 198 return halt
199 199
200 200
201 201 def forbidcrlf(ui, repo, hooktype, node, **kwargs):
202 202 return forbidnewline(ui, repo, hooktype, node, b'\r\n', **kwargs)
203 203
204 204
205 205 def forbidcr(ui, repo, hooktype, node, **kwargs):
206 206 return forbidnewline(ui, repo, hooktype, node, b'\r', **kwargs)
207 207
208 208
209 209 def reposetup(ui, repo):
210 210 if not repo.local():
211 211 return
212 212 for name, fn in _filters.items():
213 213 repo.adddatafilter(name, fn)
214 214
215 215
216 216 def wrap_revert(orig, repo, ctx, names, uipathfn, actions, *args, **kwargs):
217 217 # reset dirstate cache for file we touch
218 218 ds = repo.dirstate
219 with ds.changing_parents(repo):
220 for filename in actions[b'revert'][0]:
221 entry = ds.get_entry(filename)
222 if entry is not None:
223 if entry.p1_tracked:
224 # If we revert the file, it is possibly dirty. However,
225 # this extension meddle with the file content and therefore
226 # its size. As a result, we cannot simply call
227 # `dirstate.set_possibly_dirty` as it will not affet the
228 # expected size of the file.
229 #
230 # At least, now, the quirk is properly documented.
231 ds.hacky_extension_update_file(
232 filename,
233 entry.tracked,
234 p1_tracked=True,
235 p2_info=entry.p2_info,
236 )
219 for filename in actions[b'revert'][0]:
220 entry = ds.get_entry(filename)
221 if entry is not None:
222 if entry.p1_tracked:
223 # If we revert the file, it is possibly dirty. However,
224 # this extension meddle with the file content and therefore
225 # its size. As a result, we cannot simply call
226 # `dirstate.set_possibly_dirty` as it will not affet the
227 # expected size of the file.
228 #
229 # At least, now, the quirk is properly documented.
230 ds.hacky_extension_update_file(
231 filename,
232 entry.tracked,
233 p1_tracked=True,
234 p2_info=entry.p2_info,
235 )
237 236 return orig(repo, ctx, names, uipathfn, actions, *args, **kwargs)
238 237
239 238
240 239 def extsetup(ui):
241 240 # deprecated config: win32text.warn
242 241 if ui.configbool(b'win32text', b'warn'):
243 242 ui.warn(
244 243 _(
245 244 b"win32text is deprecated: "
246 245 b"https://mercurial-scm.org/wiki/Win32TextExtension\n"
247 246 )
248 247 )
249 248 extensions.wrapfunction(cmdutil, '_performrevert', wrap_revert)
General Comments 0
You need to be logged in to leave comments. Login now