Mercurial > hg
changeset 37774:d6970628b95f
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.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sat, 14 Apr 2018 00:30:39 +0900 |
parents | 0f084741cd66 |
children | 03d7f885d5f2 |
files | hgext/fix.py mercurial/cmdutil.py |
diffstat | 2 files changed, 34 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/hgext/fix.py Fri Apr 13 23:07:12 2018 +0900 +++ b/hgext/fix.py Sat Apr 14 00:30:39 2018 +0900 @@ -387,7 +387,7 @@ 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 @@ """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)
--- a/mercurial/cmdutil.py Fri Apr 13 23:07:12 2018 +0900 +++ b/mercurial/cmdutil.py Sat Apr 14 00:30:39 2018 +0900 @@ -904,6 +904,33 @@ 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