hgkw/keyword.py
branchkwmap-templates
changeset 186 c1b7b1d052de
parent 185 bc5cd6cf69bc
child 187 a01a0392f648
--- a/hgkw/keyword.py	Tue Jul 17 14:15:47 2007 +0200
+++ b/hgkw/keyword.py	Wed Jul 18 16:12:14 2007 +0200
@@ -136,27 +136,36 @@
     Sets up keyword templates, corresponding keyword regex, and
     provides keyword substitution functions.
     '''
-    def __init__(self, ui, repo, path='', node=None):
+    def __init__(self, ui, repo, path='', node=None, expand=True):
         self.ui = ui
         self.repo = repo
         self.path = path
         self.node = node
         templates = dict(ui.configitems('keywordmaps'))
         if templates:
-            # parse templates here for less overhead in kwsub matchfunc
             for k in templates.keys():
                 templates[k] = templater.parsestring(templates[k],
                                                      quoted=False)
         self.templates = templates or deftemplates
         escaped = [re.escape(k) for k in self.templates.keys()]
         self.re_kw = re.compile(r'\$(%s)[^$]*?\$' % '|'.join(escaped))
-        templater.common_filters['utcdate'] = utcdate
-        try:
-            self.t = cmdutil.changeset_templater(ui, repo, False, '', False)
-        except TypeError:
-            # depending on hg rev changeset_templater has extra "brinfo" arg
-            self.t = cmdutil.changeset_templater(ui, repo,
-                                                 False, None, '', False)
+        if expand:
+            templater.common_filters['utcdate'] = utcdate
+            try:
+                self.t = cmdutil.changeset_templater(ui, repo,
+                                                     False, '', False)
+            except TypeError:
+                # depending on hg rev changeset_templater has extra "brinfo" arg
+                self.t = cmdutil.changeset_templater(ui, repo,
+                                                     False, None, '', False)
+        else:
+            self.t = None
+
+    def ctxnode(self, node):
+        '''Obtains missing node from file context.'''
+        if not self.node:
+            c = context.filectx(self.repo, self.path, fileid=node)
+            self.node = c.node()
 
     def kwsub(self, mobj):
         '''Substitutes keyword using corresponding template.'''
@@ -168,57 +177,66 @@
         return '$%s: %s $' % (kw, keywordsub)
 
     def expand(self, node, data):
-        '''Returns data with expanded keywords.'''
+        '''Returns data with keywords expanded.'''
         if util.binary(data):
             return data
-        c = context.filectx(self.repo, self.path, fileid=node)
-        self.node = c.node()
+        self.ctxnode(node)
         return self.re_kw.sub(self.kwsub, data)
 
+    def process(self, node, data):
+        '''Returns a tuple: data, count.
+        Count is number of keywords/keyword substitutions.
+        Keywords in data are expanded, if templater was initialized.'''
+        if util.binary(data):
+            return data, None
+        if self.t:
+            self.ctxnode(node)
+            return self.re_kw.subn(self.kwsub, data)
+        return data, self.re_kw.search(data)
+
     def shrink(self, text):
         '''Returns text with all keyword substitutions removed.'''
         if util.binary(text):
             return text
         return self.re_kw.sub(r'$\1$', text)
 
-    def overwrite(self, candidates, manifest, expand=True, commit=True):
-        '''Overwrites candidates in working dir expanding keywords.'''
-        if expand:
-            sub = self.kwsub
-            action = 'expanding'
-        else:
-            sub = r'$\1$'
-            action = 'shrinking'
-        if not commit:
-            notify = self.ui.note
-        else:
-            notify = self.ui.debug
+    def overwrite(self, candidates, man, commit=True):
+        '''Overwrites files in working directory if keywords are detected.
+        Keywords are expanded if keyword templater is initialized,
+        otherwise their substitution is removed.'''
+        expand = self.t is not None
+        action = ('shrinking', 'expanding')[expand]
+        notify = (self.ui.note, self.ui.debug)[commit]
         files = []
         for f in candidates:
-            data = self.repo.wread(f)
-            if not util.binary(data):
-                self.path = f
-                data, kwct = self.re_kw.subn(sub, data)
-                if kwct:
-                    notify(_('overwriting %s %s keywords\n') % (f, action))
-                    self.repo.wwrite(f, data, manifest.flags(f))
-                    files.append(f)
+            fp = self.repo.file(f, kwcnt=True, kwexp=expand)
+            data, cnt = fp.read(man[f])
+            if cnt:
+                notify(_('overwriting %s %s keywords\n') % (f, action))
+                self.repo.wwrite(f, data, man.flags(f))
+                files.append(f)
         if files:
             self.repo.dirstate.update(files, 'n')
 
 class kwfilelog(filelog.filelog):
     '''
     Subclass of filelog to hook into its read, add, cmp methods.
