Patchwork [4,of,4] templater: look up symbols/resources as if they were separated (issue5699)

login
register
mail settings
Submitter Yuya Nishihara
Date Dec. 21, 2017, 3:08 p.m.
Message ID <9d50cfedc380d05dfbe0.1513868927@mimosa>
Download mbox | patch
Permalink /patch/26382/
State Accepted
Headers show

Comments

Yuya Nishihara - Dec. 21, 2017, 3:08 p.m.
# HG changeset patch
# User Yuya Nishihara <yuya@tcha.org>
# Date 1513862259 -32400
#      Thu Dec 21 22:17:39 2017 +0900
# Node ID 9d50cfedc380d05dfbe0ed8b9360603b61b3c601
# Parent  c06827f22f361f8e1ff3431c18ed0734708149ed
templater: look up symbols/resources as if they were separated (issue5699)

It wouldn't be easy to split the mapping dict into (symbols, resources). This
patch instead rejects invalid lookup taking resources.keys() as source of
truth.

The doctest is updated since mapping['repo'] is now reserved for a repo
object.

Patch

diff --git a/mercurial/formatter.py b/mercurial/formatter.py
--- a/mercurial/formatter.py
+++ b/mercurial/formatter.py
@@ -94,14 +94,14 @@  Nested example:
 
 >>> def subrepos(ui, fm):
 ...     fm.startitem()
-...     fm.write(b'repo', b'[%s]\\n', b'baz')
+...     fm.write(b'reponame', b'[%s]\\n', b'baz')
 ...     files(ui, fm.nested(b'files'))
 ...     fm.end()
 >>> show(subrepos)
 [baz]
 foo
 bar
->>> show(subrepos, template=b'{repo}: {join(files % "{path}", ", ")}\\n')
+>>> show(subrepos, template=b'{reponame}: {join(files % "{path}", ", ")}\\n')
 baz: foo, bar
 """
 
@@ -491,7 +491,9 @@  def templateresources(ui, repo=None):
     and function"""
     return {
         'cache': {},  # for templatekw/funcs to store reusable data
+        'ctx': None,
         'repo': repo,
+        'revcache': None,  # per-ctx cache; set later
         'ui': ui,
     }
 
diff --git a/mercurial/templater.py b/mercurial/templater.py
--- a/mercurial/templater.py
+++ b/mercurial/templater.py
@@ -1320,7 +1320,9 @@  class engine(object):
 
     def symbol(self, mapping, key):
         """Resolve symbol to value or function; None if nothing found"""
-        v = mapping.get(key)
+        v = None
+        if key not in self._resources:
+            v = mapping.get(key)
         if v is None:
             v = self._defaults.get(key)
         return v
@@ -1328,11 +1330,13 @@  class engine(object):
     def resource(self, mapping, key):
         """Return internal data (e.g. cache) used for keyword/function
         evaluation"""
-        v = mapping.get(key)
+        v = None
+        if key in self._resources:
+            v = mapping.get(key)
         if v is None:
             v = self._resources.get(key)
         if v is None:
-            raise KeyError
+            raise error.Abort(_('template resource not available: %s') % key)
         return v
 
     def _load(self, t):
diff --git a/tests/test-command-template.t b/tests/test-command-template.t
--- a/tests/test-command-template.t
+++ b/tests/test-command-template.t
@@ -206,7 +206,13 @@  never cause crash:
 
 Internal resources shouldn't be exposed (issue5699):
 
-  $ hg log -r. -T '{cache}{repo}{templ}{ui}'
+  $ hg log -r. -T '{cache}{ctx}{repo}{revcache}{templ}{ui}'
+
+Never crash on internal resource not available:
+
+  $ hg --cwd .. debugtemplate '{"c0bebeef"|shortest}\n'
+  abort: template resource not available: ctx
+  [255]
 
 Quoting for ui.logtemplate