89 commands.optionalrepo += ' kwdemo' |
89 commands.optionalrepo += ' kwdemo' |
90 |
90 |
91 def utcdate(date): |
91 def utcdate(date): |
92 '''Returns hgdate in cvs-like UTC format.''' |
92 '''Returns hgdate in cvs-like UTC format.''' |
93 return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0])) |
93 return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0])) |
94 |
|
95 _kwtemplater = None |
|
96 |
94 |
97 class kwtemplater(object): |
95 class kwtemplater(object): |
98 ''' |
96 ''' |
99 Sets up keyword templates, corresponding keyword regex, and |
97 Sets up keyword templates, corresponding keyword regex, and |
100 provides keyword substitution functions. |
98 provides keyword substitution functions. |
171 '''Returns text with all keyword substitutions removed.''' |
169 '''Returns text with all keyword substitutions removed.''' |
172 if util.binary(data): |
170 if util.binary(data): |
173 return data |
171 return data |
174 return self.re_kw.sub(r'$\1$', data) |
172 return self.re_kw.sub(r'$\1$', data) |
175 |
173 |
176 |
|
177 # store original patch.patchfile.__init__ |
174 # store original patch.patchfile.__init__ |
178 _patchfile_init = patch.patchfile.__init__ |
175 _patchfile_init = patch.patchfile.__init__ |
179 |
176 |
180 def _kwpatchfile_init(self, ui, fname, missing=False): |
177 |
181 '''Monkeypatch/wrap patch.patchfile.__init__ to avoid |
178 def _iskwfile(f, link, kwt): |
182 rejects or conflicts due to expanded keywords in working dir.''' |
179 return not link(f) and kwt.matcher(f) |
183 _patchfile_init(self, ui, fname, missing=missing) |
|
184 |
|
185 if _kwtemplater.matcher(self.fname): |
|
186 # shrink keywords read from working dir |
|
187 kwshrunk = _kwtemplater.shrink(''.join(self.lines)) |
|
188 self.lines = kwshrunk.splitlines(True) |
|
189 |
|
190 |
|
191 def _iskwfile(f, link): |
|
192 return not link(f) and _kwtemplater.matcher(f) |
|
193 |
180 |
194 def _status(ui, repo, *pats, **opts): |
181 def _status(ui, repo, *pats, **opts): |
195 '''Bails out if [keyword] configuration is not active. |
182 '''Bails out if [keyword] configuration is not active. |
196 Returns status of working directory.''' |
183 Returns status of working directory.''' |
197 if _kwtemplater: |
184 if hasattr(repo, '_kwt'): |
198 files, match, anypats = cmdutil.matchpats(repo, pats, opts) |
185 files, match, anypats = cmdutil.matchpats(repo, pats, opts) |
199 return repo.status(files=files, match=match, list_clean=True) |
186 return repo.status(files=files, match=match, list_clean=True) |
200 if ui.configitems('keyword'): |
187 if ui.configitems('keyword'): |
201 raise util.Abort(_('[keyword] patterns cannot match')) |
188 raise util.Abort(_('[keyword] patterns cannot match')) |
202 raise util.Abort(_('no [keyword] patterns configured')) |
189 raise util.Abort(_('no [keyword] patterns configured')) |
339 modified, added, removed, deleted, unknown, ignored, clean = status |
326 modified, added, removed, deleted, unknown, ignored, clean = status |
340 files = modified + added + clean |
327 files = modified + added + clean |
341 if opts.get('untracked'): |
328 if opts.get('untracked'): |
342 files += unknown |
329 files += unknown |
343 files.sort() |
330 files.sort() |
344 kwfiles = [f for f in files if _iskwfile(f, repo._link)] |
331 kwfiles = [f for f in files if _iskwfile(f, repo._link, repo._kwt)] |
345 cwd = pats and repo.getcwd() or '' |
332 cwd = pats and repo.getcwd() or '' |
346 kwfstats = not opts.get('ignore') and (('K', kwfiles),) or () |
333 kwfstats = not opts.get('ignore') and (('K', kwfiles),) or () |
347 if opts.get('all') or opts.get('ignore'): |
334 if opts.get('all') or opts.get('ignore'): |
348 kwfstats += (('I', [f for f in files if f not in kwfiles]),) |
335 kwfstats += (('I', [f for f in files if f not in kwfiles]),) |
349 for char, filenames in kwfstats: |
336 for char, filenames in kwfstats: |
374 else: |
361 else: |
375 exc.append(pat) |
362 exc.append(pat) |
376 if not inc: |
363 if not inc: |
377 return |
364 return |
378 |
365 |
379 global _kwtemplater |
|
380 _kwtemplater = kwtemplater(ui, repo, inc, exc) |
|
381 |
|
382 class kwrepo(repo.__class__): |
366 class kwrepo(repo.__class__): |
383 def _wreadkwct(self, filename, expand, ctx, node): |
367 def _wreadkwct(self, filename, expand, ctx, node): |
384 '''Reads filename and returns tuple of data with keywords |
368 '''Reads filename and returns tuple of data with keywords |
385 expanded/shrunk and count of keywords (for _overwrite).''' |
369 expanded/shrunk and count of keywords (for _overwrite).''' |
386 data = super(kwrepo, self).wread(filename) |
370 data = super(kwrepo, self).wread(filename) |
387 return _kwtemplater.process(filename, data, expand, ctx, node) |
371 return self._kwt.process(filename, data, expand, ctx, node) |
388 |
372 |
389 def wread(self, filename): |
373 def wread(self, filename): |
390 data = super(kwrepo, self).wread(filename) |
374 data = super(kwrepo, self).wread(filename) |
391 if _kwtemplater.matcher(filename): |
375 if self._kwt.matcher(filename): |
392 return _kwtemplater.shrink(data) |
376 return self._kwt.shrink(data) |
393 return data |
377 return data |
394 |
378 |
395 def wwrite(self, filename, data, flags, overwrite=False): |
379 def wwrite(self, filename, data, flags, overwrite=False): |
396 if not overwrite and _kwtemplater.matcher(filename): |
380 if not overwrite and self._kwt.matcher(filename): |
397 data = _kwtemplater.expand(filename, data) |
381 data = self._kwt.expand(filename, data) |
398 super(kwrepo, self).wwrite(filename, data, flags) |
382 super(kwrepo, self).wwrite(filename, data, flags) |
399 |
383 |
400 def wwritedata(self, filename, data): |
384 def wwritedata(self, filename, data): |
401 if _kwtemplater.matcher(filename): |
385 if self._kwt.matcher(filename): |
402 data = _kwtemplater.expand(filename, data) |
386 data = self._kwt.expand(filename, data) |
403 return super(kwrepo, self).wwritedata(filename, data) |
387 return super(kwrepo, self).wwritedata(filename, data) |
404 |
388 |
405 def commit(self, files=None, text='', user=None, date=None, |
389 def commit(self, files=None, text='', user=None, date=None, |
406 match=util.always, force=False, force_editor=False, |
390 match=util.always, force=False, force_editor=False, |
407 p1=None, p2=None, extra={}): |
391 p1=None, p2=None, extra={}): |
442 repo.hook('commit', node=node, parent1=_p1, parent2=_p2) |
426 repo.hook('commit', node=node, parent1=_p1, parent2=_p2) |
443 return node |
427 return node |
444 finally: |
428 finally: |
445 del wlock, lock |
429 del wlock, lock |
446 |
430 |
|
431 kwt = kwrepo._kwt = kwtemplater(ui, repo, inc, exc) |
|
432 |
|
433 def kwpatchfile_init(self, ui, fname, missing=False): |
|
434 '''Monkeypatch/wrap patch.patchfile.__init__ to avoid |
|
435 rejects or conflicts due to expanded keywords in working dir.''' |
|
436 _patchfile_init(self, ui, fname, missing=missing) |
|
437 |
|
438 if kwt.matcher(self.fname): |
|
439 # shrink keywords read from working dir |
|
440 kwshrunk = kwt.shrink(''.join(self.lines)) |
|
441 self.lines = kwshrunk.splitlines(True) |
|
442 |
447 repo.__class__ = kwrepo |
443 repo.__class__ = kwrepo |
448 patch.patchfile.__init__ = _kwpatchfile_init |
444 patch.patchfile.__init__ = kwpatchfile_init |
449 |
445 |
450 |
446 |
451 cmdtable = { |
447 cmdtable = { |
452 'kwdemo': |
448 'kwdemo': |
453 (demo, |
449 (demo, |