keyword: support mq; handle (q)record more gracefully
authorChristian Ebert <blacktrash@gmx.net>
Tue, 15 Jan 2008 13:58:22 +0100
changeset 5884 a139f141dcae
parent 5878 d39af2eabb8c
child 5885 53be157543d4
keyword: support mq; handle (q)record more gracefully mq: Ensure that expanded keywords do not make it into patches. - disable expansion when reading filelog - shrink expanded keywords when reading from working dir (wread) (q)record: Avoid additional hunks due to expanded keywords. However this is still a compromise, as keyword expansions are not updated in working directory because record should not overwrite files. Mention above shortcomings and "hg kwexpand" workaround in help and update test output. system argument parsing: Command detection might be slightly more expensive with dispatch._parse, but we will need this for improving "hg diff" output.
hgext/keyword.py
tests/test-keyword.out
--- a/hgext/keyword.py	Fri Jan 18 10:48:25 2008 -0600
+++ b/hgext/keyword.py	Tue Jan 15 13:58:22 2008 +0100
@@ -69,12 +69,16 @@
 To force expansion after enabling it, or a configuration change, run
 "hg kwexpand".
 
+Also, when committing with the record extension or using mq's qrecord, be aware
+that keywords cannot be updated. Again, run "hg kwexpand" on the files in
+question to update keyword expansions after all changes have been checked in.
+
 Expansions spanning more than one line and incremental expansions,
 like CVS' $Log$, are not supported. A keyword template map
 "Log = {desc}" expands to the first line of the changeset description.
 '''
 
-from mercurial import commands, cmdutil, context, fancyopts, filelog
+from mercurial import commands, cmdutil, context, dispatch, filelog
 from mercurial import patch, localrepo, revlog, templater, util
 from mercurial.node import *
 from mercurial.i18n import _
@@ -86,6 +90,13 @@
     '''Returns hgdate in cvs-like UTC format.'''
     return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0]))
 
+def _kwrestrict(cmd):
+    '''Returns True if cmd should trigger restricted expansion.
+    Keywords will only expanded when writing to working dir.
+    Crucial for mq as expanded keywords should not make it into patches.'''
+    return cmd in ('qimport', 'qnew', 'qpush', 'qrefresh', 'record', 'qrecord')
+
+
 _kwtemplater = None
 
 class kwtemplater(object):
@@ -103,10 +114,11 @@
         'Header': '{root}/{file},v {node|short} {date|utcdate} {author|user}',
     }
 
-    def __init__(self, ui, repo, inc, exc):
+    def __init__(self, ui, repo, inc, exc, hgcmd):
         self.ui = ui
         self.repo = repo
         self.matcher = util.matcher(repo.root, inc=inc, exc=exc)[1]
+        self.hgcmd = hgcmd
         self.commitnode = None
         self.path = ''
 
@@ -144,7 +156,7 @@
 
     def expand(self, node, data):
         '''Returns data with keywords expanded.'''
-        if util.binary(data):
+        if util.binary(data) or _kwrestrict(self.hgcmd):
             return data
         return self.substitute(node, data, self.re_kw.sub)
 
@@ -395,20 +407,16 @@
     This is done for local repos only, and only if there are
     files configured at all for keyword substitution.'''
 
-    def kwbailout():
-        '''Obtains command via simplified cmdline parsing,
-        returns True if keyword expansion not needed.'''
-        nokwcommands = ('add', 'addremove', 'bundle', 'clone', 'copy',
-                        'export', 'grep', 'identify', 'incoming', 'init',
-                        'log', 'outgoing', 'push', 'remove', 'rename',
-                        'rollback', 'tip',
-                        'convert')
-        args = fancyopts.fancyopts(sys.argv[1:], commands.globalopts, {})
-        if args:
-            aliases, i = cmdutil.findcmd(ui, args[0], commands.table)
-            return aliases[0] in nokwcommands
+    if not repo.local():
+        return
 
-    if not repo.local() or kwbailout():
+    nokwcommands = ('add', 'addremove', 'bundle', 'clone', 'copy',
+                    'export', 'grep', 'identify', 'incoming', 'init',
+                    'log', 'outgoing', 'push', 'remove', 'rename',
+                    'rollback', 'tip',
+                    'convert')
+    hgcmd, func, args, opts, cmdopts = dispatch._parse(ui, sys.argv[1:])
+    if hgcmd in nokwcommands:
         return
 
     inc, exc = [], ['.hgtags']
@@ -421,7 +429,7 @@
         return
 
     global _kwtemplater
-    _kwtemplater = kwtemplater(ui, repo, inc, exc)
+    _kwtemplater = kwtemplater(ui, repo, inc, exc, hgcmd)
 
     class kwrepo(repo.__class__):
         def file(self, f, kwmatch=False):
@@ -431,6 +439,12 @@
                 return kwfilelog(self.sopener, f)
             return filelog.filelog(self.sopener, f)
 
+        def wread(self, filename):
+            data = super(kwrepo, self).wread(filename)
+            if _kwrestrict(hgcmd) and _kwtemplater.matcher(filename):
+                return _kwtemplater.shrink(data)
+            return data
+
         def commit(self, files=None, text='', user=None, date=None,
                    match=util.always, force=False, force_editor=False,
                    p1=None, p2=None, extra={}):
--- a/tests/test-keyword.out	Fri Jan 18 10:48:25 2008 -0600
+++ b/tests/test-keyword.out	Tue Jan 15 13:58:22 2008 +0100
@@ -36,6 +36,10 @@
 To force expansion after enabling it, or a configuration change, run
 "hg kwexpand".
 
+Also, when committing with the record extension or using mq's qrecord, be aware
+that keywords cannot be updated. Again, run "hg kwexpand" on the files in
+question to update keyword expansions after all changes have been checked in.
+
 Expansions spanning more than one line and incremental expansions,
 like CVS' $Log$, are not supported. A keyword template map
 "Log = {desc}" expands to the first line of the changeset description.