hgkw/keyword.py
branchkwmap-templates
changeset 129 15e8cd7f5295
parent 128 fe37939db543
child 133 cb60196a500b
equal deleted inserted replaced
128:fe37939db543 129:15e8cd7f5295
    71 hgrc files.
    71 hgrc files.
    72 '''
    72 '''
    73 
    73 
    74 from mercurial.i18n import gettext as _
    74 from mercurial.i18n import gettext as _
    75 # above line for backwards compatibility of standalone version
    75 # above line for backwards compatibility of standalone version
    76 from mercurial import commands, cmdutil, templater, util
    76 from mercurial import cmdutil, templater, util
    77 from mercurial import context, filelog, revlog
    77 from mercurial import context, filelog, revlog
    78 from mercurial.node import bin
    78 import os.path, re, time
    79 import os.path, re, sys, time
       
    80 
    79 
    81 deftemplates = {
    80 deftemplates = {
    82         'Revision': '{node|short}',
    81         'Revision': '{node|short}',
    83         'Author': '{author|user}',
    82         'Author': '{author|user}',
    84         'Date': '{date|utcdate}',
    83         'Date': '{date|utcdate}',
    89         }
    88         }
    90 
    89 
    91 def utcdate(date):
    90 def utcdate(date):
    92     '''Returns hgdate in cvs-like UTC format.'''
    91     '''Returns hgdate in cvs-like UTC format.'''
    93     return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0]))
    92     return time.strftime('%Y/%m/%d %H:%M:%S', time.gmtime(date[0]))
    94 
       
    95 def getmodulename():
       
    96     '''Makes sure pretxncommit-hook can import keyword module
       
    97     regardless of where its located.'''
       
    98     for k, v in sys.modules.iteritems():
       
    99         if v is None or not hasattr(v, '__file__'):
       
   100             continue
       
   101         if v.__file__.startswith(__file__):
       
   102             return k
       
   103     else:
       
   104         sys.path.insert(0, os.path.abspath(os.path.dirname(__file__)))
       
   105         return os.path.splitext(os.path.basename(__file__))[0]
       
   106 
    93 
   107 class kwtemplater(object):
    94 class kwtemplater(object):
   108     '''
    95     '''
   109     Sets up keyword templates, corresponding keyword regex, and
    96     Sets up keyword templates, corresponding keyword regex, and
   110     provides keyword expansion function.
    97     provides keyword expansion function.
   150     class kwrepo(repo.__class__):
   137     class kwrepo(repo.__class__):
   151         def file(self, f):
   138         def file(self, f):
   152             if f[0] == '/':
   139             if f[0] == '/':
   153                 f = f[1:]
   140                 f = f[1:]
   154             return filelog.filelog(self.sopener, f, self, self.revlogversion)
   141             return filelog.filelog(self.sopener, f, self, self.revlogversion)
       
   142 
       
   143         def commit(self, files=None, text="", user=None, date=None,
       
   144                 match=util.always, force=False, lock=None, wlock=None,
       
   145                 force_editor=False, p1=None, p2=None, extra={}):
       
   146             '''Wraps commit, expanding keywords of committed and
       
   147             configured files in working directory.'''
       
   148 
       
   149             node = super(kwrepo, self).commit(files=files,
       
   150                     text=text, user=user, date=date,
       
   151                     match=match, force=force, lock=lock, wlock=wlock,
       
   152                     force_editor=force_editor, p1=p1, p2=p2, extra=extra)
       
   153             if node is None:
       
   154                 return node
       
   155 
       
   156             candidates = self.changelog.read(node)[3]
       
   157             candidates = [f for f in candidates
       
   158                     if self.kwfmatcher(f) and os.path.isfile(self.wjoin(f))]
       
   159             if not candidates:
       
   160                 return node
       
   161 
       
   162             kwt = kwtemplater(self.ui, self)
       
   163             overwrite = []
       
   164             for f in candidates:
       
   165                 data = self.wfile(f).read()
       
   166                 if not util.binary(data):
       
   167                     data, kwct = kwt.re_kw.subn(lambda m:
       
   168                             kwt.expand(m, f, node), data)
       
   169                     if kwct:
       
   170                         ui.debug(_('overwriting %s expanding keywords\n' % f))
       
   171                         self.wfile(f, 'w').write(data)
       
   172                         overwrite.append(f)
       
   173             self.dirstate.update(overwrite, 'n')
       
   174             return node
   155 
   175 
   156     class kwfilelog(filelog.filelog):
   176     class kwfilelog(filelog.filelog):
   157         '''
   177         '''
   158         Superclass over filelog to customize it's read, add, cmp methods.
   178         Superclass over filelog to customize it's read, add, cmp methods.
   159         Keywords are "stored" unexpanded, and expanded on reading.
   179         Keywords are "stored" unexpanded, and expanded on reading.
   196                 text = self.kwt.re_kw.sub(r'$\1$', text)
   216                 text = self.kwt.re_kw.sub(r'$\1$', text)
   197             return super(kwfilelog, self).cmp(node, text)
   217             return super(kwfilelog, self).cmp(node, text)
   198 
   218 
   199     filelog.filelog = kwfilelog
   219     filelog.filelog = kwfilelog
   200     repo.__class__ = kwrepo
   220     repo.__class__ = kwrepo
   201     # configure pretxncommit hook
       
   202     repo.ui.setconfig('hooks', 'pretxncommit.keyword',
       
   203             'python:%s.pretxnkw' % getmodulename())
       
   204 
       
   205 
       
   206 def pretxnkw(ui, repo, hooktype, **args):
       
   207     '''pretxncommit hook that collects candidates for keyword expansion
       
   208     on commit and expands keywords in working dir.'''
       
   209 
       
   210     cmd, sysargs, globalopts, cmdopts = commands.parse(ui, sys.argv[1:])[1:]
       
   211     if repr(cmd).split()[1] in ('tag', 'import_'):
       
   212         return
       
   213 
       
   214     files, match, anypats = cmdutil.matchpats(repo, sysargs, cmdopts)
       
   215     modified, added = repo.status(files=files, match=match)[:2]
       
   216     candidates = [f for f in modified + added if repo.kwfmatcher(f)]
       
   217     if not candidates:
       
   218         return
       
   219 
       
   220     kwt = kwtemplater(ui, repo)
       
   221     node = bin(args['node'])
       
   222     for f in candidates:
       
   223         data = repo.wfile(f).read()
       
   224         if not util.binary(data):
       
   225             data, kwct = kwt.re_kw.subn(lambda m: kwt.expand(m, f, node), data)
       
   226             if kwct:
       
   227                 ui.debug(_('overwriting %s expanding keywords\n' % f))
       
   228                 repo.wfile(f, 'w').write(data)