87 |
87 |
88 from mercurial import commands, cmdutil, context, fancyopts |
88 from mercurial import commands, cmdutil, context, fancyopts |
89 from mercurial import filelog, localrepo, revlog, templater, util |
89 from mercurial import filelog, localrepo, revlog, templater, util |
90 from mercurial.node import * |
90 from mercurial.node import * |
91 from mercurial.i18n import gettext as _ |
91 from mercurial.i18n import gettext as _ |
92 import getopt, os.path, re, shutil, sys, tempfile, time |
92 import getopt, os.path, re, shutil, tempfile, time |
93 |
93 |
94 commands.optionalrepo += ' kwdemo' |
94 commands.optionalrepo += ' kwdemo' |
95 |
95 |
96 # hg commands that do not act on keywords |
96 # hg commands that do not act on keywords |
97 nokwcommands = ('add addremove bundle copy export grep identify incoming init' |
97 nokwcommands = ('add addremove bundle copy export grep identify incoming init' |
98 ' log outgoing push remove rename rollback tip convert') |
98 ' log outgoing push remove rename rollback tip convert email') |
99 |
99 |
100 # hg commands that trigger expansion only when writing to working dir, |
100 # hg commands that trigger expansion only when writing to working dir, |
101 # not when reading filelog, and unexpand when reading from working dir |
101 # not when reading filelog, and unexpand when reading from working dir |
102 restricted = 'diff1 record qfold qimport qnew qpush qrefresh qrecord' |
102 restricted = 'diff1 record qfold qimport qnew qpush qrefresh qrecord' |
103 |
103 |
104 def utcdate(date): |
104 def utcdate(date): |
105 '''Returns hgdate in cvs-like UTC format.''' |
105 '''Returns hgdate in cvs-like UTC format.''' |
106 return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0])) |
106 return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0])) |
107 |
107 |
108 |
108 |
109 _kwtemplater = None |
109 _kwtemplater, _cmd, _cmdoptions = None, None, None |
110 |
110 |
111 # backwards compatibility hacks |
111 # backwards compatibility hacks |
|
112 |
|
113 try: |
|
114 # cmdutil.parse moves to dispatch._parse in 18a9fbb5cd78 |
|
115 from mercurial import dispatch |
|
116 _dispatch_parse = dispatch._parse |
|
117 except ImportError: |
|
118 try: |
|
119 # commands.parse moves to cmdutil.parse in 0c61124ad877 |
|
120 _dispatch_parse = cmdutil.parse |
|
121 except AttributeError: |
|
122 _dispatch_parse = commands.parse |
|
123 |
|
124 def _kwdispatch_parse(ui, args): |
|
125 '''Monkeypatch dispatch._parse to obtain |
|
126 current command and command options (global _cmd, _cmdoptions).''' |
|
127 global _cmd, _cmdoptions |
|
128 _cmd, func, args, options, _cmdoptions = _dispatch_parse(ui, args) |
|
129 return _cmd, func, args, options, _cmdoptions |
|
130 |
|
131 try: |
|
132 setattr(dispatch, '_parse', _kwdispatch_parse) |
|
133 except (NameError, ImportError): |
|
134 # 0.9.4 needs ImportError |
|
135 if hasattr(cmdutil, 'parse'): |
|
136 cmdutil.parse = _kwdispatch_parse |
|
137 else: |
|
138 commands.parse = _kwdispatch_parse |
112 |
139 |
113 try: |
140 try: |
114 # avoid spurious rejects if patchfile is available |
141 # avoid spurious rejects if patchfile is available |
115 from mercurial.patch import patchfile |
142 from mercurial.patch import patchfile |
116 _patchfile_init = patchfile.__init__ |
143 _patchfile_init = patchfile.__init__ |
132 template_filters = templatefilters.filters |
159 template_filters = templatefilters.filters |
133 template_firstline = templatefilters.firstline |
160 template_firstline = templatefilters.firstline |
134 except ImportError: |
161 except ImportError: |
135 template_filters = templater.common_filters |
162 template_filters = templater.common_filters |
136 template_firstline = templater.firstline |
163 template_firstline = templater.firstline |
137 |
|
138 try: |
|
139 # cmdutil.parse moves to dispatch._parse in 18a9fbb5cd78 |
|
140 # also avoid name conflict with other dispatch package(s) |
|
141 from mercurial.dispatch import _parse |
|
142 except ImportError: |
|
143 try: |
|
144 # commands.parse moves to cmdutil.parse in 0c61124ad877 |
|
145 _parse = cmdutil.parse |
|
146 except AttributeError: |
|
147 _parse = commands.parse |
|
148 |
164 |
149 def _wwrite(repo, f, data, mf): |
165 def _wwrite(repo, f, data, mf): |
150 '''Makes repo.wwrite backwards compatible.''' |
166 '''Makes repo.wwrite backwards compatible.''' |
151 # 656e06eebda7 removed file descriptor argument |
167 # 656e06eebda7 removed file descriptor argument |
152 # 67982d3ee76c added flags argument |
168 # 67982d3ee76c added flags argument |
243 'Source': '{root}/{file},v', |
259 'Source': '{root}/{file},v', |
244 'Id': '{file|basename},v {node|short} {date|utcdate} {author|user}', |
260 'Id': '{file|basename},v {node|short} {date|utcdate} {author|user}', |
245 'Header': '{root}/{file},v {node|short} {date|utcdate} {author|user}', |
261 'Header': '{root}/{file},v {node|short} {date|utcdate} {author|user}', |
246 } |
262 } |
247 |
263 |
248 def __init__(self, ui, repo, inc, exc, restricted): |
264 def __init__(self, ui, repo, inc, exc, restrict): |
249 self.ui = ui |
265 self.ui = ui |
250 self.repo = repo |
266 self.repo = repo |
251 self.matcher = util.matcher(repo.root, inc=inc, exc=exc)[1] |
267 self.matcher = util.matcher(repo.root, inc=inc, exc=exc)[1] |
252 self.restricted = restricted |
268 self.restrict = restrict |
253 self.commitnode = None |
269 self.commitnode = None |
254 self.path = '' |
270 self.path = '' |
255 |
271 |
256 kwmaps = self.ui.configitems('keywordmaps') |
272 kwmaps = self.ui.configitems('keywordmaps') |
257 if kwmaps: # override default templates |
273 if kwmaps: # override default templates |
294 |
310 |
295 return subfunc(kwsub, data) |
311 return subfunc(kwsub, data) |
296 |
312 |
297 def expand(self, node, data): |
313 def expand(self, node, data): |
298 '''Returns data with keywords expanded.''' |
314 '''Returns data with keywords expanded.''' |
299 if self.restricted or util.binary(data): |
315 if self.restrict or util.binary(data): |
300 return data |
316 return data |
301 return self.substitute(node, data, self.re_kw.sub) |
317 return self.substitute(node, data, self.re_kw.sub) |
302 |
318 |
303 def process(self, node, data, expand): |
319 def process(self, node, data, expand): |
304 '''Returns a tuple: data, count. |
320 '''Returns a tuple: data, count. |
534 Wraps commit to overwrite configured files with updated |
550 Wraps commit to overwrite configured files with updated |
535 keyword substitutions. |
551 keyword substitutions. |
536 This is done for local repos only, and only if there are |
552 This is done for local repos only, and only if there are |
537 files configured at all for keyword substitution.''' |
553 files configured at all for keyword substitution.''' |
538 |
554 |
539 if not repo.local(): |
555 global _kwtemplater |
540 return |
556 hgcmd, hgcmdopts = _cmd, _cmdoptions |
541 |
557 |
542 hgcmd, func, args, opts, cmdopts = _parse(ui, sys.argv[1:]) |
558 try: |
543 if hgcmd in nokwcommands.split(): |
559 if (not repo.local() or hgcmd in nokwcommands.split() |
544 return |
560 or '.hg' in repo.root.split('/') |
545 |
561 or repo._url.startswith('bundle:')): |
546 if hgcmd == 'diff': |
|
547 # only expand if comparing against working dir |
|
548 node1, node2 = cmdutil.revpair(repo, cmdopts.get('rev')) |
|
549 if node2 is not None: |
|
550 return |
562 return |
551 # shrink if rev is not current node |
563 except AttributeError: |
552 if node1 is not None and node1 != repo.changectx().node(): |
564 pass |
553 hgcmd = 'diff1' |
565 |
554 |
566 inc, exc = [], ['.hg*'] |
555 inc, exc = [], ['.hgtags'] |
|
556 for pat, opt in ui.configitems('keyword'): |
567 for pat, opt in ui.configitems('keyword'): |
557 if opt != 'ignore': |
568 if opt != 'ignore': |
558 inc.append(pat) |
569 inc.append(pat) |
559 else: |
570 else: |
560 exc.append(pat) |
571 exc.append(pat) |
561 if not inc: |
572 if not inc: |
562 return |
573 return |
563 |
574 |
564 global _kwtemplater |
575 if hgcmd == 'diff': |
565 _restricted = hgcmd in restricted.split() |
576 # only expand if comparing against working dir |
566 _kwtemplater = kwtemplater(ui, repo, inc, exc, _restricted) |
577 node1, node2 = cmdutil.revpair(repo, hgcmdopts.get('rev')) |
|
578 if node2 is not None: |
|
579 return |
|
580 # shrink if rev is not current node |
|
581 if node1 is not None and node1 != repo.changectx().node(): |
|
582 hgcmd = 'diff1' |
|
583 |
|
584 restrict = hgcmd in restricted.split() |
|
585 _kwtemplater = kwtemplater(ui, repo, inc, exc, restrict) |
567 |
586 |
568 class kwrepo(repo.__class__): |
587 class kwrepo(repo.__class__): |
569 def file(self, f, kwmatch=False): |
588 def file(self, f, kwmatch=False): |
570 if f[0] == '/': |
589 if f[0] == '/': |
571 f = f[1:] |
590 f = f[1:] |
573 return kwfilelog(self.sopener, f) |
592 return kwfilelog(self.sopener, f) |
574 return filelog.filelog(self.sopener, f) |
593 return filelog.filelog(self.sopener, f) |
575 |
594 |
576 def wread(self, filename): |
595 def wread(self, filename): |
577 data = super(kwrepo, self).wread(filename) |
596 data = super(kwrepo, self).wread(filename) |
578 if _restricted and _kwtemplater.matcher(filename): |
597 if restrict and _kwtemplater.matcher(filename): |
579 return _kwtemplater.shrink(data) |
598 return _kwtemplater.shrink(data) |
580 return data |
599 return data |
581 |
600 |
582 def _commit(self, files, text, user, date, match, force, lock, wlock, |
601 def _commit(self, files, text, user, date, match, force, lock, wlock, |
583 force_editor, p1, p2, extra, empty_ok): |
602 force_editor, p1, p2, extra, empty_ok): |