##// END OF EJS Templates
localrepo.status: move fixup concatenation inside if block for clarity...
localrepo.status: move fixup concatenation inside if block for clarity clean += fixup only makes sense if fixup is not empty; it should be inside the "if fixup" test.

File last commit:

r11616:fda0e478 default
r11669:c47cb319 default
Show More
keyword.py
576 lines | 21.7 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: update copyright
r10653 # Copyright 2007-2010 Christian Ebert <blacktrash@gmx.net>
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 #
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 #
# $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
Dirkjan Ochtman
change wiki/bts URLs to point to new hostname
r8936 # <http://mercurial.selenic.com/wiki/KeywordPlan>.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 #
# Keyword expansion is based on Mercurial's changeset template mappings.
#
# Binary files are not touched.
#
# 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.
Cédric Duval
extensions: improve the consistency of synopses...
r8894 '''expand keywords in tracked files
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Martin Geisler
keyword: wrap docstrings at 70 characters
r9264 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: wrap docstrings at 70 characters
r9264 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
Christian Ebert
keyword: offer svn-like default keywordmaps...
r11214 Configuration is done in the [keyword], [keywordset] and [keywordmaps]
sections of hgrc files.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Martin Geisler
commands: use minirst parser when displaying help
r9157 Example::
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
[keyword]
# expand keywords in every python file except those matching "x*"
**.py =
x* = ignore
Christian Ebert
keyword: offer svn-like default keywordmaps...
r11214 [keywordset]
# prefer svn- over cvs-like default keywordmaps
svn = True
Martin Geisler
keyword: wrap docstrings at 70 characters
r9264 NOTE: the more specific you are in your filename patterns the less you
lose speed in huge repositories.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Martin Geisler
keyword: wrap docstrings at 70 characters
r9264 For [keywordmaps] template mapping and expansion demonstration and
Martin Geisler
Use hg role in help strings
r10973 control run :hg:`kwdemo`. See :hg:`help templates` for a list of
Christian Ebert
keyword: reference templating help, add utcdate filter example
r9307 available templates and filters.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Christian Ebert
keyword: add 2 svn-like date filters...
r11213 Three additional date template filters are provided::
utcdate "2006/09/18 15:13:13"
svnutcdate "2006-09-18 15:13:13Z"
svnisodate "2006-09-18 08:13:13 -700 (Mon, 18 Sep 2006)"
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Martin Geisler
Use hg role in help strings
r10973 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
Martin Geisler
Use hg role in help strings
r10973 Before changing/disabling active keywords, run :hg:`kwshrink` to avoid
Martin Geisler
keyword: wrap docstrings at 70 characters
r9264 the risk of inadvertently storing expanded keywords in the change
history.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Martin Geisler
keyword: wrap docstrings at 70 characters
r9264 To force expansion after enabling it, or a configuration change, run
Martin Geisler
Use hg role in help strings
r10973 :hg:`kwexpand`.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Martin Geisler
keyword: wrap docstrings at 70 characters
r9264 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.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 '''
Matt Mackall
extensions: use new wrapper functions
r7216 from mercurial import commands, cmdutil, dispatch, filelog, revlog, extensions
Matt Mackall
match: change all users of util.matcher to match.match
r8566 from mercurial import patch, localrepo, templater, templatefilters, util, match
Christian Ebert
keyword: no expansion in web diffs...
r6072 from mercurial.hgweb import webcommands
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 from mercurial.i18n import _
Christian Ebert
keyword: use util.datestr for utcdate filter, expose through variable
r9308 import re, shutil, tempfile
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: remove mq commands from restricted list...
r11044 restricted = 'merge record qrecord resolve transplant'
Christian Ebert
keyword: detect restricted commands thru variable
r5961
Christian Ebert
keyword: support (q)record...
r11045 # commands using dorecord
recordcommands = 'record qrecord'
Christian Ebert
keyword: support extensions using dorecord, e.g. crecord...
r11168 # names of extensions using dorecord
recordextensions = 'record'
Christian Ebert
keyword: support (q)record...
r11045
Christian Ebert
keyword: add 2 svn-like date filters...
r11213 # date like in cvs' $Date
Christian Ebert
keyword: fix utcdate filter...
r10332 utcdate = lambda x: util.datestr((x[0], 0), '%Y/%m/%d %H:%M:%S')
Christian Ebert
keyword: add 2 svn-like date filters...
r11213 # date like in svn's $Date
svnisodate = lambda x: util.datestr(x, '%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)')
# date like in svn's $Id
svnutcdate = lambda x: util.datestr((x[0], 0), '%Y-%m-%d %H:%M:%SZ')
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
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
Christian Ebert
keyword: offer svn-like default keywordmaps...
r11214 def _defaultkwmaps(ui):
'''Returns default keywordmaps according to keywordset configuration.'''
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 templates = {
'Revision': '{node|short}',
'Author': '{author|user}',
Christian Ebert
keyword: offer svn-like default keywordmaps...
r11214 }
kwsets = ({
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 'Date': '{date|utcdate}',
Christian Ebert
keyword: the CVS keyword is $RCSfile$, not $RCSFile$...
r9943 'RCSfile': '{file|basename},v',
timeless
keyword: clarify object of backwards compatibility
r9950 'RCSFile': '{file|basename},v', # kept for backwards compatibility
# with hg-keyword
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 '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: offer svn-like default keywordmaps...
r11214 }, {
'Date': '{date|svnisodate}',
'Id': '{file|basename},v {node|short} {date|svnutcdate} {author|user}',
'LastChangedRevision': '{node|short}',
'LastChangedBy': '{author|user}',
'LastChangedDate': '{date|svnisodate}',
})
templates.update(kwsets[ui.configbool('keywordset', 'svn')])
return templates
class kwtemplater(object):
'''
Sets up keyword templates, corresponding keyword regex, and
provides keyword substitution functions.
'''
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 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: rename matcher() to match() mimicking changes in main
r8638 self.match = match.match(repo.root, '', [],
kwtools['inc'], kwtools['exc'])
Christian Ebert
keyword: make main class and hg command accessible...
r6115 self.restrict = kwtools['hgcmd'] in restricted.split()
Christian Ebert
keyword: support (q)record...
r11045 self.record = kwtools['hgcmd'] in recordcommands.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: collect kwmaps using a generator expression...
r9081 self.templates = dict((k, templater.parsestring(v, False))
for k, v in kwmaps)
Christian Ebert
keyword: offer svn-like default keywordmaps...
r11214 else:
self.templates = _defaultkwmaps(self.ui)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 escaped = map(re.escape, self.templates.keys())
kwpat = r'\$(%s)(: [^$\n\r]*? )??\$' % '|'.join(escaped)
self.re_kw = re.compile(kwpat)
Christian Ebert
keyword: add extra datefilters in a single update call
r11616 templatefilters.filters.update({'utcdate': utcdate,
'svnisodate': svnisodate,
'svnutcdate': svnutcdate})
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)
Christian Ebert
keyword: make the templater a local variable...
r10894 ct = cmdutil.changeset_templater(self.ui, self.repo,
False, None, '', False)
ct.use_template(self.templates[kw])
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 self.ui.pushbuffer()
Christian Ebert
keyword: make the templater a local variable...
r10894 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.'''
Christian Ebert
keyword: rename matcher() to match() mimicking changes in main
r8638 if not self.restrict and self.match(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.'''
Christian Ebert
keyword: rename matcher() to match() mimicking changes in main
r8638 return self.match(path) and not 'l' in flagfunc(path)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Christian Ebert
keyword: pass context to kwtemplater.overwrite...
r11320 def overwrite(self, ctx, candidates, iswctx, expand):
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 '''Overwrites selected files expanding/shrinking keywords.'''
Christian Ebert
keyword: retrieve added and modified files from commitctx
r11253 if self.record:
Christian Ebert
keyword: postpone manifest calculation in kwtemplater.overwrite...
r11350 candidates = [f for f in ctx.files() if f in ctx]
Christian Ebert
keyword: 1 variable name for overwriting candidates
r10712 candidates = [f for f in candidates if self.iskwfile(f, ctx.flags)]
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 if candidates:
Christian Ebert
keyword: pass context to kwtemplater.overwrite...
r11320 self.restrict = True # do not expand when reading
Christian Ebert
keyword: postpone manifest calculation in kwtemplater.overwrite...
r11350 mf = ctx.manifest()
Christian Ebert
keyword: set overwrite message only once, not for each file
r8098 msg = (expand and _('overwriting %s expanding keywords\n')
or _('overwriting %s shrinking keywords\n'))
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 for f in candidates:
Christian Ebert
keyword: simplify record switch in kwtemplater.overwrite...
r11087 if not self.record:
Christian Ebert
keyword: support (q)record...
r11045 data = self.repo.file(f).read(mf[f])
else:
data = self.repo.wread(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:
Christian Ebert
keyword: pass context to kwtemplater.overwrite...
r11320 if iswctx:
Dirkjan Ochtman
keyword: be more efficient about ctx usage
r7375 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:
Christian Ebert
keyword: do not customize ui.note() when overwriting...
r10711 self.ui.note(msg % f)
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 self.repo.wwrite(f, data, mf.flags(f))
Christian Ebert
keyword: pass context to kwtemplater.overwrite...
r11320 if iswctx:
Christian Ebert
keyword: make repo.commit use a custom commitctx wrapper...
r8996 self.repo.dirstate.normal(f)
Christian Ebert
keyword: force dirstate normal when all changes in a file are recorded...
r11252 elif self.record:
self.repo.dirstate.normallookup(f)
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 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.'''
Christian Ebert
keyword: rename matcher() to match() mimicking changes in main
r8638 if self.match(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.'''
Christian Ebert
keyword: rename matcher() to match() mimicking changes in main
r8638 if self.match(fname):
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 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)
Christian Ebert
keyword: kwfiles --unknown instead of --untracked...
r9491 def _status(ui, repo, kwt, *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:
Christian Ebert
keyword: kwfiles --unknown instead of --untracked...
r9491 return repo.status(match=cmdutil.match(repo, pats, opts), clean=True,
Christian Ebert
keyword: remove deprecated options
r10652 unknown=opts.get('unknown') or opts.get('all'))
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: pass context to kwtemplater.overwrite...
r11320 wctx = repo[None]
if len(wctx.parents()) > 1:
Christian Ebert
keyword: mimic cmdutil.bail_if_changed even more...
r6672 raise util.Abort(_('outstanding uncommitted merge'))
Christian Ebert
keyword: make main class and hg command accessible...
r6115 kwt = kwtools['templater']
Christian Ebert
keyword: remove spurious locks, improve handling of wlock...
r10604 wlock = repo.wlock()
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 try:
Christian Ebert
keyword: remove spurious locks, improve handling of wlock...
r10604 status = _status(ui, repo, kwt, *pats, **opts)
modified, added, removed, deleted, unknown, ignored, clean = status
if modified or added or removed or deleted:
raise util.Abort(_('outstanding uncommitted changes'))
Christian Ebert
keyword: pass context to kwtemplater.overwrite...
r11320 kwt.overwrite(wctx, clean, True, expand)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 finally:
Christian Ebert
keyword: remove spurious locks, improve handling of wlock...
r10604 wlock.release()
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
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
timeless
keyword: improve English
r8763 expansions.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Christian Ebert
keyword: refactor kwdemo and make output translatable...
r9281 Extend the current configuration by specifying maps as arguments
and using -f/--rcfile to source an external hgrc file.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Christian Ebert
keyword: refactor kwdemo and make output translatable...
r9281 Use -d/--default to disable current configuration.
Christian Ebert
keyword: reference templating help, add utcdate filter example
r9307
Martin Geisler
Use our custom hg reStructuredText role some more...
r11193 See :hg:`help templates` for information on templates and filters.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 '''
def demoitems(section, items):
ui.write('[%s]\n' % section)
Martin Geisler
keyword: sort demo output to ensure deterministic output
r9942 for k, v in sorted(items):
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 ui.write('%s = %s\n' % (k, v))
fn = 'demo.txt'
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, '')
Christian Ebert
keyword: refactor kwdemo and make output translatable...
r9281
uikwmaps = ui.configitems('keywordmaps')
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 if args or opts.get('rcfile'):
Christian Ebert
keyword: refactor kwdemo and make output translatable...
r9281 ui.status(_('\n\tconfiguration using custom keyword template maps\n'))
if uikwmaps:
ui.status(_('\textending current template maps\n'))
if opts.get('default') or not uikwmaps:
ui.status(_('\toverriding default template maps\n'))
if opts.get('rcfile'):
ui.readconfig(opts.get('rcfile'))
if 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'))
kwmaps = dict(ui.configitems('keywordmaps'))
elif opts.get('default'):
ui.status(_('\n\tconfiguration using default keyword template maps\n'))
Christian Ebert
keyword: offer svn-like default keywordmaps...
r11214 kwmaps = _defaultkwmaps(ui)
Christian Ebert
keyword: refactor kwdemo and make output translatable...
r9281 if uikwmaps:
ui.status(_('\tdisabling current template maps\n'))
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)
Christian Ebert
keyword: refactor kwdemo and make output translatable...
r9281 else:
ui.status(_('\n\tconfiguration using current keyword template maps\n'))
Christian Ebert
keyword: offer svn-like default keywordmaps...
r11214 kwmaps = dict(uikwmaps) or _defaultkwmaps(ui)
Christian Ebert
keyword: refactor kwdemo and make output translatable...
r9281
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)
Christian Ebert
keyword: do not bother about detecting extension path in demo...
r10714 ui.write('[extensions]\nkeyword =\n')
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 demoitems('keyword', ui.configitems('keyword'))
Christian Ebert
keyword: improve use of dicts...
r5946 demoitems('keywordmaps', kwmaps.iteritems())
Martin Geisler
keyword: sort demo output to ensure deterministic output
r9942 keywords = '$' + '$\n$'.join(sorted(kwmaps.keys())) + '$\n'
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 repo.wopener(fn, 'w').write(keywords)
Dirkjan Ochtman
move working dir/dirstate methods from localrepo to workingctx
r11303 repo[None].add([fn])
Christian Ebert
keyword: make kwdemo less verbose...
r10713 ui.note(_('\nkeywords written to %s:\n') % fn)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 ui.note(keywords)
Christian Ebert
keyword: make kwdemo less verbose...
r10713 repo.dirstate.setbranch('demobranch')
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].find('commit') > -1:
repo.ui.setconfig('hooks', name, '')
Christian Ebert
keyword: mark improved demo commit message for translation...
r10499 msg = _('hg keyword configuration and expansion example')
Christian Ebert
keyword: make kwdemo less verbose...
r10713 ui.note("hg ci -m '%s'\n" % msg)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 repo.commit(text=msg)
Christian Ebert
keyword: refactor kwdemo and make output translatable...
r9281 ui.status(_('\n\tkeywords expanded\n'))
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 ui.write(repo.wread(fn))
shutil.rmtree(tmpdir, ignore_errors=True)
def expand(ui, repo, *pats, **opts):
timeless
keyword: improve English
r8763 '''expand keywords in the working directory
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
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):
Christian Ebert
keyword: improve help for kwfiles...
r8957 '''show files configured for keyword expansion
Christian Ebert
keyword: improve help for kwfiles
r8950
Martin Geisler
keyword: wrap docstrings at 70 characters
r9264 List which files in the working directory are matched by the
[keyword] configuration patterns.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Martin Geisler
keyword: wrap docstrings at 70 characters
r9264 Useful to prevent inadvertent keyword expansion and to speed up
execution by including only files that are actual candidates for
expansion.
Christian Ebert
keyword: improve help for kwfiles
r8950
Martin Geisler
Use hg role in help strings
r10973 See :hg:`help keyword` on how to construct patterns both for
Martin Geisler
keyword: wrap docstrings at 70 characters
r9264 inclusion and exclusion of files.
Christian Ebert
keyword: improve help for kwfiles...
r8957
Christian Ebert
keyword: uppercase short option for kwfiles --all, like hg status -A...
r9494 With -A/--all and -v/--verbose the codes used to show the status
Martin Geisler
keyword: wrap docstrings at 70 characters
r9264 of files are::
Christian Ebert
keyword: reformat kwfiles help for minirst parser
r9195
K = keyword expansion candidate
Christian Ebert
keyword: kwfiles --unknown instead of --untracked...
r9491 k = keyword expansion candidate (not tracked)
Christian Ebert
keyword: reformat kwfiles help for minirst parser
r9195 I = ignored
Christian Ebert
keyword: kwfiles --unknown instead of --untracked...
r9491 i = ignored (not tracked)
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']
Christian Ebert
keyword: kwfiles --unknown instead of --untracked...
r9491 status = _status(ui, repo, kwt, *pats, **opts)
Christian Ebert
keyword: make kwfiles -u show untracked files only (like status)...
r9493 cwd = pats and repo.getcwd() or ''
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 modified, added, removed, deleted, unknown, ignored, clean = status
Christian Ebert
keyword: make kwfiles -u show untracked files only (like status)...
r9493 files = []
Christian Ebert
keyword: remove deprecated options
r10652 if not opts.get('unknown') or opts.get('all'):
Christian Ebert
keyword: make kwfiles -u show untracked files only (like status)...
r9493 files = sorted(modified + added + clean)
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
keyword: kwfiles --unknown instead of --untracked...
r9491 kwunknown = [f for f in unknown if kwt.iskwfile(f, wctx.flags)]
Christian Ebert
keyword: make kwfiles -u show untracked files only (like status)...
r9493 if not opts.get('ignore') or opts.get('all'):
showfiles = kwfiles, kwunknown
else:
showfiles = [], []
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 if opts.get('all') or opts.get('ignore'):
Christian Ebert
keyword: make kwfiles -u show untracked files only (like status)...
r9493 showfiles += ([f for f in files if f not in kwfiles],
[f for f in unknown if f not in kwunknown])
for char, filenames in zip('KkIi', showfiles):
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):
timeless
keyword: improve English
r8763 '''revert expanded keywords in the working directory
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Martin Geisler
keyword: word-wrap help texts at 70 characters
r7993 Run before changing/disabling active keywords or if you experience
Martin Geisler
Use hg role in help strings
r10973 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
keyword: eliminate potential reference cycles from kwrepo...
r9096 def commit(self, *args, **opts):
Christian Ebert
keyword: make repo.commit use a custom commitctx wrapper...
r8996 # use custom commitctx for user commands
# other extensions can still wrap repo.commitctx directly
Christian Ebert
keyword: eliminate potential reference cycles from kwrepo...
r9096 self.commitctx = self.kwcommitctx
try:
Christian Ebert
keyword: do not postpone commit hooks...
r10495 return super(kwrepo, self).commit(*args, **opts)
Christian Ebert
keyword: eliminate potential reference cycles from kwrepo...
r9096 finally:
del self.commitctx
Christian Ebert
keyword: make repo.commit use a custom commitctx wrapper...
r8996
def kwcommitctx(self, ctx, error=False):
Christian Ebert
keyword: remove spurious locks, improve handling of wlock...
r10604 n = super(kwrepo, self).commitctx(ctx, error)
# no lock needed, only called from repo.commit() which already locks
Christian Ebert
keyword: support (q)record...
r11045 if not kwt.record:
Christian Ebert
keyword: pass context to kwtemplater.overwrite...
r11320 kwt.overwrite(self[n], sorted(ctx.added() + ctx.modified()),
False, True)
Christian Ebert
keyword: remove spurious locks, improve handling of wlock...
r10604 return n
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Christian Ebert
keyword: privatize remaining monkeypatches by moving them into reposetup...
r6503 # monkeypatches
Christian Ebert
keyword: break overlong line
r9013 def kwpatchfile_init(orig, self, ui, fname, opener,
Augie Fackler
keyword: monkeypatch patch so that optional args can be passed as kwargs
r10967 missing=False, eolmode=None):
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.'''
Augie Fackler
keyword: monkeypatch patch so that optional args can be passed as kwargs
r10967 orig(self, ui, fname, opener, missing, eolmode)
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:
Christian Ebert
keyword: rename matcher() to match() mimicking changes in main
r8638 kwt.match = 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: rename matcher() to match() mimicking changes in main
r8638 kwt.match = 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
keyword: support (q)record...
r11045 def kw_dorecord(orig, ui, repo, commitfunc, *pats, **opts):
'''Wraps record.dorecord expanding keywords after recording.'''
wlock = repo.wlock()
try:
# record returns 0 even when nothing has changed
# therefore compare nodes before and after
ctx = repo['.']
ret = orig(ui, repo, commitfunc, *pats, **opts)
Christian Ebert
keyword: pass context to kwtemplater.overwrite...
r11320 recordctx = repo['.']
if ctx != recordctx:
kwt.overwrite(recordctx, None, False, True)
Christian Ebert
keyword: support (q)record...
r11045 return ret
finally:
wlock.release()
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)
Christian Ebert
keyword: do not monkeypatch diff when in restricted mode...
r10116 if not kwt.restrict:
extensions.wrapfunction(patch, 'diff', kw_diff)
Matt Mackall
extensions: use new wrapper functions
r7216 for c in 'annotate changeset rev filediff diff'.split():
extensions.wrapfunction(webcommands, c, kwweb_skip)
Christian Ebert
keyword: support extensions using dorecord, e.g. crecord...
r11168 for name in recordextensions.split():
try:
record = extensions.find(name)
extensions.wrapfunction(record, 'dorecord', kw_dorecord)
except KeyError:
pass
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
cmdtable = {
'kwdemo':
(demo,
[('d', 'default', None, _('show default keyword template maps')),
FUJIWARA Katsunori
help: show value requirement and multiple occurrence of options...
r11321 ('f', 'rcfile', '',
_('read maps from rcfile'), _('FILE'))],
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 _('hg kwdemo [-d] [-f RCFILE] [TEMPLATEMAP]...')),
'kwexpand': (expand, commands.walkopts,
_('hg kwexpand [OPTION]... [FILE]...')),
'kwfiles':
(files,
Christian Ebert
keyword: uppercase short option for kwfiles --all, like hg status -A...
r9494 [('A', 'all', None, _('show keyword status flags of all files')),
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 ('i', 'ignore', None, _('show files excluded from expansion')),
Christian Ebert
keyword: make kwfiles -u show untracked files only (like status)...
r9493 ('u', 'unknown', None, _('only show unknown (not tracked) files')),
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 ] + commands.walkopts,
_('hg kwfiles [OPTION]... [FILE]...')),
'kwshrink': (shrink, commands.walkopts,
_('hg kwshrink [OPTION]... [FILE]...')),
}