hgkw/keyword.py
branch0.9.2compat
changeset 370 a8983fed9a9e
parent 366 b1105cc0982f
child 380 0ed26effe190
equal deleted inserted replaced
366:b1105cc0982f 370:a8983fed9a9e
    83         cause rejects if the patch context contains an active keyword.
    83         cause rejects if the patch context contains an active keyword.
    84         In that case run "hg kwshrink", and then reimport.
    84         In that case run "hg kwshrink", and then reimport.
    85         Or, better, use bundle/unbundle to share changes.
    85         Or, better, use bundle/unbundle to share changes.
    86 '''
    86 '''
    87 
    87 
    88 from mercurial import commands, cmdutil, context, filelog
    88 from mercurial import commands, cmdutil, context
    89 from mercurial import localrepo, revlog, templater, util
    89 from mercurial import localrepo, revlog, templater, util
    90 from mercurial.node import *
    90 from mercurial.node import *
    91 from mercurial.i18n import gettext as _
    91 from mercurial.i18n import gettext as _
    92 import os.path, re, shutil, tempfile, time
    92 import mimetypes, os.path, re, shutil, tempfile, time
    93 
    93 
    94 try:
    94 try:
    95     # avoid spurious rejects if patchfile is available
    95     # avoid spurious rejects if patchfile is available
    96     from mercurial.patch import patchfile
    96     from mercurial.patch import patchfile
    97     _patchfile_init = patchfile.__init__
    97     _patchfile_init = patchfile.__init__
   106     template_filters = templatefilters.filters
   106     template_filters = templatefilters.filters
   107     template_firstline = templatefilters.firstline
   107     template_firstline = templatefilters.firstline
   108 except ImportError:
   108 except ImportError:
   109     template_filters = templater.common_filters
   109     template_filters = templater.common_filters
   110     template_firstline = templater.firstline
   110     template_firstline = templater.firstline
       
   111 
       
   112 try:
       
   113     # webcommands module introduced in 08887121a652
       
   114     from mercurial.hgweb import webcommands
       
   115     _webcommands = True
       
   116     kwweb_func = webcommands.rawfile
       
   117 except ImportError:
       
   118     from mercurial.hgweb import hgweb_mod
       
   119     _webcommands = False
   111 
   120 
   112 def _normal(repo, files):
   121 def _normal(repo, files):
   113     '''Backwards compatible repo.dirstate.normal/update.'''
   122     '''Backwards compatible repo.dirstate.normal/update.'''
   114     # 6fd953d5faea introduced dirstate.normal()
   123     # 6fd953d5faea introduced dirstate.normal()
   115     try:
   124     try:
   188                 c = context.filectx(self.repo, path, fileid=fnode, filelog=fl)
   197                 c = context.filectx(self.repo, path, fileid=fnode, filelog=fl)
   189                 node = c.node()
   198                 node = c.node()
   190             except revlog.LookupError:
   199             except revlog.LookupError:
   191                 # eg: convert
   200                 # eg: convert
   192                 return subfunc == self.re_kw.sub and data or (data, None)
   201                 return subfunc == self.re_kw.sub and data or (data, None)
   193         elif subfunc == self.re_kw.sub:
       
   194             # hg kwcat using kwfilelog.read
       
   195             c = context.filectx(self.repo, path, fileid=node)
       
   196             node = c.node()
       
   197 
   202 
   198         def kwsub(mobj):
   203         def kwsub(mobj):
   199             '''Substitutes keyword using corresponding template.'''
   204             '''Substitutes keyword using corresponding template.'''
   200             kw = mobj.group(1)
   205             kw = mobj.group(1)
   201             self.ct.use_template(self.templates[kw])
   206             self.ct.use_template(self.templates[kw])
   227         '''Returns text with all keyword substitutions removed.'''
   232         '''Returns text with all keyword substitutions removed.'''
   228         if util.binary(data):
   233         if util.binary(data):
   229             return data
   234             return data
   230         return self.re_kw.sub(r'$\1$', data)
   235         return self.re_kw.sub(r'$\1$', data)
   231 
   236 
   232 class kwfilelog(filelog.filelog):
       
   233     '''
       
   234     Subclass of filelog to hook into its read method for kwcat.
       
   235     '''
       
   236     def __init__(self, opener, path, kwt):
       
   237         super(kwfilelog, self).__init__(opener, path)
       
   238         self._kwt = kwt
       
   239         self._path = path
       
   240 
       
   241     def read(self, node):
       
   242         '''Expands keywords when reading filelog.'''
       
   243         data = super(kwfilelog, self).read(node)
       
   244         return self._kwt.expand(self._path, data, node)
       
   245 
   237 
   246 
   238 
   247 def _status(ui, repo, *pats, **opts):
   239 def _status(ui, repo, *pats, **opts):
   248     '''Bails out if [keyword] configuration is not active.
   240     '''Bails out if [keyword] configuration is not active.
   249     Returns status of working directory.'''
   241     Returns status of working directory.'''
   305 
   297 
   306     %s   basename of file being printed
   298     %s   basename of file being printed
   307     %d   dirname of file being printed, or '.' if in repo root
   299     %d   dirname of file being printed, or '.' if in repo root
   308     %p   root-relative path name of file being printed
   300     %p   root-relative path name of file being printed
   309     '''
   301     '''
       
   302     ctx = repo.changectx(opts['rev'])
   310     try:
   303     try:
   311         repo.file = repo._kwfile
   304         repo._kwt.ctx = ctx
       
   305         kw = True
   312     except AttributeError:
   306     except AttributeError:
   313         pass
   307         kw = False
   314     commands.cat(ui, repo, file1, *pats, **opts)
   308     err = 1
       
   309     for src, abs, rel, exact in cmdutil.walk(repo, (file1,) + pats, opts,
       
   310                                              ctx.node()):
       
   311         fp = cmdutil.make_file(repo, opts['output'], ctx.node(), pathname=abs)
       
   312         data = ctx.filectx(abs).data()
       
   313         if kw and repo._kwt.matcher(abs):
       
   314             data = repo._kwt.expand(abs, data, None)
       
   315         fp.write(data)
       
   316         err = 0
       
   317     return err
   315 
   318 
   316 def demo(ui, repo, *args, **opts):
   319 def demo(ui, repo, *args, **opts):
   317     '''print [keywordmaps] configuration and an expansion example
   320     '''print [keywordmaps] configuration and an expansion example
   318 
   321 
   319     Show current, custom, or default keyword template maps
   322     Show current, custom, or default keyword template maps
   452             exc.append(pat)
   455             exc.append(pat)
   453     if not inc:
   456     if not inc:
   454         return
   457         return
   455 
   458 
   456     class kwrepo(repo.__class__):
   459     class kwrepo(repo.__class__):
   457         def _kwfile(self, f):
       
   458             '''Returns filelog expanding keywords on read (for kwcat).'''
       
   459             if f[0] == '/':
       
   460                 f = f[1:]
       
   461             if self._kwt.matcher(f):
       
   462                 return kwfilelog(self.sopener, f, self._kwt)
       
   463             return filelog.filelog(self.sopener, f)
       
   464 
       
   465         def _wreadkwct(self, filename, expand, ctx, node):
   460         def _wreadkwct(self, filename, expand, ctx, node):
   466             '''Reads filename and returns tuple of data with keywords
   461             '''Reads filename and returns tuple of data with keywords
   467             expanded/shrunk and count of keywords (for _overwrite).'''
   462             expanded/shrunk and count of keywords (for _overwrite).'''
   468             data = super(kwrepo, self).wread(filename)
   463             data = super(kwrepo, self).wread(filename)
   469             return self._kwt.process(filename, data, expand, ctx, node)
   464             return self._kwt.process(filename, data, expand, ctx, node)
   576                 kwshrunk = kwt.shrink(''.join(self.lines))
   571                 kwshrunk = kwt.shrink(''.join(self.lines))
   577                 self.lines = kwshrunk.splitlines(True)
   572                 self.lines = kwshrunk.splitlines(True)
   578 
   573 
   579         patchfile.__init__ = kwpatchfile_init
   574         patchfile.__init__ = kwpatchfile_init
   580 
   575 
       
   576     if _webcommands:
       
   577         def kwweb_rawfile(web, req, tmpl):
       
   578             '''Monkeypatch webcommands.rawfile so it expands keywords.'''
       
   579             path = web.cleanpath(req.form.get('file', [''])[0])
       
   580             if not path:
       
   581                 content = web.manifest(tmpl, web.changectx(req), path)
       
   582                 req.respond(webcommands.HTTP_OK, web.ctype)
       
   583                 return content
       
   584             try:
       
   585                 fctx = web.filectx(req)
       
   586             except revlog.LookupError:
       
   587                 content = web.manifest(tmpl, web.changectx(req), path)
       
   588                 req.respond(webcommands.HTTP_OK, web.ctype)
       
   589                 return content
       
   590             path = fctx.path()
       
   591             text = fctx.data()
       
   592             if kwt.matcher(path):
       
   593                 text = kwt.expand(path, text, fctx.node())
       
   594             mt = mimetypes.guess_type(path)[0]
       
   595             if mt is None or util.binary(text):
       
   596                 mt = mt or 'application/octet-stream'
       
   597             req.respond(webcommands.HTTP_OK, mt, path, len(text))
       
   598             return [text]
       
   599 
       
   600         webcommands.rawfile = kwweb_rawfile
       
   601 
       
   602     else:
       
   603         def kwweb_filerevision(self, fctx):
       
   604             '''Monkeypatch hgweb_mod.hgweb.filerevision so keywords are
       
   605             expanded in raw file output.'''
       
   606             f = fctx.path()
       
   607             text = fctx.data()
       
   608             fl = fctx.filelog()
       
   609             n = fctx.filenode()
       
   610             parity = hgweb_mod.paritygen(self.stripecount)
       
   611             mt = mimetypes.guess_type(f)[0]
       
   612             rawtext = text
       
   613             if kwt.matcher(f):
       
   614                 rawtext = kwt.expand(f, text, fctx.node())
       
   615             if util.binary(text):
       
   616                 mt = mt or 'application/octet-stream'
       
   617                 text = "(binary:%s)" % mt
       
   618             mt = mt or 'text/plain'
       
   619             def lines():
       
   620                 for l, t in enumerate(text.splitlines(1)):
       
   621                     yield {"line": t,
       
   622                            "linenumber": "% 6d" % (l + 1),
       
   623                            "parity": parity.next()}
       
   624             yield self.t("filerevision",
       
   625                          file=f,
       
   626                          path=hgweb_mod._up(f),
       
   627                          text=lines(),
       
   628                          raw=rawtext,
       
   629                          mimetype=mt,
       
   630                          rev=fctx.rev(),
       
   631                          node=hex(fctx.node()),
       
   632                          author=fctx.user(),
       
   633                          date=fctx.date(),
       
   634                          desc=fctx.description(),
       
   635                          parent=self.siblings(fctx.parents()),
       
   636                          child=self.siblings(fctx.children()),
       
   637                          rename=self.renamelink(fl, n),
       
   638                          permissions=fctx.manifest().flags(f))
       
   639 
       
   640         hgweb_mod.hgweb.filerevision = kwweb_filerevision
       
   641 
   581     repo.__class__ = kwrepo
   642     repo.__class__ = kwrepo
   582 
   643 
   583 
   644 
   584 cmdtable = {
   645 cmdtable = {
   585     'kwcat':
   646     'kwcat':