hgext/keyword.py
changeset 12625 d87f3ff904ba
parent 12605 aa4a6e3ed0c9
child 12626 41df968a54c9
--- a/hgext/keyword.py	Fri Oct 08 18:00:19 2010 -0500
+++ b/hgext/keyword.py	Fri Oct 08 18:39:46 2010 +0100
@@ -96,7 +96,7 @@
 
 # hg commands that trigger expansion only when writing to working dir,
 # not when reading filelog, and unexpand when reading from working dir
-restricted = 'merge record qrecord resolve transplant'
+restricted = 'merge kwexpand kwshrink record qrecord resolve transplant'
 
 # commands using dorecord
 recordcommands = 'record qrecord'
@@ -138,6 +138,12 @@
     templates.update(kwsets[ui.configbool('keywordset', 'svn')])
     return templates
 
+def _shrinktext(text, subfunc):
+    '''Helper for keyword expansion removal in text.
+    Depending on subfunc also returns number of substitutions.'''
+    return subfunc(r'$\1$', text)
+
+
 class kwtemplater(object):
     '''
     Sets up keyword templates, corresponding keyword regex, and
@@ -191,49 +197,44 @@
         Caveat: localrepository._link fails on Windows.'''
         return self.match(path) and not 'l' in flagfunc(path)
 
-    def overwrite(self, ctx, candidates, iswctx, expand, changed):
+    def overwrite(self, ctx, candidates, lookup, expand):
         '''Overwrites selected files expanding/shrinking keywords.'''
-        if changed is not None:
-            candidates = [f for f in candidates if f in changed]
         candidates = [f for f in candidates if self.iskwfile(f, ctx.flags)]
-        if candidates:
-            restrict = self.restrict
-            self.restrict = True        # do not expand when reading
-            rollback = kwtools['hgcmd'] == 'rollback'
+        if not candidates:
+            return
+        commit = self.restrict and not lookup
+        if self.restrict or expand and lookup:
             mf = ctx.manifest()
-            msg = (expand and _('overwriting %s expanding keywords\n')
-                   or _('overwriting %s shrinking keywords\n'))
-            for f in candidates:
-                if not self.record and not rollback:
-                    data = self.repo.file(f).read(mf[f])
-                else:
-                    data = self.repo.wread(f)
-                if util.binary(data):
-                    continue
-                if expand:
-                    if iswctx:
-                        ctx = self.repo.filectx(f, fileid=mf[f]).changectx()
-                    data, found = self.substitute(data, f, ctx,
-                                                  self.re_kw.subn)
-                else:
-                    found = self.re_kw.search(data)
-                if found:
-                    self.ui.note(msg % f)
-                    self.repo.wwrite(f, data, mf.flags(f))
-                    if iswctx and not rollback:
-                        self.repo.dirstate.normal(f)
-                    elif self.record:
-                        self.repo.dirstate.normallookup(f)
-            self.restrict = restrict
-
-    def shrinktext(self, text):
-        '''Unconditionally removes all keyword substitutions from text.'''
-        return self.re_kw.sub(r'$\1$', text)
+        fctx = ctx
+        msg = (expand and _('overwriting %s expanding keywords\n')
+               or _('overwriting %s shrinking keywords\n'))
+        for f in candidates:
+            if self.restrict:
+                data = self.repo.file(f).read(mf[f])
+            else:
+                data = self.repo.wread(f)
+            if util.binary(data):
+                continue
+            if expand:
+                if lookup:
+                    fctx = self.repo.filectx(f, fileid=mf[f]).changectx()
+                data, found = self.substitute(data, f, fctx, self.re_kw.subn)
+            elif self.restrict:
+                found = self.re_kw.search(data)
+            else:
+                data, found = _shrinktext(data, self.re_kw.subn)
+            if found:
+                self.ui.note(msg % f)
+                self.repo.wwrite(f, data, ctx.flags(f))
+                if commit:
+                    self.repo.dirstate.normal(f)
+                elif self.record:
+                    self.repo.dirstate.normallookup(f)
 
     def shrink(self, fname, text):
         '''Returns text with all keyword substitutions removed.'''
         if self.match(fname) and not util.binary(text):
-            return self.shrinktext(text)
+            return _shrinktext(text, self.re_kw.sub)
         return text
 
     def shrinklines(self, fname, lines):
@@ -241,7 +242,7 @@
         if self.match(fname):
             text = ''.join(lines)
             if not util.binary(text):
-                return self.shrinktext(text).splitlines(True)
+                return _shrinktext(text, self.re_kw.sub).splitlines(True)
         return lines
 
     def wread(self, fname, data):
@@ -299,7 +300,7 @@
         modified, added, removed, deleted, unknown, ignored, clean = status
         if modified or added or removed or deleted:
             raise util.Abort(_('outstanding uncommitted changes'))
-        kwt.overwrite(wctx, clean, True, expand, None)
+        kwt.overwrite(wctx, clean, True, expand)
     finally:
         wlock.release()
 
@@ -502,8 +503,11 @@
             n = super(kwrepo, self).commitctx(ctx, error)
             # no lock needed, only called from repo.commit() which already locks
             if not kwt.record:
+                restrict = kwt.restrict
+                kwt.restrict = True
                 kwt.overwrite(self[n], sorted(ctx.added() + ctx.modified()),
-                              False, True, None)
+                              False, True)
+                kwt.restrict = restrict
             return n
 
         def rollback(self, dryrun=False):
@@ -515,8 +519,10 @@
                 if not dryrun:
                     ctx = self['.']
                     modified, added = self[None].status()[:2]
-                    kwt.overwrite(ctx, added, True, False, changed)
-                    kwt.overwrite(ctx, modified, True, True, changed)
+                    modified = [f for f in modified if f in changed]
+                    added = [f for f in added if f in changed]
+                    kwt.overwrite(ctx, added, True, False)
+                    kwt.overwrite(ctx, modified, True, True)
                 return ret
             finally:
                 wlock.release()
@@ -551,8 +557,10 @@
             ret = orig(ui, repo, commitfunc, *pats, **opts)
             recordctx = repo['.']
             if ctx != recordctx:
-                kwt.overwrite(recordctx, recordctx.files(),
-                              False, True, recordctx)
+                candidates = [f for f in recordctx.files() if f in recordctx]
+                kwt.restrict = False
+                kwt.overwrite(recordctx, candidates, False, True)
+                kwt.restrict = True
             return ret
         finally:
             wlock.release()