Mercurial > hg
comparison hgext/keyword.py @ 45942:89a2afe31e82
formating: upgrade to black 20.8b1
This required a couple of small tweaks to un-confuse black, but now it
works. Big formatting changes come from:
* Dramatically improved collection-splitting logic upstream
* Black having a strong (correct IMO) opinion that """ is better than '''
Differential Revision: https://phab.mercurial-scm.org/D9430
author | Augie Fackler <raf@durin42.com> |
---|---|
date | Fri, 27 Nov 2020 17:03:29 -0500 |
parents | 9f70512ae2cf |
children | b492bc018011 |
comparison
equal
deleted
inserted
replaced
45941:346af7687c6f | 45942:89a2afe31e82 |
---|---|
156 | 156 |
157 configtable = {} | 157 configtable = {} |
158 configitem = registrar.configitem(configtable) | 158 configitem = registrar.configitem(configtable) |
159 | 159 |
160 configitem( | 160 configitem( |
161 b'keywordset', b'svn', default=False, | 161 b'keywordset', |
162 b'svn', | |
163 default=False, | |
162 ) | 164 ) |
163 # date like in cvs' $Date | 165 # date like in cvs' $Date |
164 @templatefilter(b'utcdate', intype=templateutil.date) | 166 @templatefilter(b'utcdate', intype=templateutil.date) |
165 def utcdate(date): | 167 def utcdate(date): |
166 '''Date. Returns a UTC-date in this format: "2009/08/18 11:00:13". | 168 """Date. Returns a UTC-date in this format: "2009/08/18 11:00:13".""" |
167 ''' | |
168 dateformat = b'%Y/%m/%d %H:%M:%S' | 169 dateformat = b'%Y/%m/%d %H:%M:%S' |
169 return dateutil.datestr((date[0], 0), dateformat) | 170 return dateutil.datestr((date[0], 0), dateformat) |
170 | 171 |
171 | 172 |
172 # date like in svn's $Date | 173 # date like in svn's $Date |
173 @templatefilter(b'svnisodate', intype=templateutil.date) | 174 @templatefilter(b'svnisodate', intype=templateutil.date) |
174 def svnisodate(date): | 175 def svnisodate(date): |
175 '''Date. Returns a date in this format: "2009-08-18 13:00:13 | 176 """Date. Returns a date in this format: "2009-08-18 13:00:13 |
176 +0200 (Tue, 18 Aug 2009)". | 177 +0200 (Tue, 18 Aug 2009)". |
177 ''' | 178 """ |
178 return dateutil.datestr(date, b'%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)') | 179 return dateutil.datestr(date, b'%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)') |
179 | 180 |
180 | 181 |
181 # date like in svn's $Id | 182 # date like in svn's $Id |
182 @templatefilter(b'svnutcdate', intype=templateutil.date) | 183 @templatefilter(b'svnutcdate', intype=templateutil.date) |
183 def svnutcdate(date): | 184 def svnutcdate(date): |
184 '''Date. Returns a UTC-date in this format: "2009-08-18 | 185 """Date. Returns a UTC-date in this format: "2009-08-18 |
185 11:00:13Z". | 186 11:00:13Z". |
186 ''' | 187 """ |
187 dateformat = b'%Y-%m-%d %H:%M:%SZ' | 188 dateformat = b'%Y-%m-%d %H:%M:%SZ' |
188 return dateutil.datestr((date[0], 0), dateformat) | 189 return dateutil.datestr((date[0], 0), dateformat) |
189 | 190 |
190 | 191 |
191 # make keyword tools accessible | 192 # make keyword tools accessible |
219 templates.update(kwsets[ui.configbool(b'keywordset', b'svn')]) | 220 templates.update(kwsets[ui.configbool(b'keywordset', b'svn')]) |
220 return templates | 221 return templates |
221 | 222 |
222 | 223 |
223 def _shrinktext(text, subfunc): | 224 def _shrinktext(text, subfunc): |
224 '''Helper for keyword expansion removal in text. | 225 """Helper for keyword expansion removal in text. |
225 Depending on subfunc also returns number of substitutions.''' | 226 Depending on subfunc also returns number of substitutions.""" |
226 return subfunc(br'$\1$', text) | 227 return subfunc(br'$\1$', text) |
227 | 228 |
228 | 229 |
229 def _preselect(wstatus, changed): | 230 def _preselect(wstatus, changed): |
230 '''Retrieves modified and added files from a working directory state | 231 """Retrieves modified and added files from a working directory state |
231 and returns the subset of each contained in given changed files | 232 and returns the subset of each contained in given changed files |
232 retrieved from a change context.''' | 233 retrieved from a change context.""" |
233 modified = [f for f in wstatus.modified if f in changed] | 234 modified = [f for f in wstatus.modified if f in changed] |
234 added = [f for f in wstatus.added if f in changed] | 235 added = [f for f in wstatus.added if f in changed] |
235 return modified, added | 236 return modified, added |
236 | 237 |
237 | 238 |
238 class kwtemplater(object): | 239 class kwtemplater(object): |
239 ''' | 240 """ |
240 Sets up keyword templates, corresponding keyword regex, and | 241 Sets up keyword templates, corresponding keyword regex, and |
241 provides keyword substitution functions. | 242 provides keyword substitution functions. |
242 ''' | 243 """ |
243 | 244 |
244 def __init__(self, ui, repo, inc, exc): | 245 def __init__(self, ui, repo, inc, exc): |
245 self.ui = ui | 246 self.ui = ui |
246 self._repo = weakref.ref(repo) | 247 self._repo = weakref.ref(repo) |
247 self.match = match.match(repo.root, b'', [], inc, exc) | 248 self.match = match.match(repo.root, b'', [], inc, exc) |
302 ctx = self.linkctx(path, node) | 303 ctx = self.linkctx(path, node) |
303 return self.substitute(data, path, ctx, self.rekw.sub) | 304 return self.substitute(data, path, ctx, self.rekw.sub) |
304 return data | 305 return data |
305 | 306 |
306 def iskwfile(self, cand, ctx): | 307 def iskwfile(self, cand, ctx): |
307 '''Returns subset of candidates which are configured for keyword | 308 """Returns subset of candidates which are configured for keyword |
308 expansion but are not symbolic links.''' | 309 expansion but are not symbolic links.""" |
309 return [f for f in cand if self.match(f) and b'l' not in ctx.flags(f)] | 310 return [f for f in cand if self.match(f) and b'l' not in ctx.flags(f)] |
310 | 311 |
311 def overwrite(self, ctx, candidates, lookup, expand, rekw=False): | 312 def overwrite(self, ctx, candidates, lookup, expand, rekw=False): |
312 '''Overwrites selected files expanding/shrinking keywords.''' | 313 '''Overwrites selected files expanding/shrinking keywords.''' |
313 if self.restrict or lookup or self.postcommit: # exclude kw_copy | 314 if self.restrict or lookup or self.postcommit: # exclude kw_copy |
372 if not stringutil.binary(text): | 373 if not stringutil.binary(text): |
373 return _shrinktext(text, self.rekwexp.sub).splitlines(True) | 374 return _shrinktext(text, self.rekwexp.sub).splitlines(True) |
374 return lines | 375 return lines |
375 | 376 |
376 def wread(self, fname, data): | 377 def wread(self, fname, data): |
377 '''If in restricted mode returns data read from wdir with | 378 """If in restricted mode returns data read from wdir with |
378 keyword substitutions removed.''' | 379 keyword substitutions removed.""" |
379 if self.restrict: | 380 if self.restrict: |
380 return self.shrink(fname, data) | 381 return self.shrink(fname, data) |
381 return data | 382 return data |
382 | 383 |
383 | 384 |
384 class kwfilelog(filelog.filelog): | 385 class kwfilelog(filelog.filelog): |
385 ''' | 386 """ |
386 Subclass of filelog to hook into its read, add, cmp methods. | 387 Subclass of filelog to hook into its read, add, cmp methods. |
387 Keywords are "stored" unexpanded, and processed on reading. | 388 Keywords are "stored" unexpanded, and processed on reading. |
388 ''' | 389 """ |
389 | 390 |
390 def __init__(self, opener, kwt, path): | 391 def __init__(self, opener, kwt, path): |
391 super(kwfilelog, self).__init__(opener, path) | 392 super(kwfilelog, self).__init__(opener, path) |
392 self.kwt = kwt | 393 self.kwt = kwt |
393 self.path = path | 394 self.path = path |
409 text = self.kwt.shrink(self.path, text) | 410 text = self.kwt.shrink(self.path, text) |
410 return super(kwfilelog, self).cmp(node, text) | 411 return super(kwfilelog, self).cmp(node, text) |
411 | 412 |
412 | 413 |
413 def _status(ui, repo, wctx, kwt, *pats, **opts): | 414 def _status(ui, repo, wctx, kwt, *pats, **opts): |
414 '''Bails out if [keyword] configuration is not active. | 415 """Bails out if [keyword] configuration is not active. |
415 Returns status of working directory.''' | 416 Returns status of working directory.""" |
416 if kwt: | 417 if kwt: |
417 opts = pycompat.byteskwargs(opts) | 418 opts = pycompat.byteskwargs(opts) |
418 return repo.status( | 419 return repo.status( |
419 match=scmutil.match(wctx, pats, opts), | 420 match=scmutil.match(wctx, pats, opts), |
420 clean=True, | 421 clean=True, |
446 ], | 447 ], |
447 _(b'hg kwdemo [-d] [-f RCFILE] [TEMPLATEMAP]...'), | 448 _(b'hg kwdemo [-d] [-f RCFILE] [TEMPLATEMAP]...'), |
448 optionalrepo=True, | 449 optionalrepo=True, |
449 ) | 450 ) |
450 def demo(ui, repo, *args, **opts): | 451 def demo(ui, repo, *args, **opts): |
451 '''print [keywordmaps] configuration and an expansion example | 452 """print [keywordmaps] configuration and an expansion example |
452 | 453 |
453 Show current, custom, or default keyword template maps and their | 454 Show current, custom, or default keyword template maps and their |
454 expansions. | 455 expansions. |
455 | 456 |
456 Extend the current configuration by specifying maps as arguments | 457 Extend the current configuration by specifying maps as arguments |
457 and using -f/--rcfile to source an external hgrc file. | 458 and using -f/--rcfile to source an external hgrc file. |
458 | 459 |
459 Use -d/--default to disable current configuration. | 460 Use -d/--default to disable current configuration. |
460 | 461 |
461 See :hg:`help templates` for information on templates and filters. | 462 See :hg:`help templates` for information on templates and filters. |
462 ''' | 463 """ |
463 | 464 |
464 def demoitems(section, items): | 465 def demoitems(section, items): |
465 ui.write(b'[%s]\n' % section) | 466 ui.write(b'[%s]\n' % section) |
466 for k, v in sorted(items): | 467 for k, v in sorted(items): |
467 if isinstance(v, bool): | 468 if isinstance(v, bool): |
545 cmdutil.walkopts, | 546 cmdutil.walkopts, |
546 _(b'hg kwexpand [OPTION]... [FILE]...'), | 547 _(b'hg kwexpand [OPTION]... [FILE]...'), |
547 inferrepo=True, | 548 inferrepo=True, |
548 ) | 549 ) |
549 def expand(ui, repo, *pats, **opts): | 550 def expand(ui, repo, *pats, **opts): |
550 '''expand keywords in the working directory | 551 """expand keywords in the working directory |
551 | 552 |
552 Run after (re)enabling keyword expansion. | 553 Run after (re)enabling keyword expansion. |
553 | 554 |
554 kwexpand refuses to run if given files contain local changes. | 555 kwexpand refuses to run if given files contain local changes. |
555 ''' | 556 """ |
556 # 3rd argument sets expansion to True | 557 # 3rd argument sets expansion to True |
557 _kwfwrite(ui, repo, True, *pats, **opts) | 558 _kwfwrite(ui, repo, True, *pats, **opts) |
558 | 559 |
559 | 560 |
560 @command( | 561 @command( |
567 + cmdutil.walkopts, | 568 + cmdutil.walkopts, |
568 _(b'hg kwfiles [OPTION]... [FILE]...'), | 569 _(b'hg kwfiles [OPTION]... [FILE]...'), |
569 inferrepo=True, | 570 inferrepo=True, |
570 ) | 571 ) |
571 def files(ui, repo, *pats, **opts): | 572 def files(ui, repo, *pats, **opts): |
572 '''show files configured for keyword expansion | 573 """show files configured for keyword expansion |
573 | 574 |
574 List which files in the working directory are matched by the | 575 List which files in the working directory are matched by the |
575 [keyword] configuration patterns. | 576 [keyword] configuration patterns. |
576 | 577 |
577 Useful to prevent inadvertent keyword expansion and to speed up | 578 Useful to prevent inadvertent keyword expansion and to speed up |
586 | 587 |
587 K = keyword expansion candidate | 588 K = keyword expansion candidate |
588 k = keyword expansion candidate (not tracked) | 589 k = keyword expansion candidate (not tracked) |
589 I = ignored | 590 I = ignored |
590 i = ignored (not tracked) | 591 i = ignored (not tracked) |
591 ''' | 592 """ |
592 kwt = getattr(repo, '_keywordkwt', None) | 593 kwt = getattr(repo, '_keywordkwt', None) |
593 wctx = repo[None] | 594 wctx = repo[None] |
594 status = _status(ui, repo, wctx, kwt, *pats, **opts) | 595 status = _status(ui, repo, wctx, kwt, *pats, **opts) |
595 if pats: | 596 if pats: |
596 cwd = repo.getcwd() | 597 cwd = repo.getcwd() |
632 cmdutil.walkopts, | 633 cmdutil.walkopts, |
633 _(b'hg kwshrink [OPTION]... [FILE]...'), | 634 _(b'hg kwshrink [OPTION]... [FILE]...'), |
634 inferrepo=True, | 635 inferrepo=True, |
635 ) | 636 ) |
636 def shrink(ui, repo, *pats, **opts): | 637 def shrink(ui, repo, *pats, **opts): |
637 '''revert expanded keywords in the working directory | 638 """revert expanded keywords in the working directory |
638 | 639 |
639 Must be run before changing/disabling active keywords. | 640 Must be run before changing/disabling active keywords. |
640 | 641 |
641 kwshrink refuses to run if given files contain local changes. | 642 kwshrink refuses to run if given files contain local changes. |
642 ''' | 643 """ |
643 # 3rd argument sets expansion to False | 644 # 3rd argument sets expansion to False |
644 _kwfwrite(ui, repo, False, *pats, **opts) | 645 _kwfwrite(ui, repo, False, *pats, **opts) |
645 | 646 |
646 | 647 |
647 # monkeypatches | 648 # monkeypatches |
648 | 649 |
649 | 650 |
650 def kwpatchfile_init(orig, self, ui, gp, backend, store, eolmode=None): | 651 def kwpatchfile_init(orig, self, ui, gp, backend, store, eolmode=None): |
651 '''Monkeypatch/wrap patch.patchfile.__init__ to avoid | 652 """Monkeypatch/wrap patch.patchfile.__init__ to avoid |
652 rejects or conflicts due to expanded keywords in working dir.''' | 653 rejects or conflicts due to expanded keywords in working dir.""" |
653 orig(self, ui, gp, backend, store, eolmode) | 654 orig(self, ui, gp, backend, store, eolmode) |
654 kwt = getattr(getattr(backend, 'repo', None), '_keywordkwt', None) | 655 kwt = getattr(getattr(backend, 'repo', None), '_keywordkwt', None) |
655 if kwt: | 656 if kwt: |
656 # shrink keywords read from working dir | 657 # shrink keywords read from working dir |
657 self.lines = kwt.shrinklines(self.fname, self.lines) | 658 self.lines = kwt.shrinklines(self.fname, self.lines) |
700 kwt.restrict = False | 701 kwt.restrict = False |
701 return newid | 702 return newid |
702 | 703 |
703 | 704 |
704 def kw_copy(orig, ui, repo, pats, opts, rename=False): | 705 def kw_copy(orig, ui, repo, pats, opts, rename=False): |
705 '''Wraps cmdutil.copy so that copy/rename destinations do not | 706 """Wraps cmdutil.copy so that copy/rename destinations do not |
706 contain expanded keywords. | 707 contain expanded keywords. |
707 Note that the source of a regular file destination may also be a | 708 Note that the source of a regular file destination may also be a |
708 symlink: | 709 symlink: |
709 hg cp sym x -> x is symlink | 710 hg cp sym x -> x is symlink |
710 cp sym x; hg cp -A sym x -> x is file (maybe expanded keywords) | 711 cp sym x; hg cp -A sym x -> x is file (maybe expanded keywords) |
711 For the latter we have to follow the symlink to find out whether its | 712 For the latter we have to follow the symlink to find out whether its |
712 target is configured for expansion and we therefore must unexpand the | 713 target is configured for expansion and we therefore must unexpand the |
713 keywords in the destination.''' | 714 keywords in the destination.""" |
714 kwt = getattr(repo, '_keywordkwt', None) | 715 kwt = getattr(repo, '_keywordkwt', None) |
715 if kwt is None: | 716 if kwt is None: |
716 return orig(ui, repo, pats, opts, rename) | 717 return orig(ui, repo, pats, opts, rename) |
717 with repo.wlock(): | 718 with repo.wlock(): |
718 orig(ui, repo, pats, opts, rename) | 719 orig(ui, repo, pats, opts, rename) |
720 return | 721 return |
721 wctx = repo[None] | 722 wctx = repo[None] |
722 cwd = repo.getcwd() | 723 cwd = repo.getcwd() |
723 | 724 |
724 def haskwsource(dest): | 725 def haskwsource(dest): |
725 '''Returns true if dest is a regular file and configured for | 726 """Returns true if dest is a regular file and configured for |
726 expansion or a symlink which points to a file configured for | 727 expansion or a symlink which points to a file configured for |
727 expansion. ''' | 728 expansion.""" |
728 source = repo.dirstate.copied(dest) | 729 source = repo.dirstate.copied(dest) |
729 if b'l' in wctx.flags(source): | 730 if b'l' in wctx.flags(source): |
730 source = pathutil.canonpath( | 731 source = pathutil.canonpath( |
731 repo.root, cwd, os.path.realpath(source) | 732 repo.root, cwd, os.path.realpath(source) |
732 ) | 733 ) |
783 return self._filelog.cmp(self._filenode, fctx.data()) | 784 return self._filelog.cmp(self._filenode, fctx.data()) |
784 return True | 785 return True |
785 | 786 |
786 | 787 |
787 def uisetup(ui): | 788 def uisetup(ui): |
788 ''' Monkeypatches dispatch._parse to retrieve user command. | 789 """Monkeypatches dispatch._parse to retrieve user command. |
789 Overrides file method to return kwfilelog instead of filelog | 790 Overrides file method to return kwfilelog instead of filelog |
790 if file matches user configuration. | 791 if file matches user configuration. |
791 Wraps commit to overwrite configured files with updated | 792 Wraps commit to overwrite configured files with updated |
792 keyword substitutions. | 793 keyword substitutions. |
793 Monkeypatches patch and webcommands.''' | 794 Monkeypatches patch and webcommands.""" |
794 | 795 |
795 def kwdispatch_parse(orig, ui, args): | 796 def kwdispatch_parse(orig, ui, args): |
796 '''Monkeypatch dispatch._parse to obtain running hg command.''' | 797 '''Monkeypatch dispatch._parse to obtain running hg command.''' |
797 cmd, func, args, options, cmdoptions = orig(ui, args) | 798 cmd, func, args, options, cmdoptions = orig(ui, args) |
798 kwtools[b'hgcmd'] = cmd | 799 kwtools[b'hgcmd'] = cmd |