[PATCH] keyword: support copy and rename (2nd try)

Christian Ebert blacktrash at gmx.net
Tue Sep 28 17:14:39 CDT 2010


# HG changeset patch
# User Christian Ebert <blacktrash at gmx.net>
# Date 1285711707 -7200
# Node ID 47aa65fcfb2995e3d71c4eabc0dca8a5eba5c9fb
# Parent  f6443444cf12e17e6761f4e320f65781e6014e30
keyword: support copy and rename

When a file containing keywords is copied/renamed to a destintation
which is ignored by the extension, the destination is now overwritten
with the keywords unexpanded to avoid the danger of accidentally
storing expanded keywords in history.

Files copied/renamed from an ignored source to an ignored
destination are not touched.

Add tests covering both of the above cases.

diff --git a/hgext/keyword.py b/hgext/keyword.py
--- a/hgext/keyword.py
+++ b/hgext/keyword.py
@@ -84,6 +84,7 @@
 
 from mercurial import commands, cmdutil, dispatch, filelog, revlog, extensions
 from mercurial import patch, localrepo, templater, templatefilters, util, match
+from mercurial import mdiff
 from mercurial.hgweb import webcommands
 from mercurial.i18n import _
 import re, shutil, tempfile
@@ -91,8 +92,8 @@
 commands.optionalrepo += ' kwdemo'
 
 # hg commands that do not act on keywords
-nokwcommands = ('add addremove annotate bundle copy export grep incoming init'
-                ' log outgoing push rename tip verify convert email glog')
+nokwcommands = ('add addremove annotate bundle export grep incoming init log'
+                ' outgoing push tip verify convert email glog')
 
 # hg commands that trigger expansion only when writing to working dir,
 # not when reading filelog, and unexpand when reading from working dir
@@ -543,6 +544,36 @@
         kwt.match = util.never
         return orig(web, req, tmpl)
 
+    def kw_copy(orig, ui, repo, pats, opts, rename=False):
+        '''Wraps cmdutil.copy to prevent keyword expansion in a copy/rename
+        destination.
+        diffopts.git only shows textual differences when the destination
+        differs from the original. Therefore overwriting is only triggered
+        when the destination's text content differs from the filelog data
+        of the original:
+        kwfile -> ignored overwrites when keywords are found
+        ignored -> ignored does not overwrite even when keywords are found.
+        '''
+        orig(ui, repo, pats, opts, rename)
+        if opts.get('dry_run'):
+            return
+        wctx = repo[None]
+        ignored = [f for f in wctx.added()
+                   if not kwt.match(f) and not 'l' in wctx.flags(f)]
+        if not ignored:
+            return
+        diffopts = mdiff.diffopts(context=0, git=True)
+        for f in ignored:
+            data = repo.wread(f)
+            if not util.binary(data):
+                diffmatch = match.match(repo, '', [f], exact=True)
+                for chunk in patch.diff(repo, match=diffmatch, opts=diffopts):
+                    if kwt.re_kw.search(chunk):
+                        data = kwt.re_kw.sub(r'$\1$', data)
+                        ui.note(_('overwriting %s shrinking keywords\n') % f)
+                        repo.wwrite(f, data, wctx.flags(f))
+                        break
+
     def kw_dorecord(orig, ui, repo, commitfunc, *pats, **opts):
         '''Wraps record.dorecord expanding keywords after recording.'''
         wlock = repo.wlock()
@@ -563,6 +594,7 @@
 
     extensions.wrapfunction(patch.patchfile, '__init__', kwpatchfile_init)
     extensions.wrapfunction(patch, 'diff', kw_diff)
+    extensions.wrapfunction(cmdutil, 'copy', kw_copy)
     for c in 'annotate changeset rev filediff diff'.split():
         extensions.wrapfunction(webcommands, c, kwweb_skip)
     for name in recordextensions.split():
diff --git a/tests/test-keyword.t b/tests/test-keyword.t
--- a/tests/test-keyword.t
+++ b/tests/test-keyword.t
@@ -48,6 +48,7 @@
   > [keyword]
   > ** =
   > b = ignore
+  > i = ignore
   > [hooks]
   > commit=
   > commit.test=cp a hooktest
@@ -498,6 +499,23 @@
   $ touch c
   $ hg status
 
+Copy kwfile to keyword ignored file unexpanding keywords
+
+  $ hg --verbose copy a i
+  copying a to i
+  overwriting i shrinking keywords
+  $ head -n 1 i
+  expand $Id$
+  $ hg forget i
+  $ rm i
+
+Copy ignored file to ignored file: no overwriting
+
+  $ hg --verbose copy b i
+  copying b to i
+  $ hg forget i
+  $ rm i
+
 Test different options of hg kwfiles
 
   $ hg kwfiles
@@ -541,6 +559,7 @@
   ** = 
   b = ignore
   demo.txt = 
+  i = ignore
   [keywordmaps]
   Xinfo = {author}: {desc}
   $Xinfo: test: hg keyword configuration and expansion example $


More information about the Mercurial-devel mailing list