hgext/keyword.py
changeset 6052 75425961e955
parent 6051 1038b1458d7a
child 6059 d74c5e99d05b
equal deleted inserted replaced
6051:1038b1458d7a 6052:75425961e955
    80 
    80 
    81 from mercurial import commands, cmdutil, context, dispatch, filelog, revlog
    81 from mercurial import commands, cmdutil, context, dispatch, filelog, revlog
    82 from mercurial import patch, localrepo, templater, templatefilters, util
    82 from mercurial import patch, localrepo, templater, templatefilters, util
    83 from mercurial.node import *
    83 from mercurial.node import *
    84 from mercurial.i18n import _
    84 from mercurial.i18n import _
    85 import re, shutil, sys, tempfile, time
    85 import re, shutil, tempfile, time
    86 
    86 
    87 commands.optionalrepo += ' kwdemo'
    87 commands.optionalrepo += ' kwdemo'
    88 
    88 
    89 # hg commands that do not act on keywords
    89 # hg commands that do not act on keywords
    90 nokwcommands = ('add addremove bundle copy export grep identify incoming init'
    90 nokwcommands = ('add addremove bundle copy export grep identify incoming init'
    97 def utcdate(date):
    97 def utcdate(date):
    98     '''Returns hgdate in cvs-like UTC format.'''
    98     '''Returns hgdate in cvs-like UTC format.'''
    99     return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0]))
    99     return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0]))
   100 
   100 
   101 
   101 
   102 _kwtemplater = None
   102 _kwtemplater, _cmd, _cmdoptions = None, None, None
       
   103  
       
   104 # store originals of monkeypatches
       
   105 _patchfile_init = patch.patchfile.__init__
       
   106 _dispatch_parse = dispatch._parse
       
   107 
       
   108 def _kwpatchfile_init(self, ui, fname, missing=False):
       
   109     '''Monkeypatch/wrap patch.patchfile.__init__ to avoid
       
   110     rejects or conflicts due to expanded keywords in working dir.'''
       
   111     _patchfile_init(self, ui, fname, missing=missing)
       
   112     if _kwtemplater.matcher(self.fname):
       
   113         # shrink keywords read from working dir
       
   114         kwshrunk = _kwtemplater.shrink(''.join(self.lines))
       
   115         self.lines = kwshrunk.splitlines(True)
       
   116 
       
   117 def _kwdispatch_parse(ui, args):
       
   118     '''Monkeypatch dispatch._parse to obtain
       
   119     current command and command options (global _cmd, _cmdoptions).'''
       
   120     global _cmd, _cmdoptions
       
   121     _cmd, func, args, options, _cmdoptions = _dispatch_parse(ui, args)
       
   122     return _cmd, func, args, options, _cmdoptions
       
   123 
       
   124 dispatch._parse = _kwdispatch_parse
       
   125 
   103 
   126 
   104 class kwtemplater(object):
   127 class kwtemplater(object):
   105     '''
   128     '''
   106     Sets up keyword templates, corresponding keyword regex, and
   129     Sets up keyword templates, corresponding keyword regex, and
   107     provides keyword substitution functions.
   130     provides keyword substitution functions.
   208         text = _kwtemplater.shrink(text)
   231         text = _kwtemplater.shrink(text)
   209         if self.renamed(node):
   232         if self.renamed(node):
   210             t2 = super(kwfilelog, self).read(node)
   233             t2 = super(kwfilelog, self).read(node)
   211             return t2 != text
   234             return t2 != text
   212         return revlog.revlog.cmp(self, node, text)
   235         return revlog.revlog.cmp(self, node, text)
   213 
       
   214 
       
   215 # store original patch.patchfile.__init__
       
   216 _patchfile_init = patch.patchfile.__init__
       
   217 
       
   218 def _kwpatchfile_init(self, ui, fname, missing=False):
       
   219     '''Monkeypatch/wrap patch.patchfile.__init__ to avoid
       
   220     rejects or conflicts due to expanded keywords in working dir.'''
       
   221     _patchfile_init(self, ui, fname, missing=missing)
       
   222 
       
   223     if _kwtemplater.matcher(self.fname):
       
   224         # shrink keywords read from working dir
       
   225         kwshrunk = _kwtemplater.shrink(''.join(self.lines))
       
   226         self.lines = kwshrunk.splitlines(True)
       
   227 
       
   228 
   236 
   229 def _iskwfile(f, link):
   237 def _iskwfile(f, link):
   230     return not link(f) and _kwtemplater.matcher(f)
   238     return not link(f) and _kwtemplater.matcher(f)
   231 
   239 
   232 def _status(ui, repo, *pats, **opts):
   240 def _status(ui, repo, *pats, **opts):
   408     Wraps commit to overwrite configured files with updated
   416     Wraps commit to overwrite configured files with updated
   409     keyword substitutions.
   417     keyword substitutions.
   410     This is done for local repos only, and only if there are
   418     This is done for local repos only, and only if there are
   411     files configured at all for keyword substitution.'''
   419     files configured at all for keyword substitution.'''
   412 
   420 
       
   421     global _kwtemplater
       
   422     hgcmd, hgcmdopts = _cmd, _cmdoptions
       
   423 
   413     try:
   424     try:
   414         if (not repo.local() or '.hg' in repo.root.split('/')
   425         if (not repo.local() or hgcmd in nokwcommands.split() 
       
   426             or '.hg' in repo.root.split('/')
   415             or repo._url.startswith('bundle:')):
   427             or repo._url.startswith('bundle:')):
   416             return
   428             return
   417     except AttributeError:
   429     except AttributeError:
   418         pass
   430         pass
   419 
       
   420     hgcmd, func, args, opts, cmdopts = dispatch._parse(ui, sys.argv[1:])
       
   421     if hgcmd in nokwcommands.split():
       
   422         return
       
   423 
       
   424     if hgcmd == 'diff':
       
   425         # only expand if comparing against working dir
       
   426         node1, node2 = cmdutil.revpair(repo, cmdopts.get('rev'))
       
   427         if node2 is not None:
       
   428             return
       
   429         # shrink if rev is not current node
       
   430         if node1 is not None and node1 != repo.changectx().node():
       
   431             hgcmd = 'diff1'
       
   432 
   431 
   433     inc, exc = [], ['.hg*']
   432     inc, exc = [], ['.hg*']
   434     for pat, opt in ui.configitems('keyword'):
   433     for pat, opt in ui.configitems('keyword'):
   435         if opt != 'ignore':
   434         if opt != 'ignore':
   436             inc.append(pat)
   435             inc.append(pat)
   437         else:
   436         else:
   438             exc.append(pat)
   437             exc.append(pat)
   439     if not inc:
   438     if not inc:
   440         return
   439         return
   441 
   440 
   442     global _kwtemplater
   441     if hgcmd == 'diff':
       
   442         # only expand if comparing against working dir
       
   443         node1, node2 = cmdutil.revpair(repo, hgcmdopts.get('rev'))
       
   444         if node2 is not None:
       
   445             return
       
   446         # shrink if rev is not current node
       
   447         if node1 is not None and node1 != repo.changectx().node():
       
   448             hgcmd = 'diff1'
       
   449 
   443     restrict = hgcmd in restricted.split()
   450     restrict = hgcmd in restricted.split()
   444     _kwtemplater = kwtemplater(ui, repo, inc, exc, restrict)
   451     _kwtemplater = kwtemplater(ui, repo, inc, exc, restrict)
   445 
   452 
   446     class kwrepo(repo.__class__):
   453     class kwrepo(repo.__class__):
   447         def file(self, f, kwmatch=False):
   454         def file(self, f, kwmatch=False):