hgkw/keyword.py
branchkwmap-templates
changeset 110 b0b85b383f36
parent 109 b2cc6a8d4a18
child 111 94315baadcaf
--- 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)