Mercurial > hg
comparison hgext/eol.py @ 43076:2372284d9457
formatting: blacken the codebase
This is using my patch to black
(https://github.com/psf/black/pull/826) so we don't un-wrap collection
literals.
Done with:
hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**"' | xargs black -S
# skip-blame mass-reformatting only
# no-check-commit reformats foo_bar functions
Differential Revision: https://phab.mercurial-scm.org/D6971
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:45:02 -0400 |
parents | d98ec36be808 |
children | 687b865b95ad |
comparison
equal
deleted
inserted
replaced
43075:57875cf423c9 | 43076:2372284d9457 |
---|---|
104 pycompat, | 104 pycompat, |
105 registrar, | 105 registrar, |
106 scmutil, | 106 scmutil, |
107 util, | 107 util, |
108 ) | 108 ) |
109 from mercurial.utils import ( | 109 from mercurial.utils import stringutil |
110 stringutil, | |
111 ) | |
112 | 110 |
113 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for | 111 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for |
114 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should | 112 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should |
115 # be specifying the version(s) of Mercurial they are tested with, or | 113 # be specifying the version(s) of Mercurial they are tested with, or |
116 # leave the attribute unspecified. | 114 # leave the attribute unspecified. |
117 testedwith = 'ships-with-hg-core' | 115 testedwith = 'ships-with-hg-core' |
118 | 116 |
119 configtable = {} | 117 configtable = {} |
120 configitem = registrar.configitem(configtable) | 118 configitem = registrar.configitem(configtable) |
121 | 119 |
122 configitem('eol', 'fix-trailing-newline', | 120 configitem( |
123 default=False, | 121 'eol', 'fix-trailing-newline', default=False, |
124 ) | 122 ) |
125 configitem('eol', 'native', | 123 configitem( |
126 default=pycompat.oslinesep, | 124 'eol', 'native', default=pycompat.oslinesep, |
127 ) | 125 ) |
128 configitem('eol', 'only-consistent', | 126 configitem( |
129 default=True, | 127 'eol', 'only-consistent', default=True, |
130 ) | 128 ) |
131 | 129 |
132 # Matches a lone LF, i.e., one that is not part of CRLF. | 130 # Matches a lone LF, i.e., one that is not part of CRLF. |
133 singlelf = re.compile('(^|[^\r])\n') | 131 singlelf = re.compile('(^|[^\r])\n') |
134 | 132 |
133 | |
135 def inconsistenteol(data): | 134 def inconsistenteol(data): |
136 return '\r\n' in data and singlelf.search(data) | 135 return '\r\n' in data and singlelf.search(data) |
136 | |
137 | 137 |
138 def tolf(s, params, ui, **kwargs): | 138 def tolf(s, params, ui, **kwargs): |
139 """Filter to convert to LF EOLs.""" | 139 """Filter to convert to LF EOLs.""" |
140 if stringutil.binary(s): | 140 if stringutil.binary(s): |
141 return s | 141 return s |
142 if ui.configbool('eol', 'only-consistent') and inconsistenteol(s): | 142 if ui.configbool('eol', 'only-consistent') and inconsistenteol(s): |
143 return s | 143 return s |
144 if (ui.configbool('eol', 'fix-trailing-newline') | 144 if ( |
145 and s and not s.endswith('\n')): | 145 ui.configbool('eol', 'fix-trailing-newline') |
146 and s | |
147 and not s.endswith('\n') | |
148 ): | |
146 s = s + '\n' | 149 s = s + '\n' |
147 return util.tolf(s) | 150 return util.tolf(s) |
151 | |
148 | 152 |
149 def tocrlf(s, params, ui, **kwargs): | 153 def tocrlf(s, params, ui, **kwargs): |
150 """Filter to convert to CRLF EOLs.""" | 154 """Filter to convert to CRLF EOLs.""" |
151 if stringutil.binary(s): | 155 if stringutil.binary(s): |
152 return s | 156 return s |
153 if ui.configbool('eol', 'only-consistent') and inconsistenteol(s): | 157 if ui.configbool('eol', 'only-consistent') and inconsistenteol(s): |
154 return s | 158 return s |
155 if (ui.configbool('eol', 'fix-trailing-newline') | 159 if ( |
156 and s and not s.endswith('\n')): | 160 ui.configbool('eol', 'fix-trailing-newline') |
161 and s | |
162 and not s.endswith('\n') | |
163 ): | |
157 s = s + '\n' | 164 s = s + '\n' |
158 return util.tocrlf(s) | 165 return util.tocrlf(s) |
166 | |
159 | 167 |
160 def isbinary(s, params): | 168 def isbinary(s, params): |
161 """Filter to do nothing with the file.""" | 169 """Filter to do nothing with the file.""" |
162 return s | 170 return s |
171 | |
163 | 172 |
164 filters = { | 173 filters = { |
165 'to-lf': tolf, | 174 'to-lf': tolf, |
166 'to-crlf': tocrlf, | 175 'to-crlf': tocrlf, |
167 'is-binary': isbinary, | 176 'is-binary': isbinary, |
168 # The following provide backwards compatibility with win32text | 177 # The following provide backwards compatibility with win32text |
169 'cleverencode:': tolf, | 178 'cleverencode:': tolf, |
170 'cleverdecode:': tocrlf | 179 'cleverdecode:': tocrlf, |
171 } | 180 } |
181 | |
172 | 182 |
173 class eolfile(object): | 183 class eolfile(object): |
174 def __init__(self, ui, root, data): | 184 def __init__(self, ui, root, data): |
175 self._decode = {'LF': 'to-lf', 'CRLF': 'to-crlf', 'BIN': 'is-binary'} | 185 self._decode = {'LF': 'to-lf', 'CRLF': 'to-crlf', 'BIN': 'is-binary'} |
176 self._encode = {'LF': 'to-lf', 'CRLF': 'to-crlf', 'BIN': 'is-binary'} | 186 self._encode = {'LF': 'to-lf', 'CRLF': 'to-crlf', 'BIN': 'is-binary'} |
206 for pattern, key, m in self.patterns: | 216 for pattern, key, m in self.patterns: |
207 try: | 217 try: |
208 ui.setconfig('decode', pattern, self._decode[key], 'eol') | 218 ui.setconfig('decode', pattern, self._decode[key], 'eol') |
209 ui.setconfig('encode', pattern, self._encode[key], 'eol') | 219 ui.setconfig('encode', pattern, self._encode[key], 'eol') |
210 except KeyError: | 220 except KeyError: |
211 ui.warn(_("ignoring unknown EOL style '%s' from %s\n") | 221 ui.warn( |
212 % (key, self.cfg.source('patterns', pattern))) | 222 _("ignoring unknown EOL style '%s' from %s\n") |
223 % (key, self.cfg.source('patterns', pattern)) | |
224 ) | |
213 # eol.only-consistent can be specified in ~/.hgrc or .hgeol | 225 # eol.only-consistent can be specified in ~/.hgrc or .hgeol |
214 for k, v in self.cfg.items('eol'): | 226 for k, v in self.cfg.items('eol'): |
215 ui.setconfig('eol', k, v, 'eol') | 227 ui.setconfig('eol', k, v, 'eol') |
216 | 228 |
217 def checkrev(self, repo, ctx, files): | 229 def checkrev(self, repo, ctx, files): |
218 failed = [] | 230 failed = [] |
219 for f in (files or ctx.files()): | 231 for f in files or ctx.files(): |
220 if f not in ctx: | 232 if f not in ctx: |
221 continue | 233 continue |
222 for pattern, key, m in self.patterns: | 234 for pattern, key, m in self.patterns: |
223 if not m(f): | 235 if not m(f): |
224 continue | 236 continue |
225 target = self._encode[key] | 237 target = self._encode[key] |
226 data = ctx[f].data() | 238 data = ctx[f].data() |
227 if (target == "to-lf" and "\r\n" in data | 239 if ( |
228 or target == "to-crlf" and singlelf.search(data)): | 240 target == "to-lf" |
241 and "\r\n" in data | |
242 or target == "to-crlf" | |
243 and singlelf.search(data) | |
244 ): | |
229 failed.append((f, target, bytes(ctx))) | 245 failed.append((f, target, bytes(ctx))) |
230 break | 246 break |
231 return failed | 247 return failed |
248 | |
232 | 249 |
233 def parseeol(ui, repo, nodes): | 250 def parseeol(ui, repo, nodes): |
234 try: | 251 try: |
235 for node in nodes: | 252 for node in nodes: |
236 try: | 253 try: |
242 data = repo[node]['.hgeol'].data() | 259 data = repo[node]['.hgeol'].data() |
243 return eolfile(ui, repo.root, data) | 260 return eolfile(ui, repo.root, data) |
244 except (IOError, LookupError): | 261 except (IOError, LookupError): |
245 pass | 262 pass |
246 except errormod.ParseError as inst: | 263 except errormod.ParseError as inst: |
247 ui.warn(_("warning: ignoring .hgeol file due to parse error " | 264 ui.warn( |
248 "at %s: %s\n") % (inst.args[1], inst.args[0])) | 265 _("warning: ignoring .hgeol file due to parse error " "at %s: %s\n") |
266 % (inst.args[1], inst.args[0]) | |
267 ) | |
249 return None | 268 return None |
269 | |
250 | 270 |
251 def ensureenabled(ui): | 271 def ensureenabled(ui): |
252 """make sure the extension is enabled when used as hook | 272 """make sure the extension is enabled when used as hook |
253 | 273 |
254 When eol is used through hooks, the extension is never formally loaded and | 274 When eol is used through hooks, the extension is never formally loaded and |
258 """ | 278 """ |
259 if 'eol' in ui._knownconfig: | 279 if 'eol' in ui._knownconfig: |
260 return | 280 return |
261 ui.setconfig('extensions', 'eol', '', source='internal') | 281 ui.setconfig('extensions', 'eol', '', source='internal') |
262 extensions.loadall(ui, ['eol']) | 282 extensions.loadall(ui, ['eol']) |
283 | |
263 | 284 |
264 def _checkhook(ui, repo, node, headsonly): | 285 def _checkhook(ui, repo, node, headsonly): |
265 # Get revisions to check and touched files at the same time | 286 # Get revisions to check and touched files at the same time |
266 ensureenabled(ui) | 287 ensureenabled(ui) |
267 files = set() | 288 files = set() |
282 | 303 |
283 if failed: | 304 if failed: |
284 eols = {'to-lf': 'CRLF', 'to-crlf': 'LF'} | 305 eols = {'to-lf': 'CRLF', 'to-crlf': 'LF'} |
285 msgs = [] | 306 msgs = [] |
286 for f, target, node in sorted(failed): | 307 for f, target, node in sorted(failed): |
287 msgs.append(_(" %s in %s should not have %s line endings") % | 308 msgs.append( |
288 (f, node, eols[target])) | 309 _(" %s in %s should not have %s line endings") |
310 % (f, node, eols[target]) | |
311 ) | |
289 raise errormod.Abort(_("end-of-line check failed:\n") + "\n".join(msgs)) | 312 raise errormod.Abort(_("end-of-line check failed:\n") + "\n".join(msgs)) |
313 | |
290 | 314 |
291 def checkallhook(ui, repo, node, hooktype, **kwargs): | 315 def checkallhook(ui, repo, node, hooktype, **kwargs): |
292 """verify that files have expected EOLs""" | 316 """verify that files have expected EOLs""" |
293 _checkhook(ui, repo, node, False) | 317 _checkhook(ui, repo, node, False) |
294 | 318 |
319 | |
295 def checkheadshook(ui, repo, node, hooktype, **kwargs): | 320 def checkheadshook(ui, repo, node, hooktype, **kwargs): |
296 """verify that files have expected EOLs""" | 321 """verify that files have expected EOLs""" |
297 _checkhook(ui, repo, node, True) | 322 _checkhook(ui, repo, node, True) |
298 | 323 |
324 | |
299 # "checkheadshook" used to be called "hook" | 325 # "checkheadshook" used to be called "hook" |
300 hook = checkheadshook | 326 hook = checkheadshook |
327 | |
301 | 328 |
302 def preupdate(ui, repo, hooktype, parent1, parent2): | 329 def preupdate(ui, repo, hooktype, parent1, parent2): |
303 p1node = scmutil.resolvehexnodeidprefix(repo, parent1) | 330 p1node = scmutil.resolvehexnodeidprefix(repo, parent1) |
304 repo.loadeol([p1node]) | 331 repo.loadeol([p1node]) |
305 return False | 332 return False |
306 | 333 |
334 | |
307 def uisetup(ui): | 335 def uisetup(ui): |
308 ui.setconfig('hooks', 'preupdate.eol', preupdate, 'eol') | 336 ui.setconfig('hooks', 'preupdate.eol', preupdate, 'eol') |
337 | |
309 | 338 |
310 def extsetup(ui): | 339 def extsetup(ui): |
311 try: | 340 try: |
312 extensions.find('win32text') | 341 extensions.find('win32text') |
313 ui.warn(_("the eol extension is incompatible with the " | 342 ui.warn( |
314 "win32text extension\n")) | 343 _( |
344 "the eol extension is incompatible with the " | |
345 "win32text extension\n" | |
346 ) | |
347 ) | |
315 except KeyError: | 348 except KeyError: |
316 pass | 349 pass |
317 | 350 |
318 | 351 |
319 def reposetup(ui, repo): | 352 def reposetup(ui, repo): |
325 repo.adddatafilter(name, fn) | 358 repo.adddatafilter(name, fn) |
326 | 359 |
327 ui.setconfig('patch', 'eol', 'auto', 'eol') | 360 ui.setconfig('patch', 'eol', 'auto', 'eol') |
328 | 361 |
329 class eolrepo(repo.__class__): | 362 class eolrepo(repo.__class__): |
330 | |
331 def loadeol(self, nodes): | 363 def loadeol(self, nodes): |
332 eol = parseeol(self.ui, self, nodes) | 364 eol = parseeol(self.ui, self, nodes) |
333 if eol is None: | 365 if eol is None: |
334 return None | 366 return None |
335 eol.copytoui(self.ui) | 367 eol.copytoui(self.ui) |
412 # We should not abort here, since the user should | 444 # We should not abort here, since the user should |
413 # be able to say "** = native" to automatically | 445 # be able to say "** = native" to automatically |
414 # have all non-binary files taken care of. | 446 # have all non-binary files taken care of. |
415 continue | 447 continue |
416 if inconsistenteol(data): | 448 if inconsistenteol(data): |
417 raise errormod.Abort(_("inconsistent newline style " | 449 raise errormod.Abort( |
418 "in %s\n") % f) | 450 _("inconsistent newline style " "in %s\n") % f |
451 ) | |
419 return super(eolrepo, self).commitctx(ctx, error, origctx) | 452 return super(eolrepo, self).commitctx(ctx, error, origctx) |
453 | |
420 repo.__class__ = eolrepo | 454 repo.__class__ = eolrepo |
421 repo._hgcleardirstate() | 455 repo._hgcleardirstate() |