##// END OF EJS Templates
run-tests: removed some underscores (coding style)
run-tests: removed some underscores (coding style)

File last commit:

r8089:67efe5e3 default
r8097:eea3c1a8 default
Show More
keyword.py
541 lines | 20.3 KiB | text/x-python | PythonLexer
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 # keyword.py - $Keyword$ expansion for Mercurial
#
Christian Ebert
keyword: fix some doc strings; update copyright
r5831 # Copyright 2007, 2008 Christian Ebert <blacktrash@gmx.net>
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 #
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
#
# $Id$
#
# Keyword expansion hack against the grain of a DSCM
#
# There are many good reasons why this is not needed in a distributed
# SCM, still it may be useful in very small projects based on single
Martin Geisler
keyword: word-wrap help texts at 70 characters
r7993 # files (like LaTeX packages), that are mostly addressed to an
# audience not running a version control system.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 #
# For in-depth discussion refer to
# <http://www.selenic.com/mercurial/wiki/index.cgi/KeywordPlan>.
#
# Keyword expansion is based on Mercurial's changeset template mappings.
#
# Binary files are not touched.
#
# Setup in hgrc:
#
# [extensions]
# # enable extension
# hgext.keyword =
#
# Files to act upon/ignore are specified in the [keyword] section.
# Customized keyword template mappings in the [keywordmaps] section.
#
# Run "hg help keyword" and "hg kwdemo" to get info on configuration.
'''keyword expansion in local repositories
Martin Geisler
keyword: word-wrap help texts at 70 characters
r7993 This extension expands RCS/CVS-like or self-customized $Keywords$ in
tracked text files selected by your configuration.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Martin Geisler
keyword: word-wrap help texts at 70 characters
r7993 Keywords are only expanded in local repositories and not stored in the
change history. The mechanism can be regarded as a convenience for the
current user or for archive distribution.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Martin Geisler
keyword: word-wrap help texts at 70 characters
r7993 Configuration is done in the [keyword] and [keywordmaps] sections of
hgrc files.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Example:
[keyword]
# expand keywords in every python file except those matching "x*"
**.py =
x* = ignore
Note: the more specific you are in your filename patterns
Martin Geisler
expand "repo" to "repository" in help texts
r8027 the less you lose speed in huge repositories.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
For [keywordmaps] template mapping and expansion demonstration and
control run "hg kwdemo".
An additional date template filter {date|utcdate} is provided.
Martin Geisler
keyword: word-wrap help texts at 70 characters
r7993 The default template mappings (view with "hg kwdemo -d") can be
replaced with customized keywords and templates. Again, run "hg
kwdemo" to control the results of your config changes.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Before changing/disabling active keywords, run "hg kwshrink" to avoid
Martin Geisler
keyword: word-wrap help texts at 70 characters
r7993 the risk of inadvertedly storing expanded keywords in the change
history.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
To force expansion after enabling it, or a configuration change, run
"hg kwexpand".
Martin Geisler
keyword: word-wrap help texts at 70 characters
r7993 Also, when committing with the record extension or using mq's qrecord,
be aware that keywords cannot be updated. Again, run "hg kwexpand" on
the files in question to update keyword expansions after all changes
have been checked in.
Christian Ebert
keyword: support mq; handle (q)record more gracefully...
r5884
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 Expansions spanning more than one line and incremental expansions,
like CVS' $Log$, are not supported. A keyword template map
"Log = {desc}" expands to the first line of the changeset description.
'''
Matt Mackall
extensions: use new wrapper functions
r7216 from mercurial import commands, cmdutil, dispatch, filelog, revlog, extensions
Matt Mackall
templates: move filters to their own module...
r5976 from mercurial import patch, localrepo, templater, templatefilters, util
Christian Ebert
keyword: no expansion in web diffs...
r6072 from mercurial.hgweb import webcommands
Joel Rosdahl
Expand import * to allow Pyflakes to find problems
r6211 from mercurial.node import nullid, hex
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 from mercurial.i18n import _
Christian Ebert
keyword: avoid os import by using util.splitpath
r6069 import re, shutil, tempfile, time
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
commands.optionalrepo += ' kwdemo'
Christian Ebert
keyword: nokwcommands, restricted string variables at top level...
r6024 # hg commands that do not act on keywords
Christian Ebert
keyword: disable expansion for annotate...
r6667 nokwcommands = ('add addremove annotate bundle copy export grep incoming init'
Christian Ebert
keyword: add verify to nokwcommands after refactor in e79a8f36c2a5...
r6867 ' log outgoing push rename rollback tip verify'
Christian Ebert
keyword: add glog to nokwcommands
r6082 ' convert email glog')
Christian Ebert
keyword: nokwcommands, restricted string variables at top level...
r6024
Christian Ebert
keyword: detect restricted commands thru variable
r5961 # hg commands that trigger expansion only when writing to working dir,
# not when reading filelog, and unexpand when reading from working dir
Christian Ebert
keyword: avoid additional conflicts during merge/resolve...
r6933 restricted = 'merge record resolve qfold qimport qnew qpush qrefresh qrecord'
Christian Ebert
keyword: detect restricted commands thru variable
r5961
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 def utcdate(date):
'''Returns hgdate in cvs-like UTC format.'''
return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0]))
Christian Ebert
keyword: make main class and hg command accessible...
r6115 # make keyword tools accessible
Christian Ebert
keyword: collect filename patterns, wrap dispatch._parse in uisetup...
r6502 kwtools = {'templater': None, 'hgcmd': '', 'inc': [], 'exc': ['.hg*']}
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
class kwtemplater(object):
'''
Sets up keyword templates, corresponding keyword regex, and
provides keyword substitution functions.
'''
templates = {
'Revision': '{node|short}',
'Author': '{author|user}',
'Date': '{date|utcdate}',
'RCSFile': '{file|basename},v',
'Source': '{root}/{file},v',
'Id': '{file|basename},v {node|short} {date|utcdate} {author|user}',
'Header': '{root}/{file},v {node|short} {date|utcdate} {author|user}',
}
Christian Ebert
keyword: collect filename patterns, wrap dispatch._parse in uisetup...
r6502 def __init__(self, ui, repo):
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 self.ui = ui
self.repo = repo
Christian Ebert
keyword: collect filename patterns, wrap dispatch._parse in uisetup...
r6502 self.matcher = util.matcher(repo.root,
inc=kwtools['inc'], exc=kwtools['exc'])[1]
Christian Ebert
keyword: make main class and hg command accessible...
r6115 self.restrict = kwtools['hgcmd'] in restricted.split()
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
kwmaps = self.ui.configitems('keywordmaps')
if kwmaps: # override default templates
Christian Ebert
keyword: compact setting of optional arguments
r6504 kwmaps = [(k, templater.parsestring(v, False))
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 for (k, v) in kwmaps]
self.templates = dict(kwmaps)
escaped = map(re.escape, self.templates.keys())
kwpat = r'\$(%s)(: [^$\n\r]*? )??\$' % '|'.join(escaped)
self.re_kw = re.compile(kwpat)
Matt Mackall
templates: move filters to their own module...
r5976 templatefilters.filters['utcdate'] = utcdate
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 self.ct = cmdutil.changeset_templater(self.ui, self.repo,
Jim Correia
add --git option to commands supporting --patch (log, incoming, history, tip)...
r7762 False, None, '', False)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Dirkjan Ochtman
keyword: be more efficient about ctx usage
r7375 def substitute(self, data, path, ctx, subfunc):
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 '''Replaces keywords in data with expanded template.'''
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 def kwsub(mobj):
kw = mobj.group(1)
self.ct.use_template(self.templates[kw])
self.ui.pushbuffer()
Dirkjan Ochtman
keyword: be more efficient about ctx usage
r7375 self.ct.show(ctx, root=self.repo.root, file=path)
Christian Ebert
keyword: split line continuation in 2 steps (style)
r6023 ekw = templatefilters.firstline(self.ui.popbuffer())
return '$%s: %s $' % (kw, ekw)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 return subfunc(kwsub, data)
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 def expand(self, path, node, data):
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 '''Returns data with keywords expanded.'''
Bryan O'Sullivan
Get rid of reimplementations of util.binary
r6508 if not self.restrict and self.matcher(path) and not util.binary(data):
Dirkjan Ochtman
keyword: be more efficient about ctx usage
r7375 ctx = self.repo.filectx(path, fileid=node).changectx()
return self.substitute(data, path, ctx, self.re_kw.sub)
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 return data
Matt Mackall
manifest: remove execf/linkf methods
r6749 def iskwfile(self, path, flagfunc):
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 '''Returns true if path matches [keyword] pattern
and is not a symbolic link.
Caveat: localrepository._link fails on Windows.'''
Matt Mackall
manifest: remove execf/linkf methods
r6749 return self.matcher(path) and not 'l' in flagfunc(path)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Christian Ebert
keyword: make overwrite() arguments mandatory
r6505 def overwrite(self, node, expand, files):
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 '''Overwrites selected files expanding/shrinking keywords.'''
Christian Ebert
keyword: move common code out of commit condition
r7378 ctx = self.repo[node]
mf = ctx.manifest()
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 if node is not None: # commit
files = [f for f in ctx.files() if f in mf]
notify = self.ui.debug
else: # kwexpand/kwshrink
notify = self.ui.note
Matt Mackall
manifest: remove execf/linkf methods
r6749 candidates = [f for f in files if self.iskwfile(f, ctx.flags)]
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 if candidates:
self.restrict = True # do not expand when reading
for f in candidates:
fp = self.repo.file(f)
data = fp.read(mf[f])
Bryan O'Sullivan
Get rid of reimplementations of util.binary
r6508 if util.binary(data):
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 continue
if expand:
Dirkjan Ochtman
keyword: be more efficient about ctx usage
r7375 if node is None:
ctx = self.repo.filectx(f, fileid=mf[f]).changectx()
data, found = self.substitute(data, f, ctx,
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 self.re_kw.subn)
else:
found = self.re_kw.search(data)
if found:
Wagner Bruna
keyword, i18n: avoid untranslated strings as message parameters
r8089 if expand:
msg = _('overwriting %s expanding keywords\n')
else:
msg = _('overwriting %s shrinking keywords\n')
notify(msg % f)
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 self.repo.wwrite(f, data, mf.flags(f))
self.repo.dirstate.normal(f)
self.restrict = False
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 def shrinktext(self, text):
'''Unconditionally removes all keyword substitutions from text.'''
return self.re_kw.sub(r'$\1$', text)
def shrink(self, fname, text):
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 '''Returns text with all keyword substitutions removed.'''
Bryan O'Sullivan
Get rid of reimplementations of util.binary
r6508 if self.matcher(fname) and not util.binary(text):
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 return self.shrinktext(text)
return text
def shrinklines(self, fname, lines):
'''Returns lines with keyword substitutions removed.'''
if self.matcher(fname):
text = ''.join(lines)
Bryan O'Sullivan
Get rid of reimplementations of util.binary
r6508 if not util.binary(text):
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 return self.shrinktext(text).splitlines(True)
return lines
def wread(self, fname, data):
'''If in restricted mode returns data read from wdir with
keyword substitutions removed.'''
return self.restrict and self.shrink(fname, data) or data
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
class kwfilelog(filelog.filelog):
'''
Subclass of filelog to hook into its read, add, cmp methods.
Keywords are "stored" unexpanded, and processed on reading.
'''
Christian Ebert
keyword: privatize remaining monkeypatches by moving them into reposetup...
r6503 def __init__(self, opener, kwt, path):
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 super(kwfilelog, self).__init__(opener, path)
Christian Ebert
keyword: privatize remaining monkeypatches by moving them into reposetup...
r6503 self.kwt = kwt
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 self.path = path
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
def read(self, node):
'''Expands keywords when reading filelog.'''
data = super(kwfilelog, self).read(node)
Christian Ebert
keyword: make main class and hg command accessible...
r6115 return self.kwt.expand(self.path, node, data)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
def add(self, text, meta, tr, link, p1=None, p2=None):
'''Removes keyword substitutions when adding to filelog.'''
Christian Ebert
keyword: make main class and hg command accessible...
r6115 text = self.kwt.shrink(self.path, text)
Christian Ebert
keyword: compact setting of optional arguments
r6504 return super(kwfilelog, self).add(text, meta, tr, link, p1, p2)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
def cmp(self, node, text):
'''Removes keyword substitutions for comparison.'''
Christian Ebert
keyword: make main class and hg command accessible...
r6115 text = self.kwt.shrink(self.path, text)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 if self.renamed(node):
t2 = super(kwfilelog, self).read(node)
return t2 != text
return revlog.revlog.cmp(self, node, text)
Matt Mackall
status: clean up all users for unknown files
r6760 def _status(ui, repo, kwt, unknown, *pats, **opts):
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 '''Bails out if [keyword] configuration is not active.
Returns status of working directory.'''
Christian Ebert
keyword: make main class and hg command accessible...
r6115 if kwt:
Matt Mackall
walk: remove remaining users of cmdutils.matchpats
r6582 matcher = cmdutil.match(repo, pats, opts)
Matt Mackall
status: clean up all users for unknown files
r6760 return repo.status(match=matcher, unknown=unknown, clean=True)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 if ui.configitems('keyword'):
raise util.Abort(_('[keyword] patterns cannot match'))
raise util.Abort(_('no [keyword] patterns configured'))
def _kwfwrite(ui, repo, expand, *pats, **opts):
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 '''Selects files and passes them to kwtemplater.overwrite.'''
Christian Ebert
keyword: mimic cmdutil.bail_if_changed even more...
r6672 if repo.dirstate.parents()[1] != nullid:
raise util.Abort(_('outstanding uncommitted merge'))
Christian Ebert
keyword: make main class and hg command accessible...
r6115 kwt = kwtools['templater']
Matt Mackall
status: clean up all users for unknown files
r6760 status = _status(ui, repo, kwt, False, *pats, **opts)
modified, added, removed, deleted = status[:4]
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 if modified or added or removed or deleted:
Christian Ebert
keyword: mimic cmdutil.bail_if_changed even more...
r6672 raise util.Abort(_('outstanding uncommitted changes'))
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 wlock = lock = None
try:
wlock = repo.wlock()
lock = repo.lock()
Matt Mackall
status: clean up all users for unknown files
r6760 kwt.overwrite(None, expand, status[6])
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 finally:
del wlock, lock
def demo(ui, repo, *args, **opts):
'''print [keywordmaps] configuration and an expansion example
Martin Geisler
keyword: word-wrap help texts at 70 characters
r7993 Show current, custom, or default keyword template maps and their
expansion.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Martin Geisler
keyword: word-wrap help texts at 70 characters
r7993 Extend current configuration by specifying maps as arguments and
optionally by reading from an additional hgrc file.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Override current keyword template maps with "default" option.
'''
def demostatus(stat):
ui.status(_('\n\t%s\n') % stat)
def demoitems(section, items):
ui.write('[%s]\n' % section)
for k, v in items:
ui.write('%s = %s\n' % (k, v))
msg = 'hg keyword config and expansion example'
kwstatus = 'current'
fn = 'demo.txt'
branchname = 'demobranch'
tmpdir = tempfile.mkdtemp('', 'kwdemo.')
Martin Geisler
expand "repo" to "repository" in help texts
r8027 ui.note(_('creating temporary repository at %s\n') % tmpdir)
Christian Ebert
keyword: compact setting of optional arguments
r6504 repo = localrepo.localrepository(ui, tmpdir, True)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 ui.setconfig('keyword', fn, '')
if args or opts.get('rcfile'):
kwstatus = 'custom'
if opts.get('rcfile'):
ui.readconfig(opts.get('rcfile'))
if opts.get('default'):
kwstatus = 'default'
kwmaps = kwtemplater.templates
if ui.configitems('keywordmaps'):
# override maps from optional rcfile
Christian Ebert
keyword: improve use of dicts...
r5946 for k, v in kwmaps.iteritems():
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 ui.setconfig('keywordmaps', k, v)
elif args:
# simulate hgrc parsing
rcmaps = ['[keywordmaps]\n'] + [a + '\n' for a in args]
fp = repo.opener('hgrc', 'w')
fp.writelines(rcmaps)
fp.close()
ui.readconfig(repo.join('hgrc'))
if not opts.get('default'):
kwmaps = dict(ui.configitems('keywordmaps')) or kwtemplater.templates
Christian Ebert
keyword: collect filename patterns, wrap dispatch._parse in uisetup...
r6502 uisetup(ui)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 reposetup(ui, repo)
for k, v in ui.configitems('extensions'):
if k.endswith('keyword'):
extension = '%s = %s' % (k, v)
break
demostatus('config using %s keyword template maps' % kwstatus)
ui.write('[extensions]\n%s\n' % extension)
demoitems('keyword', ui.configitems('keyword'))
Christian Ebert
keyword: improve use of dicts...
r5946 demoitems('keywordmaps', kwmaps.iteritems())
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 keywords = '$' + '$\n$'.join(kwmaps.keys()) + '$\n'
repo.wopener(fn, 'w').write(keywords)
repo.add([fn])
path = repo.wjoin(fn)
ui.note(_('\n%s keywords written to %s:\n') % (kwstatus, path))
ui.note(keywords)
ui.note('\nhg -R "%s" branch "%s"\n' % (tmpdir, branchname))
# silence branch command if not verbose
quiet = ui.quiet
Christian Ebert
keyword: clean up quiet setting in kwdemo and adding of untracked kwfiles
r5825 ui.quiet = not ui.verbose
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 commands.branch(ui, repo, branchname)
ui.quiet = quiet
for name, cmd in ui.configitems('hooks'):
if name.split('.', 1)[0].find('commit') > -1:
repo.ui.setconfig('hooks', name, '')
ui.note(_('unhooked all commit hooks\n'))
ui.note('hg -R "%s" ci -m "%s"\n' % (tmpdir, msg))
repo.commit(text=msg)
Christian Ebert
keyword: do not shadow builtin format (detected by pychecker)
r7417 fmt = ui.verbose and ' in %s' % path or ''
demostatus('%s keywords expanded%s' % (kwstatus, fmt))
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 ui.write(repo.wread(fn))
Martin Geisler
expand "repo" to "repository" in help texts
r8027 ui.debug(_('\nremoving temporary repository %s\n') % tmpdir)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 shutil.rmtree(tmpdir, ignore_errors=True)
def expand(ui, repo, *pats, **opts):
'''expand keywords in working directory
Run after (re)enabling keyword expansion.
kwexpand refuses to run if given files contain local changes.
'''
# 3rd argument sets expansion to True
_kwfwrite(ui, repo, True, *pats, **opts)
def files(ui, repo, *pats, **opts):
'''print files currently configured for keyword expansion
Martin Geisler
keyword: word-wrap help texts at 70 characters
r7993 Crosscheck which files in working directory are potential targets
for keyword expansion. That is, files matched by [keyword] config
patterns but not symlinks.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 '''
Christian Ebert
keyword: make main class and hg command accessible...
r6115 kwt = kwtools['templater']
Matt Mackall
status: clean up all users for unknown files
r6760 status = _status(ui, repo, kwt, opts.get('untracked'), *pats, **opts)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 modified, added, removed, deleted, unknown, ignored, clean = status
Matt Mackall
util: add sort helper
r6762 files = util.sort(modified + added + clean + unknown)
Matt Mackall
use repo[changeid] to get a changectx
r6747 wctx = repo[None]
Matt Mackall
manifest: remove execf/linkf methods
r6749 kwfiles = [f for f in files if kwt.iskwfile(f, wctx.flags)]
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 cwd = pats and repo.getcwd() or ''
kwfstats = not opts.get('ignore') and (('K', kwfiles),) or ()
if opts.get('all') or opts.get('ignore'):
kwfstats += (('I', [f for f in files if f not in kwfiles]),)
for char, filenames in kwfstats:
Christian Ebert
keyword: do not shadow builtin format (detected by pychecker)
r7417 fmt = (opts.get('all') or ui.verbose) and '%s %%s\n' % char or '%s\n'
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 for f in filenames:
Christian Ebert
keyword: do not shadow builtin format (detected by pychecker)
r7417 ui.write(fmt % repo.pathto(f, cwd))
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
def shrink(ui, repo, *pats, **opts):
'''revert expanded keywords in working directory
Martin Geisler
keyword: word-wrap help texts at 70 characters
r7993 Run before changing/disabling active keywords or if you experience
problems with "hg import" or "hg merge".
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
kwshrink refuses to run if given files contain local changes.
'''
# 3rd argument sets expansion to False
_kwfwrite(ui, repo, False, *pats, **opts)
Christian Ebert
keyword: collect filename patterns, wrap dispatch._parse in uisetup...
r6502 def uisetup(ui):
'''Collects [keyword] config in kwtools.
Monkeypatches dispatch._parse if needed.'''
for pat, opt in ui.configitems('keyword'):
if opt != 'ignore':
kwtools['inc'].append(pat)
else:
kwtools['exc'].append(pat)
if kwtools['inc']:
Matt Mackall
extensions: use new wrapper functions
r7216 def kwdispatch_parse(orig, ui, args):
Christian Ebert
keyword: collect filename patterns, wrap dispatch._parse in uisetup...
r6502 '''Monkeypatch dispatch._parse to obtain running hg command.'''
Matt Mackall
extensions: use new wrapper functions
r7216 cmd, func, args, options, cmdoptions = orig(ui, args)
Christian Ebert
keyword: collect filename patterns, wrap dispatch._parse in uisetup...
r6502 kwtools['hgcmd'] = cmd
return cmd, func, args, options, cmdoptions
Matt Mackall
extensions: use new wrapper functions
r7216 extensions.wrapfunction(dispatch, '_parse', kwdispatch_parse)
Christian Ebert
keyword: collect filename patterns, wrap dispatch._parse in uisetup...
r6502
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 def reposetup(ui, repo):
'''Sets up repo as kwrepo for keyword substitution.
Overrides file method to return kwfilelog instead of filelog
if file matches user configuration.
Wraps commit to overwrite configured files with updated
keyword substitutions.
Christian Ebert
keyword: privatize remaining monkeypatches by moving them into reposetup...
r6503 Monkeypatches patch and webcommands.'''
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Matt Mackall
bundlerepo: reintroduce dirstate
r7853 try:
if (not repo.local() or not kwtools['inc']
or kwtools['hgcmd'] in nokwcommands.split()
or '.hg' in util.splitpath(repo.root)
or repo._url.startswith('bundle:')):
return
except AttributeError:
pass
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Christian Ebert
keyword: collect filename patterns, wrap dispatch._parse in uisetup...
r6502 kwtools['templater'] = kwt = kwtemplater(ui, repo)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
class kwrepo(repo.__class__):
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 def file(self, f):
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 if f[0] == '/':
f = f[1:]
Christian Ebert
keyword: privatize remaining monkeypatches by moving them into reposetup...
r6503 return kwfilelog(self.sopener, kwt, f)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Christian Ebert
keyword: support mq; handle (q)record more gracefully...
r5884 def wread(self, filename):
data = super(kwrepo, self).wread(filename)
Christian Ebert
keyword: make main class and hg command accessible...
r6115 return kwt.wread(filename, data)
Christian Ebert
keyword: support mq; handle (q)record more gracefully...
r5884
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 def commit(self, files=None, text='', user=None, date=None,
Matt Mackall
match: remove files arg from repo.status and friends
r6603 match=None, force=False, force_editor=False,
Christian Ebert
keyword: add empty_ok argument to kwrepo.commit
r6022 p1=None, p2=None, extra={}, empty_ok=False):
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 wlock = lock = None
_p1 = _p2 = None
try:
wlock = self.wlock()
lock = self.lock()
# store and postpone commit hooks
Christian Ebert
keyword: improve use of dicts...
r5946 commithooks = {}
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 for name, cmd in ui.configitems('hooks'):
if name.split('.', 1)[0] == 'commit':
Christian Ebert
keyword: improve use of dicts...
r5946 commithooks[name] = cmd
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 ui.setconfig('hooks', name, None)
if commithooks:
# store parents for commit hook environment
if p1 is None:
_p1, _p2 = repo.dirstate.parents()
else:
_p1, _p2 = p1, p2 or nullid
_p1 = hex(_p1)
if _p2 == nullid:
_p2 = ''
else:
_p2 = hex(_p2)
Christian Ebert
keyword: compact setting of optional arguments
r6504 n = super(kwrepo, self).commit(files, text, user, date, match,
force, force_editor, p1, p2,
extra, empty_ok)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
# restore commit hooks
Christian Ebert
keyword: improve use of dicts...
r5946 for name, cmd in commithooks.iteritems():
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 ui.setconfig('hooks', name, cmd)
Christian Ebert
keyword: compact setting of optional arguments
r6504 if n is not None:
Christian Ebert
keyword: make overwrite() arguments mandatory
r6505 kwt.overwrite(n, True, None)
Christian Ebert
keyword: compact setting of optional arguments
r6504 repo.hook('commit', node=n, parent1=_p1, parent2=_p2)
return n
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 finally:
del wlock, lock
Christian Ebert
keyword: privatize remaining monkeypatches by moving them into reposetup...
r6503 # monkeypatches
Patrick Mezard
patch: pass an opener to patchfile
r7391 def kwpatchfile_init(orig, self, ui, fname, opener, missing=False):
Christian Ebert
keyword: privatize remaining monkeypatches by moving them into reposetup...
r6503 '''Monkeypatch/wrap patch.patchfile.__init__ to avoid
rejects or conflicts due to expanded keywords in working dir.'''
Patrick Mezard
patch: pass an opener to patchfile
r7391 orig(self, ui, fname, opener, missing)
Christian Ebert
keyword: privatize remaining monkeypatches by moving them into reposetup...
r6503 # shrink keywords read from working dir
self.lines = kwt.shrinklines(self.fname, self.lines)
Dirkjan Ochtman
patch: turn patch.diff() into a generator...
r7308 def kw_diff(orig, repo, node1=None, node2=None, match=None, changes=None,
opts=None):
Christian Ebert
keyword: privatize remaining monkeypatches by moving them into reposetup...
r6503 '''Monkeypatch patch.diff to avoid expansion except when
comparing against working dir.'''
if node2 is not None:
kwt.matcher = util.never
Matt Mackall
use repo[changeid] to get a changectx
r6747 elif node1 is not None and node1 != repo['.'].node():
Christian Ebert
keyword: privatize remaining monkeypatches by moving them into reposetup...
r6503 kwt.restrict = True
Dirkjan Ochtman
patch: turn patch.diff() into a generator...
r7308 return orig(repo, node1, node2, match, changes, opts)
Christian Ebert
keyword: disable expansion for annotate...
r6667
Matt Mackall
extensions: use new wrapper functions
r7216 def kwweb_skip(orig, web, req, tmpl):
'''Wraps webcommands.x turning off keyword expansion.'''
Christian Ebert
keyword: privatize remaining monkeypatches by moving them into reposetup...
r6503 kwt.matcher = util.never
Matt Mackall
extensions: use new wrapper functions
r7216 return orig(web, req, tmpl)
Christian Ebert
keyword: privatize remaining monkeypatches by moving them into reposetup...
r6503
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 repo.__class__ = kwrepo
Christian Ebert
keyword: privatize remaining monkeypatches by moving them into reposetup...
r6503
Matt Mackall
extensions: use new wrapper functions
r7216 extensions.wrapfunction(patch.patchfile, '__init__', kwpatchfile_init)
extensions.wrapfunction(patch, 'diff', kw_diff)
for c in 'annotate changeset rev filediff diff'.split():
extensions.wrapfunction(webcommands, c, kwweb_skip)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
cmdtable = {
'kwdemo':
(demo,
[('d', 'default', None, _('show default keyword template maps')),
('f', 'rcfile', [], _('read maps from rcfile'))],
_('hg kwdemo [-d] [-f RCFILE] [TEMPLATEMAP]...')),
'kwexpand': (expand, commands.walkopts,
_('hg kwexpand [OPTION]... [FILE]...')),
'kwfiles':
(files,
[('a', 'all', None, _('show keyword status flags of all files')),
('i', 'ignore', None, _('show files excluded from expansion')),
('u', 'untracked', None, _('additionally show untracked files')),
] + commands.walkopts,
_('hg kwfiles [OPTION]... [FILE]...')),
'kwshrink': (shrink, commands.walkopts,
_('hg kwshrink [OPTION]... [FILE]...')),
}