113 def _kwpatchfile_init(self, ui, fname, missing=False): |
114 def _kwpatchfile_init(self, ui, fname, missing=False): |
114 '''Monkeypatch/wrap patch.patchfile.__init__ to avoid |
115 '''Monkeypatch/wrap patch.patchfile.__init__ to avoid |
115 rejects or conflicts due to expanded keywords in working dir.''' |
116 rejects or conflicts due to expanded keywords in working dir.''' |
116 _patchfile_init(self, ui, fname, missing=missing) |
117 _patchfile_init(self, ui, fname, missing=missing) |
117 # shrink keywords read from working dir |
118 # shrink keywords read from working dir |
118 self.lines = _kwtemplater.shrinklines(self.fname, self.lines) |
119 kwt = kwx['templater'] |
|
120 self.lines = kwt.shrinklines(self.fname, self.lines) |
119 |
121 |
120 def _kw_diff(repo, node1=None, node2=None, files=None, match=util.always, |
122 def _kw_diff(repo, node1=None, node2=None, files=None, match=util.always, |
121 fp=None, changes=None, opts=None): |
123 fp=None, changes=None, opts=None): |
122 # only expand if comparing against working dir |
124 # only expand if comparing against working dir |
123 if node2 is not None: |
125 if node2 is not None: |
124 _kwtemplater.matcher = util.never |
126 kwx['templater'].matcher = util.never |
125 if node1 is not None and node1 != repo.changectx().node(): |
127 if node1 is not None and node1 != repo.changectx().node(): |
126 _kwtemplater.restrict = True |
128 kwx['templater'].restrict = True |
127 _patch_diff(repo, node1=node1, node2=node2, files=files, match=match, |
129 _patch_diff(repo, node1=node1, node2=node2, files=files, match=match, |
128 fp=fp, changes=changes, opts=opts) |
130 fp=fp, changes=changes, opts=opts) |
129 |
131 |
130 def _kwweb_changeset(web, req, tmpl): |
132 def _kwweb_changeset(web, req, tmpl): |
131 '''Wraps webcommands.changeset turning off keyword expansion.''' |
133 '''Wraps webcommands.changeset turning off keyword expansion.''' |
132 _kwtemplater.matcher = util.never |
134 kwx['templater'].matcher = util.never |
133 return web.changeset(tmpl, web.changectx(req)) |
135 return web.changeset(tmpl, web.changectx(req)) |
134 |
136 |
135 def _kwweb_filediff(web, req, tmpl): |
137 def _kwweb_filediff(web, req, tmpl): |
136 '''Wraps webcommands.filediff turning off keyword expansion.''' |
138 '''Wraps webcommands.filediff turning off keyword expansion.''' |
137 _kwtemplater.matcher = util.never |
139 kwx['templater'].matcher = util.never |
138 return web.filediff(tmpl, web.filectx(req)) |
140 return web.filediff(tmpl, web.filectx(req)) |
139 |
141 |
140 def _kwdispatch_parse(ui, args): |
142 def _kwdispatch_parse(ui, args): |
141 '''Monkeypatch dispatch._parse to obtain running hg command.''' |
143 '''Monkeypatch dispatch._parse to obtain running hg command.''' |
142 global _cmd |
144 cmd, func, args, options, cmdoptions = _dispatch_parse(ui, args) |
143 _cmd, func, args, options, cmdoptions = _dispatch_parse(ui, args) |
145 kwx['hgcmd'] = cmd |
144 return _cmd, func, args, options, cmdoptions |
146 return cmd, func, args, options, cmdoptions |
145 |
147 |
146 # dispatch._parse is run before reposetup, so wrap it here |
148 # dispatch._parse is run before reposetup, so wrap it here |
147 dispatch._parse = _kwdispatch_parse |
149 dispatch._parse = _kwdispatch_parse |
148 |
150 |
149 |
151 |
269 Subclass of filelog to hook into its read, add, cmp methods. |
271 Subclass of filelog to hook into its read, add, cmp methods. |
270 Keywords are "stored" unexpanded, and processed on reading. |
272 Keywords are "stored" unexpanded, and processed on reading. |
271 ''' |
273 ''' |
272 def __init__(self, opener, path): |
274 def __init__(self, opener, path): |
273 super(kwfilelog, self).__init__(opener, path) |
275 super(kwfilelog, self).__init__(opener, path) |
|
276 self.kwt = kwx['templater'] |
274 self.path = path |
277 self.path = path |
275 |
278 |
276 def read(self, node): |
279 def read(self, node): |
277 '''Expands keywords when reading filelog.''' |
280 '''Expands keywords when reading filelog.''' |
278 data = super(kwfilelog, self).read(node) |
281 data = super(kwfilelog, self).read(node) |
279 return _kwtemplater.expand(self.path, node, data) |
282 return self.kwt.expand(self.path, node, data) |
280 |
283 |
281 def add(self, text, meta, tr, link, p1=None, p2=None): |
284 def add(self, text, meta, tr, link, p1=None, p2=None): |
282 '''Removes keyword substitutions when adding to filelog.''' |
285 '''Removes keyword substitutions when adding to filelog.''' |
283 text = _kwtemplater.shrink(self.path, text) |
286 text = self.kwt.shrink(self.path, text) |
284 return super(kwfilelog, self).add(text, meta, tr, link, p1=p1, p2=p2) |
287 return super(kwfilelog, self).add(text, meta, tr, link, p1=p1, p2=p2) |
285 |
288 |
286 def cmp(self, node, text): |
289 def cmp(self, node, text): |
287 '''Removes keyword substitutions for comparison.''' |
290 '''Removes keyword substitutions for comparison.''' |
288 text = _kwtemplater.shrink(self.path, text) |
291 text = self.kwt.shrink(self.path, text) |
289 if self.renamed(node): |
292 if self.renamed(node): |
290 t2 = super(kwfilelog, self).read(node) |
293 t2 = super(kwfilelog, self).read(node) |
291 return t2 != text |
294 return t2 != text |
292 return revlog.revlog.cmp(self, node, text) |
295 return revlog.revlog.cmp(self, node, text) |
293 |
296 |
294 def _status(ui, repo, *pats, **opts): |
297 def _status(ui, repo, kwt, *pats, **opts): |
295 '''Bails out if [keyword] configuration is not active. |
298 '''Bails out if [keyword] configuration is not active. |
296 Returns status of working directory.''' |
299 Returns status of working directory.''' |
297 if _kwtemplater: |
300 if kwt: |
298 files, match, anypats = cmdutil.matchpats(repo, pats, opts) |
301 files, match, anypats = cmdutil.matchpats(repo, pats, opts) |
299 return repo.status(files=files, match=match, list_clean=True) |
302 return repo.status(files=files, match=match, list_clean=True) |
300 if ui.configitems('keyword'): |
303 if ui.configitems('keyword'): |
301 raise util.Abort(_('[keyword] patterns cannot match')) |
304 raise util.Abort(_('[keyword] patterns cannot match')) |
302 raise util.Abort(_('no [keyword] patterns configured')) |
305 raise util.Abort(_('no [keyword] patterns configured')) |
303 |
306 |
304 def _kwfwrite(ui, repo, expand, *pats, **opts): |
307 def _kwfwrite(ui, repo, expand, *pats, **opts): |
305 '''Selects files and passes them to kwtemplater.overwrite.''' |
308 '''Selects files and passes them to kwtemplater.overwrite.''' |
306 status = _status(ui, repo, *pats, **opts) |
309 kwt = kwx['templater'] |
|
310 status = _status(ui, repo, kwt, *pats, **opts) |
307 modified, added, removed, deleted, unknown, ignored, clean = status |
311 modified, added, removed, deleted, unknown, ignored, clean = status |
308 if modified or added or removed or deleted: |
312 if modified or added or removed or deleted: |
309 raise util.Abort(_('outstanding uncommitted changes in given files')) |
313 raise util.Abort(_('outstanding uncommitted changes in given files')) |
310 wlock = lock = None |
314 wlock = lock = None |
311 try: |
315 try: |
312 wlock = repo.wlock() |
316 wlock = repo.wlock() |
313 lock = repo.lock() |
317 lock = repo.lock() |
314 _kwtemplater.overwrite(expand=expand, files=clean) |
318 kwt.overwrite(expand=expand, files=clean) |
315 finally: |
319 finally: |
316 del wlock, lock |
320 del wlock, lock |
317 |
321 |
318 |
322 |
319 def demo(ui, repo, *args, **opts): |
323 def demo(ui, repo, *args, **opts): |
411 |
415 |
412 Crosscheck which files in working directory are potential targets for |
416 Crosscheck which files in working directory are potential targets for |
413 keyword expansion. |
417 keyword expansion. |
414 That is, files matched by [keyword] config patterns but not symlinks. |
418 That is, files matched by [keyword] config patterns but not symlinks. |
415 ''' |
419 ''' |
416 status = _status(ui, repo, *pats, **opts) |
420 kwt = kwx['templater'] |
|
421 status = _status(ui, repo, kwt, *pats, **opts) |
417 modified, added, removed, deleted, unknown, ignored, clean = status |
422 modified, added, removed, deleted, unknown, ignored, clean = status |
418 files = modified + added + clean |
423 files = modified + added + clean |
419 if opts.get('untracked'): |
424 if opts.get('untracked'): |
420 files += unknown |
425 files += unknown |
421 files.sort() |
426 files.sort() |
422 wctx = repo.workingctx() |
427 wctx = repo.workingctx() |
423 islink = lambda p: 'l' in wctx.fileflags(p) |
428 islink = lambda p: 'l' in wctx.fileflags(p) |
424 kwfiles = [f for f in files if _kwtemplater.iskwfile(f, islink)] |
429 kwfiles = [f for f in files if kwt.iskwfile(f, islink)] |
425 cwd = pats and repo.getcwd() or '' |
430 cwd = pats and repo.getcwd() or '' |
426 kwfstats = not opts.get('ignore') and (('K', kwfiles),) or () |
431 kwfstats = not opts.get('ignore') and (('K', kwfiles),) or () |
427 if opts.get('all') or opts.get('ignore'): |
432 if opts.get('all') or opts.get('ignore'): |
428 kwfstats += (('I', [f for f in files if f not in kwfiles]),) |
433 kwfstats += (('I', [f for f in files if f not in kwfiles]),) |
429 for char, filenames in kwfstats: |
434 for char, filenames in kwfstats: |
469 else: |
472 else: |
470 exc.append(pat) |
473 exc.append(pat) |
471 if not inc: |
474 if not inc: |
472 return |
475 return |
473 |
476 |
474 _kwtemplater = kwtemplater(ui, repo, inc, exc) |
477 kwx['templater'] = kwt = kwtemplater(ui, repo, inc, exc) |
475 |
478 |
476 class kwrepo(repo.__class__): |
479 class kwrepo(repo.__class__): |
477 def file(self, f): |
480 def file(self, f): |
478 if f[0] == '/': |
481 if f[0] == '/': |
479 f = f[1:] |
482 f = f[1:] |
480 return kwfilelog(self.sopener, f) |
483 return kwfilelog(self.sopener, f) |
481 |
484 |
482 def wread(self, filename): |
485 def wread(self, filename): |
483 data = super(kwrepo, self).wread(filename) |
486 data = super(kwrepo, self).wread(filename) |
484 return _kwtemplater.wread(filename, data) |
487 return kwt.wread(filename, data) |
485 |
488 |
486 def commit(self, files=None, text='', user=None, date=None, |
489 def commit(self, files=None, text='', user=None, date=None, |
487 match=util.always, force=False, force_editor=False, |
490 match=util.always, force=False, force_editor=False, |
488 p1=None, p2=None, extra={}, empty_ok=False): |
491 p1=None, p2=None, extra={}, empty_ok=False): |
489 wlock = lock = None |
492 wlock = lock = None |