# HG changeset patch # User Christian Ebert # Date 1169081418 -3600 # Node ID b0b85b383f3683f6f4d16044fe1a132023f4aa43 # Parent b2cc6a8d4a180de144d97cae9ea574cac41be8b0 Move all that can be done only once per repo into reposetup Actually kwrepo is not set up if there aren't any files configured for keyword substitution. Stuff that now is done at reposetup and not at every filelog init or hook: 1) filename matching function 2) compilation of keyword regex 3) templates and changeset templater kwtemplater as an appended class should prevent namespace conflicts. diff -r b2cc6a8d4a18 -r b0b85b383f36 hgkw/keyword.py --- a/hgkw/keyword.py Thu Jan 18 00:06:11 2007 +0100 +++ b/hgkw/keyword.py Thu Jan 18 01:50:18 2007 +0100 @@ -57,7 +57,8 @@ # above line for backwards compatibility; can be changed to # from mercurial.i18n import _ # some day -from mercurial import cmdutil, templater, util +from mercurial import context, filelog, revlog +from mercurial import commands, cmdutil, templater, util from mercurial.node import * import os.path, re, sys, time @@ -75,22 +76,22 @@ '''Returns hgdate in cvs-like UTC format.''' return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0])) -def kwfmatches(ui, repo, files): - '''Selects candidates for keyword substitution - configured in keyword section in hgrc.''' +def getkwconfig(ui, repo): inc = [pat for pat, opt in ui.configitems('keyword') if opt != 'ignore'] if not inc: - ui.warn(_('keyword: no filename globs for expansion\n')) - return [] + ui.warn(_('keyword: no filename globs for substitution\n')) + return None, None exc = [pat for pat, opt in ui.configitems('keyword') if opt == 'ignore'] - kwfmatcher = util.matcher(repo.root, inc=inc, exc=['.hg*']+exc)[1] - return [f for f in files if kwfmatcher(f)] + return inc, exc class kwtemplater(object): ''' Sets up keyword templates, corresponding keyword regex, and provides keyword expansion function. + + If a repo is configured for keyword substitution, this class + will be set as an (appendix) attribute to the repo. ''' def __init__(self, ui, repo): self.ui = ui @@ -100,7 +101,6 @@ '|'.join(re.escape(k) for k in self.templates.keys())) templater.common_filters['utcdate'] = utcdate self.t = cmdutil.changeset_templater(ui, repo, False, '', False) - def expand(self, mobj, path, node): '''Expands keyword with corresponding template.''' @@ -109,16 +109,20 @@ self.t.use_template(template) self.ui.pushbuffer() self.t.show(changenode=node, root=self.repo.root, file=path) - expansion = templater.firstline(self.ui.popbuffer()) - return '$%s: %s $' % (kw, expansion) + kwsub = templater.firstline(self.ui.popbuffer()) + return '$%s: %s $' % (kw, kwsub) def reposetup(ui, repo): '''Sets up repo, and filelog especially, as kwrepo and kwfilelog for keyword substitution. This is done for local repos only.''' + if not repo.local(): + return - from mercurial import context, filelog, revlog - if not repo.local(): + inc, exc = getkwconfig(ui, repo) + if not inc: + # no files configured for keyword substitution: + # no need to burden repo with extra ballast return class kwrepo(repo.__class__): @@ -137,15 +141,15 @@ super(kwfilelog, self).__init__(opener, path, defversion) self._repo = repo self._path = path - # only init kwtemplater if needed - if not isinstance(repo, int) and kwfmatches(ui, repo, [path]): - self.kwt = kwtemplater(ui, repo) + # check at init if file configured for keyword substition + if not isinstance(repo, int) and repo.kwfmatcher(path): + self.kwsub = True else: - self.kwt = None + self.kwsub = False def iskwcandidate(self, data): '''Decides whether to act on keywords.''' - return self.kwt is not None and not util.binary(data) + return self.kwsub and not util.binary(data) def read(self, node): '''Substitutes keywords when reading filelog.''' @@ -153,25 +157,32 @@ if self.iskwcandidate(data): c = context.filectx(self._repo, self._path, fileid=node, filelog=self) - return self.kwt.re_kw.sub(lambda m: - self.kwt.expand(m, self._path, c.node()), data) + return self._repo.kwt.re_kw.sub(lambda m: + self._repo.kwt.expand(m, self._path, c.node()), data) return data def add(self, text, meta, tr, link, p1=None, p2=None): '''Removes keyword substitutions when adding to filelog.''' if self.iskwcandidate(text): - text = self.kwt.re_kw.sub(r'$\1$', text) + text = self._repo.kwt.re_kw.sub(r'$\1$', text) return super(kwfilelog, self).add(text, meta, tr, link, p1=p1, p2=p2) def cmp(self, node, text): '''Removes keyword substitutions for comparison.''' if self.iskwcandidate(text): - text = self.kwt.re_kw.sub(r'$\1$', text) + text = self._repo.kwt.re_kw.sub(r'$\1$', text) return super(kwfilelog, self).cmp(node, text) filelog.filelog = kwfilelog repo.__class__ = kwrepo + + # create filematching function once for repo + setattr(repo, 'kwfmatcher', + util.matcher(repo.root, inc=inc, exc=['.hg*']+exc)[1]) + # initialize kwtemplater once for repo + setattr(repo, 'kwt', kwtemplater(ui, repo)) + # make pretxncommit hook import kwmodule regardless of where it's located for k, v in sys.modules.iteritems(): if v is None: @@ -185,13 +196,13 @@ sys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) mod = os.path.splitext(os.path.basename(__file__))[0] ui.setconfig('hooks', 'pretxncommit.keyword', 'python:%s.pretxnkw' % mod) - del mod + + del inc, exc, mod def pretxnkw(ui, repo, hooktype, **args): '''pretxncommit hook that collects candidates for keyword expansion on commit and expands keywords in working dir.''' - from mercurial import commands cmd, sysargs, globalopts, cmdopts = commands.parse(ui, sys.argv[1:])[1:] if repr(cmd).split()[1] in ('tag', 'import_'): @@ -199,16 +210,16 @@ files, match, anypats = cmdutil.matchpats(repo, sysargs, cmdopts) modified, added = repo.status(files=files, match=match)[:2] - candidates = kwfmatches(ui, repo, modified+added) + candidates = [f for f in modified+added if repo.kwfmatcher(f)] if not candidates: return - kwt = kwtemplater(ui, repo) node = bin(args['node']) for f in candidates: data = repo.wfile(f).read() if not util.binary(data): - data, kwct = kwt.re_kw.subn(lambda m: kwt.expand(m, f, node), data) + data, kwct = repo.kwt.re_kw.subn(lambda m: + repo.kwt.expand(m, f, node), data) if kwct: ui.debug(_('overwriting %s expanding keywords\n' % f)) repo.wfile(f, 'w').write(data)