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