diff --git a/hgext/extdiff.py b/hgext/extdiff.py --- a/hgext/extdiff.py +++ b/hgext/extdiff.py @@ -342,7 +342,7 @@ class savedcmd(object): def __init__(self, path, cmdline): # We can't pass non-ASCII through docstrings (and path is # in an unknown encoding anyway) - docpath = path.encode("string-escape") + docpath = util.escapestr(path) self.__doc__ = self.__doc__ % {'path': util.uirepr(docpath)} self._cmdline = cmdline diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py --- a/mercurial/cmdutil.py +++ b/mercurial/cmdutil.py @@ -1300,7 +1300,7 @@ class changeset_printer(object): for key, value in sorted(extra.items()): # i18n: column positioning for "hg log" self.ui.write(_("extra: %s=%s\n") - % (key, value.encode('string_escape')), + % (key, util.escapestr(value)), label='ui.debug log.extra') description = ctx.description().strip() diff --git a/mercurial/debugcommands.py b/mercurial/debugcommands.py --- a/mercurial/debugcommands.py +++ b/mercurial/debugcommands.py @@ -1514,8 +1514,8 @@ def debugpushkey(ui, repopath, namespace return not r else: for k, v in sorted(target.listkeys(namespace).iteritems()): - ui.write("%s\t%s\n" % (k.encode('string-escape'), - v.encode('string-escape'))) + ui.write("%s\t%s\n" % (util.escapestr(k), + util.escapestr(v))) @command('debugpvec', [], _('A B')) def debugpvec(ui, repo, a, b=None): diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py --- a/mercurial/subrepo.py +++ b/mercurial/subrepo.py @@ -130,7 +130,7 @@ def state(ctx, ui): for pattern, repl in p.items('subpaths'): # Turn r'C:\foo\bar' into r'C:\\foo\\bar' since re.sub # does a string decode. - repl = repl.encode('string-escape') + repl = util.escapestr(repl) # However, we still want to allow back references to go # through unharmed, so we turn r'\\1' into r'\1'. Again, # extra escapes are needed because re.sub string decodes. diff --git a/mercurial/templatefilters.py b/mercurial/templatefilters.py --- a/mercurial/templatefilters.py +++ b/mercurial/templatefilters.py @@ -345,7 +345,7 @@ def splitlines(text): @templatefilter('stringescape') def stringescape(text): - return text.encode('string_escape') + return util.escapestr(text) @templatefilter('stringify') def stringify(thing): diff --git a/mercurial/util.py b/mercurial/util.py --- a/mercurial/util.py +++ b/mercurial/util.py @@ -2130,6 +2130,9 @@ bytecount = unitcountfn( (1, 1, _('%.0f bytes')), ) +def escapestr(s): + return s.encode('string_escape') + def uirepr(s): # Avoid double backslash in Windows path repr() return repr(s).replace('\\\\', '\\') diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py --- a/mercurial/wireproto.py +++ b/mercurial/wireproto.py @@ -900,7 +900,7 @@ def known(repo, proto, nodes, others): def pushkey(repo, proto, namespace, key, old, new): # compatibility with pre-1.8 clients which were accidentally # sending raw binary nodes rather than utf-8-encoded hex - if len(new) == 20 and new.encode('string-escape') != new: + if len(new) == 20 and util.escapestr(new) != new: # looks like it could be a binary node try: new.decode('utf-8')