-    Keywords are "stored" unexpanded, and expanded on reading.
+    Keywords are "stored" unexpanded, and processed on reading.
     '''
-    def __init__(self, opener, path, kwtemplater):
+    def __init__(self, opener, path, kwtemplater, kwcnt):
         super(kwfilelog, self).__init__(opener, path)
         self.kwtemplater = kwtemplater
+        self.kwcnt = kwcnt
 
     def read(self, node):
-        '''Substitutes keywords when reading filelog.'''
+        '''Passes data through kwemplater methods for
+        either unconditional keyword expansion
+        or counting of keywords and substitution method
+        set by the calling overwrite function.'''
         data = super(kwfilelog, self).read(node)
-        return self.kwtemplater.expand(node, data)
+        if not self.kwcnt:
+            return self.kwtemplater.expand(node, data)
+        return self.kwtemplater.process(node, data)
 
     def add(self, text, meta, tr, link, p1=None, p2=None):
         '''Removes keyword substitutions when adding to filelog.'''
@@ -233,7 +251,7 @@
             return t2 != text
         return super(kwfilelog, self).cmp(node, text)
 
-def overwrite(ui, repo, files=None, expand=False):
+def overwrite(ui, repo, files=None, expand=True):
     '''Expands/shrinks keywords in working directory.'''
     wlock = repo.wlock()
     try:
@@ -257,8 +275,8 @@
             ui.warn(_('given files not tracked or '
                       'not configured for expansion\n'))
             return
-        kwt = kwtemplater(ui, repo, node=ctx.node())
-        kwt.overwrite(files, m, expand=expand, commit=False)
+        kwt = kwtemplater(ui, repo, node=ctx.node(), expand=expand)
+        kwt.overwrite(files, m, commit=False)
     finally:
         wlock.release()
 
@@ -271,14 +289,14 @@
                changing keyword expansion configuration
     or if you experience problems with "hg import"
     '''
-    overwrite(ui, repo, args, expand=False)
+    overwrite(ui, repo, files=args, expand=False)
 
 def expand(ui, repo, *args):
     '''expand keywords in working directory
 
     run after (re)enabling keyword expansion
     '''
-    overwrite(ui, repo, args, expand=True)
+    overwrite(ui, repo, files=args)
 
 def demo(ui, repo, **opts):
     '''print [keywordmaps] configuration and an expansion example
@@ -342,12 +360,12 @@
         return
 
     class kwrepo(repo.__class__):
-        def file(self, f):
+        def file(self, f, kwcnt=False, kwexp=True):
             if f[0] == '/':
                 f = f[1:]
             if kwfmatcher(f):
-                kwt = kwtemplater(ui, self, path=f)
-                return kwfilelog(self.sopener, f, kwt)
+                kwt = kwtemplater(ui, self, path=f, expand=kwexp)
+                return kwfilelog(self.sopener, f, kwt, kwcnt)
             else:
                 return filelog.filelog(self.sopener, f)