diff --git a/mercurial/dirstate.py b/mercurial/dirstate.py
--- a/mercurial/dirstate.py
+++ b/mercurial/dirstate.py
@@ -677,9 +677,26 @@ class dirstate(object):
# step 3: report unseen items in the dmap hash
if not skipstep3 and not exact:
visit = sorted([f for f in dmap if f not in results and matchfn(f)])
- nf = iter(visit).next
- for st in util.statfiles([join(i) for i in visit]):
- results[nf()] = st
+ if unknown:
+ # unknown == True means we walked the full directory tree above.
+ # So if a file is not seen it was either a) not matching matchfn
+ # b) ignored, c) missing, or d) under a symlink directory.
+ audit_path = scmutil.pathauditor(self._root)
+
+ for nf in iter(visit):
+ # Report ignored items in the dmap as long as they are not
+ # under a symlink directory.
+ if ignore(nf) and audit_path.check(nf):
+ results[nf] = util.statfiles([join(nf)])[0]
+ else:
+ # It's either missing or under a symlink directory
+ results[nf] = None
+ else:
+ # We may not have walked the full directory tree above,
+ # so stat everything we missed.
+ nf = iter(visit).next
+ for st in util.statfiles([join(i) for i in visit]):
+ results[nf()] = st
for s in subrepos:
del results[s]
del results['.hg']
diff --git a/mercurial/extensions.py b/mercurial/extensions.py
--- a/mercurial/extensions.py
+++ b/mercurial/extensions.py
@@ -11,7 +11,7 @@ from i18n import _, gettext
_extensions = {}
_order = []
-_ignore = ['hbisect', 'bookmarks', 'parentrevspec']
+_ignore = ['hbisect', 'bookmarks', 'parentrevspec', 'interhg']
def extensions():
for name in _order:
diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt
--- a/mercurial/help/config.txt
+++ b/mercurial/help/config.txt
@@ -1463,6 +1463,39 @@ The full set of options is:
``templates``
Where to find the HTML templates. Default is install path.
+``websub``
+----------
+
+Web substitution filter definition. You can use this section to
+define a set of regular expression substitution patterns which
+let you automatically modify the hgweb server output.
+
+The default hgweb templates only apply these substitution patterns
+on the revision description fields. You can apply them anywhere
+you want when you create your own templates by adding calls to the
+"websub" filter (usually after calling the "escape" filter).
+
+This can be used, for example, to convert issue references to links
+to your issue tracker, or to convert "markdown-like" syntax into
+HTML (see the examples below).
+
+Each entry in this section names a substitution filter.
+The value of each entry defines the substitution expression itself.
+The websub expressions follow the old interhg extension syntax,
+which in turn imitates the Unix sed replacement syntax::
+
+ pattername = s/SEARCH_REGEX/REPLACE_EXPRESSION/[i]
+
+You can use any separator other than "/". The final "i" is optional
+and indicates that the search must be case insensitive.
+
+Examples::
+
+ [websub]
+ issues = s|issue(\d+)|issue\1|i
+ italic = s/\b_(\S+)_\b/\1<\/i>/
+ bold = s/\*\b(\S+)\b\*/\1<\/b>/
+
``worker``
----------
diff --git a/mercurial/hgweb/hgweb_mod.py b/mercurial/hgweb/hgweb_mod.py
--- a/mercurial/hgweb/hgweb_mod.py
+++ b/mercurial/hgweb/hgweb_mod.py
@@ -8,11 +8,13 @@
import os
from mercurial import ui, hg, hook, error, encoding, templater, util, repoview
+from mercurial.templatefilters import websub
+from mercurial.i18n import _
from common import get_stat, ErrorResponse, permhooks, caching
from common import HTTP_OK, HTTP_NOT_MODIFIED, HTTP_BAD_REQUEST
from common import HTTP_NOT_FOUND, HTTP_SERVER_ERROR
from request import wsgirequest
-import webcommands, protocol, webutil
+import webcommands, protocol, webutil, re
perms = {
'changegroup': 'pull',
@@ -73,6 +75,7 @@ class hgweb(object):
# a repo owner may set web.templates in .hg/hgrc to get any file
# readable by the user running the CGI script
self.templatepath = self.config('web', 'templates')
+ self.websubtable = self.loadwebsub()
# The CGI scripts are often run by a user different from the repo owner.
# Trust the settings from the .hg/hgrc files by default.
@@ -258,6 +261,47 @@ class hgweb(object):
return ['']
return tmpl('error', error=inst.message)
+ def loadwebsub(self):
+ websubtable = []
+ websubdefs = self.repo.ui.configitems('websub')
+ # we must maintain interhg backwards compatibility
+ websubdefs += self.repo.ui.configitems('interhg')
+ for key, pattern in websubdefs:
+ # grab the delimiter from the character after the "s"
+ unesc = pattern[1]
+ delim = re.escape(unesc)
+
+ # identify portions of the pattern, taking care to avoid escaped
+ # delimiters. the replace format and flags are optional, but
+ # delimiters are required.
+ match = re.match(
+ r'^s%s(.+)(?:(?<=\\\\)|(?{author|obfuscate} [{date|rfc822date}] rev {rev}
description: | -{desc|strip|escape|addbreaks|nonempty} | +{desc|strip|escape|websub|addbreaks|nonempty} |
---|