Re: [PATCH] fix: use templater to substitute values in command string

2018-04-18 Thread Kevin Bullock
> On Apr 14, 2018, at 00:25, Yuya Nishihara  wrote:
> 
> # HG changeset patch
> # User Yuya Nishihara 
> # Date 1523633439 -32400
> #  Sat Apr 14 00:30:39 2018 +0900
> # Node ID c11220384fc8e9bea55193401835a60d241c372f
> # Parent  611a3c98d1b68836b5725a0d97c0ae1f0b3677f6
> fix: use templater to substitute values in command string
> 
> bytes.format() isn't supported on Python 3. Luckily, our template syntax
> is similar so we can reuse it. We need a hack to disable \-escapes as '\'
> is a directory separator on Windows.

It's quite the hack ;) But I'll take it. Queued.

pacem in terris / мир / शान्ति / ‎‫سَلاَم‬ / 平和
Kevin R. Bullock

___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel


[PATCH] fix: use templater to substitute values in command string

2018-04-13 Thread Yuya Nishihara
# HG changeset patch
# User Yuya Nishihara 
# Date 1523633439 -32400
#  Sat Apr 14 00:30:39 2018 +0900
# Node ID c11220384fc8e9bea55193401835a60d241c372f
# Parent  611a3c98d1b68836b5725a0d97c0ae1f0b3677f6
fix: use templater to substitute values in command string

bytes.format() isn't supported on Python 3. Luckily, our template syntax
is similar so we can reuse it. We need a hack to disable \-escapes as '\'
is a directory separator on Windows.

diff --git a/hgext/fix.py b/hgext/fix.py
--- a/hgext/fix.py
+++ b/hgext/fix.py
@@ -387,7 +387,7 @@ def fixfile(ui, opts, fixers, fixctx, pa
 for fixername, fixer in fixers.iteritems():
 if fixer.affects(opts, fixctx, path):
 ranges = lineranges(opts, path, basectxs, fixctx, newdata)
-command = fixer.command(path, ranges)
+command = fixer.command(ui, path, ranges)
 if command is None:
 continue
 ui.debug('subprocess: %s\n' % (command,))
@@ -534,18 +534,20 @@ class Fixer(object):
 """Should this fixer run on the file at the given path and context?"""
 return scmutil.match(fixctx, [self._fileset], opts)(path)
 
-def command(self, path, ranges):
+def command(self, ui, path, ranges):
 """A shell command to use to invoke this fixer on the given file/lines
 
 May return None if there is no appropriate command to run for the given
 parameters.
 """
-parts = [self._command.format(rootpath=path,
-  basename=os.path.basename(path))]
+expand = cmdutil.rendercommandtemplate
+parts = [expand(ui, self._command,
+{'rootpath': path, 'basename': 
os.path.basename(path)})]
 if self._linerange:
 if not ranges:
 # No line ranges to fix, so don't run the fixer.
 return None
 for first, last in ranges:
-parts.append(self._linerange.format(first=first, last=last))
+parts.append(expand(ui, self._linerange,
+{'first': first, 'last': last}))
 return ' '.join(parts)
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -899,6 +899,33 @@ def getcommiteditor(edit=False, finishde
 else:
 return commiteditor
 
+def _escapecommandtemplate(tmpl):
+parts = []
+for typ, start, end in templater.scantemplate(tmpl, raw=True):
+if typ == b'string':
+parts.append(stringutil.escapestr(tmpl[start:end]))
+else:
+parts.append(tmpl[start:end])
+return b''.join(parts)
+
+def rendercommandtemplate(ui, tmpl, props):
+r"""Expand a literal template 'tmpl' in a way suitable for command line
+
+'\' in outermost string is not taken as an escape character because it
+is a directory separator on Windows.
+
+>>> from . import ui as uimod
+>>> ui = uimod.ui()
+>>> rendercommandtemplate(ui, b'c:\\{path}', {b'path': b'foo'})
+'c:\\foo'
+>>> rendercommandtemplate(ui, b'{"c:\\{path}"}', {'path': b'foo'})
+'c:{path}'
+"""
+if not tmpl:
+return tmpl
+t = formatter.maketemplater(ui, _escapecommandtemplate(tmpl))
+return t.renderdefault(props)
+
 def rendertemplate(ctx, tmpl, props=None):
 """Expand a literal template 'tmpl' byte-string against one changeset
 
___
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel