hgkw/keyword.py
changeset 340 9e9f6cbcf20b
parent 335 9f78d508764b
child 341 5ef2b11df3d3
equal deleted inserted replaced
338:d924ed135d9a 340:9e9f6cbcf20b
    69 the risk of inadvertedly storing expanded keywords in the change history.
    69 the risk of inadvertedly storing expanded keywords in the change history.
    70 
    70 
    71 To force expansion after enabling it, or a configuration change, run
    71 To force expansion after enabling it, or a configuration change, run
    72 "hg kwexpand".
    72 "hg kwexpand".
    73 
    73 
       
    74 Also, when committing with the record extension or using mq's qrecord, be aware
       
    75 that keywords cannot be updated. Again, run "hg kwexpand" on the files in
       
    76 question to update keyword expansions after all changes have been checked in.
       
    77 
    74 Expansions spanning more than one line and incremental expansions,
    78 Expansions spanning more than one line and incremental expansions,
    75 like CVS' $Log$, are not supported. A keyword template map
    79 like CVS' $Log$, are not supported. A keyword template map
    76 "Log = {desc}" expands to the first line of the changeset description.
    80 "Log = {desc}" expands to the first line of the changeset description.
    77 '''
    81 '''
    78 
    82 
    79 from mercurial import commands, cmdutil, context, fancyopts, filelog
    83 from mercurial import commands, cmdutil, context, dispatch, filelog
    80 from mercurial import patch, localrepo, revlog, templater, util
    84 from mercurial import patch, localrepo, revlog, templater, util
    81 from mercurial.node import *
    85 from mercurial.node import *
    82 from mercurial.i18n import _
    86 from mercurial.i18n import _
    83 import re, shutil, sys, tempfile, time
    87 import re, shutil, sys, tempfile, time
    84 
    88 
    85 commands.optionalrepo += ' kwdemo'
    89 commands.optionalrepo += ' kwdemo'
    86 
    90 
    87 def utcdate(date):
    91 def utcdate(date):
    88     '''Returns hgdate in cvs-like UTC format.'''
    92     '''Returns hgdate in cvs-like UTC format.'''
    89     return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0]))
    93     return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0]))
       
    94 
       
    95 def _kwrestrict(cmd):
       
    96     '''Returns True if cmd should trigger restricted expansion.
       
    97     Keywords will only expanded when writing to working dir.
       
    98     Crucial for mq as expanded keywords should not make it into patches.'''
       
    99     return cmd in ('qimport', 'qnew', 'qpush', 'qrefresh', 'record', 'qrecord')
       
   100 
    90 
   101 
    91 _kwtemplater = None
   102 _kwtemplater = None
    92 
   103 
    93 class kwtemplater(object):
   104 class kwtemplater(object):
    94     '''
   105     '''
   103         'Source': '{root}/{file},v',
   114         'Source': '{root}/{file},v',
   104         'Id': '{file|basename},v {node|short} {date|utcdate} {author|user}',
   115         'Id': '{file|basename},v {node|short} {date|utcdate} {author|user}',
   105         'Header': '{root}/{file},v {node|short} {date|utcdate} {author|user}',
   116         'Header': '{root}/{file},v {node|short} {date|utcdate} {author|user}',
   106     }
   117     }
   107 
   118 
   108     def __init__(self, ui, repo, inc, exc):
   119     def __init__(self, ui, repo, inc, exc, hgcmd):
   109         self.ui = ui
   120         self.ui = ui
   110         self.repo = repo
   121         self.repo = repo
   111         self.matcher = util.matcher(repo.root, inc=inc, exc=exc)[1]
   122         self.matcher = util.matcher(repo.root, inc=inc, exc=exc)[1]
       
   123         self.hgcmd = hgcmd
   112         self.commitnode = None
   124         self.commitnode = None
   113         self.path = ''
   125         self.path = ''
   114 
   126 
   115         kwmaps = self.ui.configitems('keywordmaps')
   127         kwmaps = self.ui.configitems('keywordmaps')
   116         if kwmaps: # override default templates
   128         if kwmaps: # override default templates
   144 
   156 
   145         return subfunc(kwsub, data)
   157         return subfunc(kwsub, data)
   146 
   158 
   147     def expand(self, node, data):
   159     def expand(self, node, data):
   148         '''Returns data with keywords expanded.'''
   160         '''Returns data with keywords expanded.'''
   149         if util.binary(data):
   161         if util.binary(data) or _kwrestrict(self.hgcmd):
   150             return data
   162             return data
   151         return self.substitute(node, data, self.re_kw.sub)
   163         return self.substitute(node, data, self.re_kw.sub)
   152 
   164 
   153     def process(self, node, data, expand):
   165     def process(self, node, data, expand):
   154         '''Returns a tuple: data, count.
   166         '''Returns a tuple: data, count.
   395     Wraps commit to overwrite configured files with updated
   407     Wraps commit to overwrite configured files with updated
   396     keyword substitutions.
   408     keyword substitutions.
   397     This is done for local repos only, and only if there are
   409     This is done for local repos only, and only if there are
   398     files configured at all for keyword substitution.'''
   410     files configured at all for keyword substitution.'''
   399 
   411 
   400     def kwbailout():
   412     if not repo.local():
   401         '''Obtains command via simplified cmdline parsing,
   413         return
   402         returns True if keyword expansion not needed.'''
   414 
   403         nokwcommands = ('add', 'addremove', 'bundle', 'clone', 'copy',
   415     nokwcommands = ('add', 'addremove', 'bundle', 'clone', 'copy',
   404                         'export', 'grep', 'identify', 'incoming', 'init',
   416                     'export', 'grep', 'identify', 'incoming', 'init',
   405                         'log', 'outgoing', 'push', 'remove', 'rename',
   417                     'log', 'outgoing', 'push', 'remove', 'rename',
   406                         'rollback', 'tip',
   418                     'rollback', 'tip',
   407                         'convert')
   419                     'convert')
   408         args = fancyopts.fancyopts(sys.argv[1:], commands.globalopts, {})
   420     hgcmd, func, args, opts, cmdopts = dispatch._parse(ui, sys.argv[1:])
   409         if args:
   421     if hgcmd in nokwcommands:
   410             aliases, i = cmdutil.findcmd(ui, args[0], commands.table)
       
   411             return aliases[0] in nokwcommands
       
   412 
       
   413     if not repo.local() or kwbailout():
       
   414         return
   422         return
   415 
   423 
   416     inc, exc = [], ['.hgtags']
   424     inc, exc = [], ['.hgtags']
   417     for pat, opt in ui.configitems('keyword'):
   425     for pat, opt in ui.configitems('keyword'):
   418         if opt != 'ignore':
   426         if opt != 'ignore':
   421             exc.append(pat)
   429             exc.append(pat)
   422     if not inc:
   430     if not inc:
   423         return
   431         return
   424 
   432 
   425     global _kwtemplater
   433     global _kwtemplater
   426     _kwtemplater = kwtemplater(ui, repo, inc, exc)
   434     _kwtemplater = kwtemplater(ui, repo, inc, exc, hgcmd)
   427 
   435 
   428     class kwrepo(repo.__class__):
   436     class kwrepo(repo.__class__):
   429         def file(self, f, kwmatch=False):
   437         def file(self, f, kwmatch=False):
   430             if f[0] == '/':
   438             if f[0] == '/':
   431                 f = f[1:]
   439                 f = f[1:]
   432             if kwmatch or _kwtemplater.matcher(f):
   440             if kwmatch or _kwtemplater.matcher(f):
   433                 return kwfilelog(self.sopener, f)
   441                 return kwfilelog(self.sopener, f)
   434             return filelog.filelog(self.sopener, f)
   442             return filelog.filelog(self.sopener, f)
       
   443 
       
   444         def wread(self, filename):
       
   445             data = super(kwrepo, self).wread(filename)
       
   446             if _kwrestrict(hgcmd) and _kwtemplater.matcher(filename):
       
   447                 return _kwtemplater.shrink(data)
       
   448             return data
   435 
   449 
   436         def commit(self, files=None, text='', user=None, date=None,
   450         def commit(self, files=None, text='', user=None, date=None,
   437                    match=util.always, force=False, force_editor=False,
   451                    match=util.always, force=False, force_editor=False,
   438                    p1=None, p2=None, extra={}):
   452                    p1=None, p2=None, extra={}):
   439             wlock = lock = None
   453             wlock = lock = None