Patchwork [2,of,3] templates: introduce revescape filter for escaping symbolic revisions

mail settings
Submitter Anton Shestakov
Date July 13, 2015, 6:03 p.m.
Message ID <92550ccf312faa7d1349.1436810600@neuro>
Download mbox | patch
Permalink /patch/9965/
State Accepted
Headers show


Anton Shestakov - July 13, 2015, 6:03 p.m.
# HG changeset patch
# User Anton Shestakov <>
# Date 1436690876 -28800
#      Sun Jul 12 16:47:56 2015 +0800
# Node ID 92550ccf312faa7d1349eaa9e77ba2035c5504a4
# Parent  fee0e3457eb36b0e23d21682f7df787a01aae598
templates: introduce revescape filter for escaping symbolic revisions

There needs to be a way to escape symbolic revisions containing forward
slashes, but urlescape filter doesn't escape slashes at all (in fact, it is
used in places where forward slashes must be preserved).

The filter considers @ to be safe just for bookmarks like @ and @default to
look good in urls.


diff --git a/mercurial/hgweb/ b/mercurial/hgweb/
--- a/mercurial/hgweb/
+++ b/mercurial/hgweb/
@@ -6,10 +6,11 @@ 
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
-import os, copy, urllib
+import os, copy
 from mercurial import match, patch, error, ui, util, pathutil, context
 from mercurial.i18n import _
 from mercurial.node import hex, nullid, short
+from mercurial.templatefilters import revescape
 from common import ErrorResponse, paritygen
 from common import HTTP_NOT_FOUND
 import difflib
@@ -281,7 +282,7 @@  def changelistentry(web, ctx, tmpl):
 def symrevorshortnode(req, ctx):
     if 'node' in req.form:
-        return urllib.quote(req.form['node'][0])
+        return revescape(req.form['node'][0])
         return short(ctx.node())
diff --git a/mercurial/ b/mercurial/
--- a/mercurial/
+++ b/mercurial/
@@ -283,6 +283,13 @@  def person(author):
     f = author.find('@')
     return author[:f].replace('.', ' ')
+def revescape(text):
+    """:revescape: Any text. Escapes all "special" characters, except @.
+    Forward slashes are escaped twice to prevent web servers from prematurely
+    unescaping them. For example, "@foo bar/baz" becomes "@foo%20bar%252Fbaz".
+    """
+    return urllib.quote(text, safe='/@').replace('/', '%252F')
 def rfc3339date(text):
     """:rfc3339date: Date. Returns a date using the Internet date format
     specified in RFC 3339: "2009-08-18T13:00:13+02:00".
@@ -402,6 +409,7 @@  filters = {
     "obfuscate": obfuscate,
     "permissions": permissions,
     "person": person,
+    "revescape": revescape,
     "rfc3339date": rfc3339date,
     "rfc822date": rfc822date,
     "short": short,