##// END OF EJS Templates
tests: fix test-match.py on Python3...
tests: fix test-match.py on Python3 # skip-blame just b prefixes Differential Revision: https://phab.mercurial-scm.org/D5835

File last commit:

r40256:c7ffc53f default
r41671:4dd07bf8 default
Show More
keyword.py
817 lines | 29.0 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 year
r23723 # Copyright 2007-2015 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$
#
Mads Kiilerich
fix trivial spelling errors
r17424 # Keyword expansion hack against the grain of a Distributed SCM
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 #
# 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
Matt Mackall
urls: bulk-change primary website URLs
r26421 # <https://mercurial-scm.org/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.
#
timeless
keyword: use single quotes in use warning
r29969 # Run 'hg help keyword' and 'hg kwdemo' to get info on configuration.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
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: explain file-wise expansion in help
r12203 Keywords expand to the changeset data pertaining to the latest change
relative to the working directory parent of each file.
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
Christian Ebert
Use more note admonitions in help texts
r12390 .. note::
Simon Heimberg
documentation: add an extra newline after note directive...
r19997
Christian Ebert
Use more note admonitions in help texts
r12390 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
Martin Geisler
keyword: convert a verbatim block to a field list
r13885 Three additional date template filters are provided:
Christian Ebert
keyword: add 2 svn-like date filters...
r11213
Martin Geisler
keyword: convert a verbatim block to a field list
r13885 :``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
Christian Ebert
keyword: s/config/configuration/ in help
r13025 :hg:`kwdemo` to control the results of your configuration changes.
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Christian Ebert
keyword: update documentation for kwshrink...
r13270 Before changing/disabling active keywords, you must run :hg:`kwshrink`
to avoid 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 '''
Christian Ebert
keyword: use absolute_import
r28321
from __future__ import absolute_import
import os
import re
FUJIWARA Katsunori
keyword: make wrapped repository and kwtemplater refer to each other...
r33067 import weakref
Christian Ebert
keyword: use absolute_import
r28321
Yuya Nishihara
py3: move up symbol imports to enforce import-checker rules...
r29205 from mercurial.i18n import _
Christian Ebert
keyword: no expansion in web diffs...
r6072 from mercurial.hgweb import webcommands
Christian Ebert
keyword: use absolute_import
r28321
from mercurial import (
cmdutil,
context,
dispatch,
error,
extensions,
filelog,
localrepo,
Yuya Nishihara
cmdutil: drop aliases for logcmdutil functions (API)...
r35906 logcmdutil,
Christian Ebert
keyword: use absolute_import
r28321 match,
patch,
pathutil,
Pulkit Goyal
py3: handle keyword arguments in hgext/keyword.py...
r35002 pycompat,
FUJIWARA Katsunori
keyword: use templatefilter to mark a function as template filter...
r28694 registrar,
Christian Ebert
keyword: use absolute_import
r28321 scmutil,
templatefilters,
Yuya Nishihara
keyword: declare input type of date filters as date...
r37245 templateutil,
Christian Ebert
keyword: use absolute_import
r28321 util,
)
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 from mercurial.utils import (
dateutil,
stringutil,
)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Martin Geisler
keyword: use cmdutil.command decorator
r14300 cmdtable = {}
Yuya Nishihara
registrar: move cmdutil.command to registrar module (API)...
r32337 command = registrar.command(cmdtable)
Augie Fackler
extensions: change magic "shipped with hg" string...
r29841 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
Augie Fackler
extensions: document that `testedwith = 'internal'` is special...
r25186 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
# be specifying the version(s) of Mercurial they are tested with, or
# leave the attribute unspecified.
Augie Fackler
extensions: change magic "shipped with hg" string...
r29841 testedwith = 'ships-with-hg-core'
Martin Geisler
keyword: use cmdutil.command decorator
r14300
Christian Ebert
keyword: nokwcommands, restricted string variables at top level...
r6024 # hg commands that do not act on keywords
Christian Ebert
keyword: support copy and rename...
r12626 nokwcommands = ('add addremove annotate bundle export grep incoming init log'
' outgoing push tip verify convert email glog')
Christian Ebert
keyword: nokwcommands, restricted string variables at top level...
r6024
FUJIWARA Katsunori
keyword: make comparison webcommand suppress keyword expansion...
r33065 # webcommands that do not act on keywords
nokwwebcommands = ('annotate changeset rev filediff diff comparison')
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
FUJIWARA Katsunori
keyword: suppress keyword expansion while 'hg unshelve' for internal merge...
r21703 restricted = ('merge kwexpand kwshrink record qrecord resolve transplant'
FUJIWARA Katsunori
keyword: suppress keyword expansion while 'hg fetch' for internal merge...
r21708 ' unshelve rebase graft backout histedit fetch')
Christian Ebert
keyword: detect restricted commands thru variable
r5961
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: colorize hg kwfiles output
r13078 colortable = {
'kwfiles.enabled': 'green bold',
Christian Ebert
keyword: make kwfiles show deleted files configured for expansion
r13079 'kwfiles.deleted': 'cyan bold underline',
Christian Ebert
keyword: colorize hg kwfiles output
r13078 'kwfiles.enabledunknown': 'green',
'kwfiles.ignored': 'bold',
'kwfiles.ignoredunknown': 'none'
}
FUJIWARA Katsunori
keyword: use templatefilter to mark a function as template filter...
r28694 templatefilter = registrar.templatefilter()
Boris Feld
configitems: register the 'keywordset.svn' config
r34501 configtable = {}
configitem = registrar.configitem(configtable)
configitem('keywordset', 'svn',
default=False,
)
Christian Ebert
keyword: add 2 svn-like date filters...
r11213 # date like in cvs' $Date
Yuya Nishihara
keyword: declare input type of date filters as date...
r37245 @templatefilter('utcdate', intype=templateutil.date)
def utcdate(date):
FUJIWARA Katsunori
keyword: use templatefilter to mark a function as template filter...
r28694 '''Date. Returns a UTC-date in this format: "2009/08/18 11:00:13".
Christian Ebert
keyword: docstrings for additional date filters
r13633 '''
Boris Feld
util: extract all date-related utils in utils/dateutil module...
r36625 dateformat = '%Y/%m/%d %H:%M:%S'
Yuya Nishihara
keyword: declare input type of date filters as date...
r37245 return dateutil.datestr((date[0], 0), dateformat)
Christian Ebert
keyword: add 2 svn-like date filters...
r11213 # date like in svn's $Date
Yuya Nishihara
keyword: declare input type of date filters as date...
r37245 @templatefilter('svnisodate', intype=templateutil.date)
def svnisodate(date):
FUJIWARA Katsunori
keyword: use templatefilter to mark a function as template filter...
r28694 '''Date. Returns a date in this format: "2009-08-18 13:00:13
Christian Ebert
keyword: docstrings for additional date filters
r13633 +0200 (Tue, 18 Aug 2009)".
'''
Yuya Nishihara
keyword: declare input type of date filters as date...
r37245 return dateutil.datestr(date, '%Y-%m-%d %H:%M:%S %1%2 (%a, %d %b %Y)')
Christian Ebert
keyword: add 2 svn-like date filters...
r11213 # date like in svn's $Id
Yuya Nishihara
keyword: declare input type of date filters as date...
r37245 @templatefilter('svnutcdate', intype=templateutil.date)
def svnutcdate(date):
FUJIWARA Katsunori
keyword: use templatefilter to mark a function as template filter...
r28694 '''Date. Returns a UTC-date in this format: "2009-08-18
Christian Ebert
keyword: docstrings for additional date filters
r13633 11:00:13Z".
'''
Boris Feld
util: extract all date-related utils in utils/dateutil module...
r36625 dateformat = '%Y-%m-%d %H:%M:%SZ'
Yuya Nishihara
keyword: declare input type of date filters as date...
r37245 return dateutil.datestr((date[0], 0), dateformat)
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
FUJIWARA Katsunori
keyword: use _keywordkwt of repository instead of kwtools['templater']...
r33070 kwtools = {'hgcmd': ''}
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114
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
Christian Ebert
keyword: refactor kwtemplater.overwrite()...
r12625 def _shrinktext(text, subfunc):
'''Helper for keyword expansion removal in text.
Depending on subfunc also returns number of substitutions.'''
Pulkit Goyal
py3: make regexes in hgext/keyword.py bytes...
r39462 return subfunc(br'$\1$', text)
Christian Ebert
keyword: refactor kwtemplater.overwrite()...
r12625
Christian Ebert
keyword: code cleanup...
r12723 def _preselect(wstatus, changed):
Mads Kiilerich
fix trivial spelling errors
r17424 '''Retrieves modified and added files from a working directory state
Christian Ebert
keyword: code cleanup...
r12723 and returns the subset of each contained in given changed files
retrieved from a change context.'''
Martin von Zweigbergk
keyword: access status fields by name rather than index
r22918 modified = [f for f in wstatus.modified if f in changed]
added = [f for f in wstatus.added if f in changed]
Christian Ebert
keyword: code cleanup...
r12723 return modified, added
Christian Ebert
keyword: refactor kwtemplater.overwrite()...
r12625
Christian Ebert
keyword: offer svn-like default keywordmaps...
r11214 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: move collecting of [keyword] patterns to reposetup (issue2303)...
r11678 def __init__(self, ui, repo, inc, exc):
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 self.ui = ui
FUJIWARA Katsunori
keyword: make wrapped repository and kwtemplater refer to each other...
r33067 self._repo = weakref.ref(repo)
Christian Ebert
keyword: move collecting of [keyword] patterns to reposetup (issue2303)...
r11678 self.match = match.match(repo.root, '', [], inc, exc)
Christian Ebert
keyword: make main class and hg command accessible...
r6115 self.restrict = kwtools['hgcmd'] in restricted.split()
Christian Ebert
keyword: rename kwt.record attribute to kwt.postcommit...
r16809 self.postcommit = False
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
kwmaps = self.ui.configitems('keywordmaps')
if kwmaps: # override default templates
Yuya Nishihara
templater: remove noop calls of parsestring(s, quoted=False) (API)...
r24987 self.templates = dict(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
FUJIWARA Katsunori
keyword: make wrapped repository and kwtemplater refer to each other...
r33067 @property
def repo(self):
return self._repo()
Christian Ebert
keyword: turn regexes and escaped keywords into a propertycache
r12926 @util.propertycache
def escape(self):
'''Returns bar-separated and escaped keywords.'''
Augie Fackler
cleanup: migrate from re.escape to stringutil.reescape...
r38494 return '|'.join(map(stringutil.reescape, self.templates.keys()))
Christian Ebert
keyword: turn regexes and escaped keywords into a propertycache
r12926
@util.propertycache
def rekw(self):
'''Returns regex for unexpanded keywords.'''
Pulkit Goyal
py3: make regexes in hgext/keyword.py bytes...
r39462 return re.compile(br'\$(%s)\$' % self.escape)
Christian Ebert
keyword: turn regexes and escaped keywords into a propertycache
r12926
@util.propertycache
def rekwexp(self):
'''Returns regex for expanded keywords.'''
Pulkit Goyal
py3: make regexes in hgext/keyword.py bytes...
r39462 return re.compile(br'\$(%s): [^$\n\r]*? \$' % self.escape)
Christian Ebert
keyword: turn regexes and escaped keywords into a propertycache
r12926
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)
Yuya Nishihara
cmdutil: drop aliases for logcmdutil functions (API)...
r35906 ct = logcmdutil.maketemplater(self.ui, self.repo,
Yuya Nishihara
cmdutil: factor out helper to create changeset_templater with literal template...
r32837 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: function to look up changectx for expansion...
r12920 def linkctx(self, path, fileid):
'''Similar to filelog.linkrev, but returns a changectx.'''
return self.repo.filectx(path, fileid=fileid).changectx()
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.'''
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 if (not self.restrict and self.match(path)
and not stringutil.binary(data)):
Christian Ebert
keyword: function to look up changectx for expansion...
r12920 ctx = self.linkctx(path, node)
Christian Ebert
keyword: turn regexes and escaped keywords into a propertycache
r12926 return self.substitute(data, path, ctx, self.rekw.sub)
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 return data
Christian Ebert
keyword: make iskwfile() a weeding method in lieu of a boolean...
r12627 def iskwfile(self, cand, ctx):
'''Returns subset of candidates which are configured for keyword
Christian Ebert
keyword: correct grammar in iskwfile docstring
r15324 expansion but are not symbolic links.'''
Brodie Rao
cleanup: "not x in y" -> "x not in y"
r16686 return [f for f in cand if self.match(f) and 'l' not in ctx.flags(f)]
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Christian Ebert
keyword: enforce subn method via boolean switch...
r12685 def overwrite(self, ctx, candidates, lookup, expand, rekw=False):
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 '''Overwrites selected files expanding/shrinking keywords.'''
Christian Ebert
keyword: rename kwt.record attribute to kwt.postcommit...
r16809 if self.restrict or lookup or self.postcommit: # exclude kw_copy
Christian Ebert
keyword: make iskwfile() a weeding method in lieu of a boolean...
r12627 candidates = self.iskwfile(candidates, ctx)
Christian Ebert
keyword: refactor kwtemplater.overwrite()...
r12625 if not candidates:
return
Christian Ebert
keyword: fix regressions introduced in d87f3ff904ba...
r12844 kwcmd = self.restrict and lookup # kwexpand/kwshrink
Christian Ebert
keyword: refactor kwtemplater.overwrite()...
r12625 if self.restrict or expand and lookup:
Christian Ebert
keyword: postpone manifest calculation in kwtemplater.overwrite...
r11350 mf = ctx.manifest()
Christian Ebert
keyword: avoid x = a and b or c
r15030 if self.restrict or rekw:
re_kw = self.rekw
else:
re_kw = self.rekwexp
if expand:
msg = _('overwriting %s expanding keywords\n')
else:
msg = _('overwriting %s shrinking keywords\n')
Christian Ebert
keyword: refactor kwtemplater.overwrite()...
r12625 for f in candidates:
if self.restrict:
data = self.repo.file(f).read(mf[f])
else:
data = self.repo.wread(f)
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 if stringutil.binary(data):
Christian Ebert
keyword: refactor kwtemplater.overwrite()...
r12625 continue
if expand:
Christian Ebert
keyword: handle resolve to either parent...
r23622 parents = ctx.parents()
Christian Ebert
keyword: refactor kwtemplater.overwrite()...
r12625 if lookup:
Christian Ebert
keyword: use wopener(..., atomictemp=True) to overwrite
r15083 ctx = self.linkctx(f, mf[f])
Christian Ebert
keyword: handle resolve to either parent...
r23622 elif self.restrict and len(parents) > 1:
# merge commit
# in case of conflict f is in modified state during
# merge, even if f does not differ from f in parent
for p in parents:
if f in p and not p[f].cmp(ctx[f]):
ctx = p[f].changectx()
break
Christian Ebert
keyword: use wopener(..., atomictemp=True) to overwrite
r15083 data, found = self.substitute(data, f, ctx, re_kw.subn)
Christian Ebert
keyword: refactor kwtemplater.overwrite()...
r12625 elif self.restrict:
Christian Ebert
keyword: turn regexes and escaped keywords into a propertycache
r12926 found = re_kw.search(data)
Christian Ebert
keyword: refactor kwtemplater.overwrite()...
r12625 else:
Christian Ebert
keyword: turn regexes and escaped keywords into a propertycache
r12926 data, found = _shrinktext(data, re_kw.subn)
Christian Ebert
keyword: refactor kwtemplater.overwrite()...
r12625 if found:
self.ui.note(msg % f)
Angel Ezquerra
localrepo: remove all external users of localrepo.wopener...
r23879 fp = self.repo.wvfs(f, "wb", atomictemp=True)
Christian Ebert
keyword: use wopener(..., atomictemp=True) to overwrite
r15083 fp.write(data)
fp.close()
Christian Ebert
keyword: fix regressions introduced in d87f3ff904ba...
r12844 if kwcmd:
Christian Ebert
keyword: refactor kwtemplater.overwrite()...
r12625 self.repo.dirstate.normal(f)
Christian Ebert
keyword: rename kwt.record attribute to kwt.postcommit...
r16809 elif self.postcommit:
Christian Ebert
keyword: refactor kwtemplater.overwrite()...
r12625 self.repo.dirstate.normallookup(f)
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114
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.'''
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 if self.match(fname) and not stringutil.binary(text):
Christian Ebert
keyword: turn regexes and escaped keywords into a propertycache
r12926 return _shrinktext(text, self.rekwexp.sub)
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 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)
Yuya Nishihara
stringutil: bulk-replace call sites to point to new module...
r37102 if not stringutil.binary(text):
Christian Ebert
keyword: turn regexes and escaped keywords into a propertycache
r12926 return _shrinktext(text, self.rekwexp.sub).splitlines(True)
Christian Ebert
keyword: move expand/shrink decisions into kwtemplater...
r6114 return lines
def wread(self, fname, data):
'''If in restricted mode returns data read from wdir with
keyword substitutions removed.'''
Christian Ebert
keyword: avoid x = a and b or c
r15030 if self.restrict:
return self.shrink(fname, data)
return 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: disable expansion in kwfilelog.read() if file renamed in node...
r12628 if self.renamed(node):
return data
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
keyword: disable expansion in kwfilelog.read() if file renamed in node...
r12628 return super(kwfilelog, self).cmp(node, text)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Christian Ebert
keyword: reuse already present working contexts for match...
r14835 def _status(ui, repo, wctx, 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:
Pulkit Goyal
py3: handle keyword arguments in hgext/keyword.py...
r35002 opts = pycompat.byteskwargs(opts)
Christian Ebert
keyword: reuse already present working contexts for match...
r14835 return repo.status(match=scmutil.match(wctx, 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'):
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('[keyword] patterns cannot match'))
raise error.Abort(_('no [keyword] patterns configured'))
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
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:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('outstanding uncommitted merge'))
FUJIWARA Katsunori
keyword: use _keywordkwt of repository instead of kwtools['templater']...
r33070 kwt = getattr(repo, '_keywordkwt', None)
Bryan O'Sullivan
with: use context manager for wlock in _kwfwrite
r27815 with repo.wlock():
Christian Ebert
keyword: reuse already present working contexts for match...
r14835 status = _status(ui, repo, wctx, kwt, *pats, **opts)
Martin von Zweigbergk
keyword: access status fields by name rather than index
r22918 if status.modified or status.added or status.removed or status.deleted:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('outstanding uncommitted changes'))
Martin von Zweigbergk
keyword: access status fields by name rather than index
r22918 kwt.overwrite(wctx, status.clean, True, expand)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Martin Geisler
keyword: use cmdutil.command decorator
r14300 @command('kwdemo',
[('d', 'default', None, _('show default keyword template maps')),
('f', 'rcfile', '',
_('read maps from rcfile'), _('FILE'))],
Gregory Szorc
keyword: define optionalrepo in command decorator
r21776 _('hg kwdemo [-d] [-f RCFILE] [TEMPLATEMAP]...'),
optionalrepo=True)
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):
Pulkit Goyal
py3: use stringutil.pprint() if we are printing bool values...
r40256 if isinstance(v, bool):
v = stringutil.pprint(v)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 ui.write('%s = %s\n' % (k, v))
fn = 'demo.txt'
Yuya Nishihara
py3: wrap tempfile.mkdtemp() to use bytes path...
r38183 tmpdir = pycompat.mkdtemp('', 'kwdemo.')
Martin Geisler
expand "repo" to "repository" in help texts
r8027 ui.note(_('creating temporary repository at %s\n') % tmpdir)
Christian Ebert
keyword: avoid traceback when kwdemo is run outside a repo...
r29634 if repo is None:
baseui = ui
else:
baseui = repo.baseui
Gregory Szorc
localrepo: move repo creation logic out of localrepository.__init__ (API)...
r39584 repo = localrepo.instance(baseui, tmpdir, create=True)
Mads Kiilerich
config: set a 'source' in most cases where config don't come from file but code...
r20790 ui.setconfig('keyword', fn, '', 'keyword')
Christian Ebert
keyword: inform user about current keywordset in kwdemo...
r13298 svn = ui.configbool('keywordset', 'svn')
# explicitly set keywordset for demo output
Mads Kiilerich
config: set a 'source' in most cases where config don't come from file but code...
r20790 ui.setconfig('keywordset', 'svn', svn, 'keyword')
Christian Ebert
keyword: refactor kwdemo and make output translatable...
r9281
uikwmaps = ui.configitems('keywordmaps')
Pulkit Goyal
py3: handle keyword arguments in hgext/keyword.py...
r35002 if args or opts.get(r'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'))
Pulkit Goyal
py3: handle keyword arguments in hgext/keyword.py...
r35002 if opts.get(r'default') or not uikwmaps:
Christian Ebert
keyword: inform user about current keywordset in kwdemo...
r13298 if svn:
ui.status(_('\toverriding default svn keywordset\n'))
else:
ui.status(_('\toverriding default cvs keywordset\n'))
Pulkit Goyal
py3: handle keyword arguments in hgext/keyword.py...
r35002 if opts.get(r'rcfile'):
Christian Ebert
keyword: refactor kwdemo and make output translatable...
r9281 ui.readconfig(opts.get('rcfile'))
if args:
# simulate hgrc parsing
Christian Ebert
keyword: compact writing of temporary kwdemo hgrc
r28458 rcmaps = '[keywordmaps]\n%s\n' % '\n'.join(args)
repo.vfs.write('hgrc', rcmaps)
Pierre-Yves David
keyword: directly use repo.vfs.join...
r31331 ui.readconfig(repo.vfs.join('hgrc'))
Christian Ebert
keyword: refactor kwdemo and make output translatable...
r9281 kwmaps = dict(ui.configitems('keywordmaps'))
Pulkit Goyal
py3: handle keyword arguments in hgext/keyword.py...
r35002 elif opts.get(r'default'):
Christian Ebert
keyword: inform user about current keywordset in kwdemo...
r13298 if svn:
ui.status(_('\n\tconfiguration using default svn keywordset\n'))
else:
ui.status(_('\n\tconfiguration using default cvs keywordset\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():
Mads Kiilerich
config: set a 'source' in most cases where config don't come from file but code...
r20790 ui.setconfig('keywordmaps', k, v, 'keyword')
Christian Ebert
keyword: refactor kwdemo and make output translatable...
r9281 else:
ui.status(_('\n\tconfiguration using current keyword template maps\n'))
Christian Ebert
keyword: avoid x = a and b or c
r15030 if uikwmaps:
kwmaps = dict(uikwmaps)
else:
kwmaps = _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)
FUJIWARA Katsunori
check-code: detect "missing _() in ui message" more exactly...
r29397 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: inform user about current keywordset in kwdemo...
r13298 demoitems('keywordset', ui.configitems('keywordset'))
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'
Angel Ezquerra
localrepo: remove all external users of localrepo.wopener...
r23879 repo.wvfs.write(fn, 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)
Bryan O'Sullivan
with: use context manager for wlock in keyword demo
r27816 with repo.wlock():
Christian Ebert
keyword: wlock while setting branch in kwdemo
r20113 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:
Mads Kiilerich
config: set a 'source' in most cases where config don't come from file but code...
r20790 repo.ui.setconfig('hooks', name, '', 'keyword')
Christian Ebert
keyword: mark improved demo commit message for translation...
r10499 msg = _('hg keyword configuration and expansion example')
Simon Heimberg
cleanup: Remove the only ever used skip-check-code pragma...
r20240 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))
Christian Ebert
keyword: use wvfs.rmtree to remove kwdemo directory...
r24905 repo.wvfs.rmtree(repo.root)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Gregory Szorc
keyword: define inferrepo in command decorator
r21784 @command('kwexpand',
Yuya Nishihara
commands: move templates of common command options to cmdutil (API)...
r32375 cmdutil.walkopts,
Gregory Szorc
keyword: define inferrepo in command decorator
r21784 _('hg kwexpand [OPTION]... [FILE]...'),
inferrepo=True)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 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)
Martin Geisler
keyword: use cmdutil.command decorator
r14300 @command('kwfiles',
[('A', 'all', None, _('show keyword status flags of all files')),
('i', 'ignore', None, _('show files excluded from expansion')),
('u', 'unknown', None, _('only show unknown (not tracked) files')),
Yuya Nishihara
commands: move templates of common command options to cmdutil (API)...
r32375 ] + cmdutil.walkopts,
Gregory Szorc
keyword: define inferrepo in command decorator
r21784 _('hg kwfiles [OPTION]... [FILE]...'),
inferrepo=True)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 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 '''
FUJIWARA Katsunori
keyword: use _keywordkwt of repository instead of kwtools['templater']...
r33070 kwt = getattr(repo, '_keywordkwt', None)
Christian Ebert
keyword: reuse already present working contexts for match...
r14835 wctx = repo[None]
status = _status(ui, repo, wctx, kwt, *pats, **opts)
Jordi Gutiérrez Hermoso
style: kill ersatz if-else ternary operators...
r24306 if pats:
cwd = repo.getcwd()
else:
cwd = ''
Christian Ebert
keyword: make kwfiles -u show untracked files only (like status)...
r9493 files = []
Pulkit Goyal
py3: handle keyword arguments in hgext/keyword.py...
r35002 opts = pycompat.byteskwargs(opts)
Christian Ebert
keyword: remove deprecated options
r10652 if not opts.get('unknown') or opts.get('all'):
Martin von Zweigbergk
keyword: access status fields by name rather than index
r22918 files = sorted(status.modified + status.added + status.clean)
Christian Ebert
keyword: make iskwfile() a weeding method in lieu of a boolean...
r12627 kwfiles = kwt.iskwfile(files, wctx)
Martin von Zweigbergk
keyword: access status fields by name rather than index
r22918 kwdeleted = kwt.iskwfile(status.deleted, wctx)
kwunknown = kwt.iskwfile(status.unknown, wctx)
Christian Ebert
keyword: make kwfiles -u show untracked files only (like status)...
r9493 if not opts.get('ignore') or opts.get('all'):
Christian Ebert
keyword: make kwfiles show deleted files configured for expansion
r13079 showfiles = kwfiles, kwdeleted, kwunknown
Christian Ebert
keyword: make kwfiles -u show untracked files only (like status)...
r9493 else:
Christian Ebert
keyword: make kwfiles show deleted files configured for expansion
r13079 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],
Martin von Zweigbergk
keyword: access status fields by name rather than index
r22918 [f for f in status.unknown if f not in kwunknown])
Christian Ebert
keyword: make kwfiles show deleted files configured for expansion
r13079 kwlabels = 'enabled deleted enabledunknown ignored ignoredunknown'.split()
Pulkit Goyal
py3: bytestr a bytes val to make sure we get bytechr while iterating...
r39463 kwstates = zip(kwlabels, pycompat.bytestr('K!kIi'), showfiles)
Christian Ebert
keyword: use ui.formatter for kwfiles output
r17057 fm = ui.formatter('kwfiles', opts)
fmt = '%.0s%s\n'
if opts.get('all') or ui.verbose:
fmt = '%s %s\n'
for kwstate, char, filenames in kwstates:
label = 'kwfiles.' + kwstate
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 for f in filenames:
Christian Ebert
keyword: use ui.formatter for kwfiles output
r17057 fm.startitem()
Yuya Nishihara
formatter: rename {abspath}/{file} to {path}, and drop relative {path} (BC)...
r39405 fm.data(kwstatus=char, path=f)
fm.plain(fmt % (char, repo.pathto(f, cwd)), label=label)
Christian Ebert
keyword: use ui.formatter for kwfiles output
r17057 fm.end()
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Gregory Szorc
keyword: define inferrepo in command decorator
r21784 @command('kwshrink',
Yuya Nishihara
commands: move templates of common command options to cmdutil (API)...
r32375 cmdutil.walkopts,
Gregory Szorc
keyword: define inferrepo in command decorator
r21784 _('hg kwshrink [OPTION]... [FILE]...'),
inferrepo=True)
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
Christian Ebert
keyword: update documentation for kwshrink...
r13270 Must be run before changing/disabling active keywords.
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)
FUJIWARA Katsunori
keyword: wrap functions only once at loading keyword extension...
r33071 # monkeypatches
def kwpatchfile_init(orig, self, ui, gp, backend, store, eolmode=None):
'''Monkeypatch/wrap patch.patchfile.__init__ to avoid
rejects or conflicts due to expanded keywords in working dir.'''
orig(self, ui, gp, backend, store, eolmode)
kwt = getattr(getattr(backend, 'repo', None), '_keywordkwt', None)
if kwt:
# shrink keywords read from working dir
self.lines = kwt.shrinklines(self.fname, self.lines)
def kwdiff(orig, repo, *args, **kwargs):
'''Monkeypatch patch.diff to avoid expansion.'''
kwt = getattr(repo, '_keywordkwt', None)
if kwt:
restrict = kwt.restrict
kwt.restrict = True
try:
for chunk in orig(repo, *args, **kwargs):
yield chunk
finally:
if kwt:
kwt.restrict = restrict
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 def kwweb_skip(orig, web):
FUJIWARA Katsunori
keyword: wrap functions only once at loading keyword extension...
r33071 '''Wraps webcommands.x turning off keyword expansion.'''
kwt = getattr(web.repo, '_keywordkwt', None)
if kwt:
origmatch = kwt.match
kwt.match = util.never
try:
Gregory Szorc
hgweb: stop passing req and tmpl into @webcommand functions (API)...
r36903 for chunk in orig(web):
FUJIWARA Katsunori
keyword: wrap functions only once at loading keyword extension...
r33071 yield chunk
finally:
if kwt:
kwt.match = origmatch
Saurabh Singh
cmdutil: remove redundant commitfunc parameter in amend (API)...
r34088 def kw_amend(orig, ui, repo, old, extra, pats, opts):
FUJIWARA Katsunori
keyword: wrap functions only once at loading keyword extension...
r33071 '''Wraps cmdutil.amend expanding keywords after amend.'''
kwt = getattr(repo, '_keywordkwt', None)
if kwt is None:
Saurabh Singh
cmdutil: remove redundant commitfunc parameter in amend (API)...
r34088 return orig(ui, repo, old, extra, pats, opts)
FUJIWARA Katsunori
keyword: wrap functions only once at loading keyword extension...
r33071 with repo.wlock():
kwt.postcommit = True
Saurabh Singh
cmdutil: remove redundant commitfunc parameter in amend (API)...
r34088 newid = orig(ui, repo, old, extra, pats, opts)
FUJIWARA Katsunori
keyword: wrap functions only once at loading keyword extension...
r33071 if newid != old.node():
ctx = repo[newid]
kwt.restrict = True
kwt.overwrite(ctx, ctx.files(), False, True)
kwt.restrict = False
return newid
def kw_copy(orig, ui, repo, pats, opts, rename=False):
'''Wraps cmdutil.copy so that copy/rename destinations do not
contain expanded keywords.
Note that the source of a regular file destination may also be a
symlink:
hg cp sym x -> x is symlink
cp sym x; hg cp -A sym x -> x is file (maybe expanded keywords)
For the latter we have to follow the symlink to find out whether its
target is configured for expansion and we therefore must unexpand the
keywords in the destination.'''
kwt = getattr(repo, '_keywordkwt', None)
if kwt is None:
return orig(ui, repo, pats, opts, rename)
with repo.wlock():
orig(ui, repo, pats, opts, rename)
if opts.get('dry_run'):
return
wctx = repo[None]
cwd = repo.getcwd()
def haskwsource(dest):
'''Returns true if dest is a regular file and configured for
expansion or a symlink which points to a file configured for
expansion. '''
source = repo.dirstate.copied(dest)
if 'l' in wctx.flags(source):
source = pathutil.canonpath(repo.root, cwd,
os.path.realpath(source))
return kwt.match(source)
candidates = [f for f in repo.dirstate.copies() if
'l' not in wctx.flags(f) and haskwsource(f)]
kwt.overwrite(wctx, candidates, False, False)
def kw_dorecord(orig, ui, repo, commitfunc, *pats, **opts):
'''Wraps record.dorecord expanding keywords after recording.'''
kwt = getattr(repo, '_keywordkwt', None)
if kwt is None:
return orig(ui, repo, commitfunc, *pats, **opts)
with repo.wlock():
# record returns 0 even when nothing has changed
# therefore compare nodes before and after
kwt.postcommit = True
ctx = repo['.']
wstatus = ctx.status()
ret = orig(ui, repo, commitfunc, *pats, **opts)
recctx = repo['.']
if ctx != recctx:
modified, added = _preselect(wstatus, recctx.files())
kwt.restrict = False
kwt.overwrite(recctx, modified, False, True)
kwt.overwrite(recctx, added, False, True, True)
kwt.restrict = True
return ret
def kwfilectx_cmp(orig, self, fctx):
if fctx._customcmp:
return fctx.cmp(self)
kwt = getattr(self._repo, '_keywordkwt', None)
if kwt is None:
return orig(self, fctx)
# keyword affects data size, comparing wdir and filelog size does
# not make sense
if (fctx._filenode is None and
(self._repo._encodefilterpats or
kwt.match(fctx.path()) and 'l' not in fctx.flags() or
self.size() - 4 == fctx.size()) or
self.size() == fctx.size()):
return self._filelog.cmp(self._filenode, fctx.data())
return True
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 uisetup(ui):
FUJIWARA Katsunori
keyword: wrap functions only once at loading keyword extension...
r33071 ''' Monkeypatches dispatch._parse to retrieve user command.
Overrides file method to return kwfilelog instead of filelog
if file matches user configuration.
Wraps commit to overwrite configured files with updated
keyword substitutions.
Monkeypatches patch and webcommands.'''
Christian Ebert
keyword: collect filename patterns, wrap dispatch._parse in uisetup...
r6502
Christian Ebert
keyword: move collecting of [keyword] patterns to reposetup (issue2303)...
r11678 def kwdispatch_parse(orig, ui, args):
'''Monkeypatch dispatch._parse to obtain running hg command.'''
cmd, func, args, options, cmdoptions = orig(ui, args)
kwtools['hgcmd'] = cmd
return cmd, func, args, options, cmdoptions
Christian Ebert
keyword: collect filename patterns, wrap dispatch._parse in uisetup...
r6502
Christian Ebert
keyword: move collecting of [keyword] patterns to reposetup (issue2303)...
r11678 extensions.wrapfunction(dispatch, '_parse', kwdispatch_parse)
Christian Ebert
keyword: collect filename patterns, wrap dispatch._parse in uisetup...
r6502
FUJIWARA Katsunori
keyword: wrap functions only once at loading keyword extension...
r33071 extensions.wrapfunction(context.filectx, 'cmp', kwfilectx_cmp)
extensions.wrapfunction(patch.patchfile, '__init__', kwpatchfile_init)
extensions.wrapfunction(patch, 'diff', kwdiff)
extensions.wrapfunction(cmdutil, 'amend', kw_amend)
extensions.wrapfunction(cmdutil, 'copy', kw_copy)
extensions.wrapfunction(cmdutil, 'dorecord', kw_dorecord)
for c in nokwwebcommands.split():
extensions.wrapfunction(webcommands, c, kwweb_skip)
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815 def reposetup(ui, repo):
FUJIWARA Katsunori
keyword: wrap functions only once at loading keyword extension...
r33071 '''Sets up repo as kwrepo for keyword substitution.'''
Christian Ebert
Add extension for filewise RCS-keyword expansion in working dir...
r5815
Matt Mackall
bundlerepo: reintroduce dirstate
r7853 try:
Christian Ebert
keyword: move collecting of [keyword] patterns to reposetup (issue2303)...
r11678 if (not repo.local() or kwtools['hgcmd'] in nokwcommands.split()
Matt Mackall
bundlerepo: reintroduce dirstate
r7853 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: move collecting of [keyword] patterns to reposetup (issue2303)...
r11678 inc, exc = [], ['.hg*']
for pat, opt in ui.configitems('keyword'):
if opt != 'ignore':
inc.append(pat)
else:
exc.append(pat)
if not inc:
return
FUJIWARA Katsunori
keyword: use _keywordkwt of repository instead of kwtools['templater']...
r33070 kwt = kwtemplater(ui, repo, inc, exc)
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:]
Angel Ezquerra
localrepo: remove all external users of localrepo.sopener...
r23878 return kwfilelog(self.svfs, 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: rename kwt.record attribute to kwt.postcommit...
r16809 if not kwt.postcommit:
Christian Ebert
keyword: refactor kwtemplater.overwrite()...
r12625 restrict = kwt.restrict
kwt.restrict = True
Christian Ebert
keyword: pass context to kwtemplater.overwrite...
r11320 kwt.overwrite(self[n], sorted(ctx.added() + ctx.modified()),
Christian Ebert
keyword: refactor kwtemplater.overwrite()...
r12625 False, True)
kwt.restrict = restrict
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
Greg Ward
rollback: avoid unsafe rollback when not at tip (issue2998)...
r15183 def rollback(self, dryrun=False, force=False):
Christian Ebert
keyword: use context manager for rollback locking
r32935 with self.wlock():
origrestrict = kwt.restrict
try:
if not dryrun:
changed = self['.'].files()
ret = super(kwrepo, self).rollback(dryrun, force)
if not dryrun:
ctx = self['.']
modified, added = _preselect(ctx.status(), changed)
kwt.restrict = False
kwt.overwrite(ctx, modified, True, True)
kwt.overwrite(ctx, added, True, False)
return ret
finally:
kwt.restrict = origrestrict
Christian Ebert
keyword: support rollback by restoring expansion to previous values...
r12498
FUJIWARA Katsunori
keyword: make wrapped repository and kwtemplater refer to each other...
r33067 repo.__class__ = kwrepo
repo._keywordkwt = kwt