--- a/mercurial/dirstate.py Sun Feb 10 16:55:01 2013 +0000
+++ b/mercurial/dirstate.py Mon Feb 11 01:21:24 2013 +0100
@@ -693,9 +693,26 @@
# 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']
--- a/mercurial/extensions.py Sun Feb 10 16:55:01 2013 +0000
+++ b/mercurial/extensions.py Mon Feb 11 01:21:24 2013 +0100
@@ -11,7 +11,7 @@
_extensions = {}
_order = []
-_ignore = ['hbisect', 'bookmarks', 'parentrevspec']
+_ignore = ['hbisect', 'bookmarks', 'parentrevspec', 'interhg']
def extensions():
for name in _order:
--- a/mercurial/help/config.txt Sun Feb 10 16:55:01 2013 +0000
+++ b/mercurial/help/config.txt Mon Feb 11 01:21:24 2013 +0100
@@ -1463,6 +1463,39 @@
``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+)|<a href="http://bts.example.org/issue\1">issue\1</a>|i
+ italic = s/\b_(\S+)_\b/<i>\1<\/i>/
+ bold = s/\*\b(\S+)\b\*/<b>\1<\/b>/
+
``worker``
----------
--- a/mercurial/hgweb/hgweb_mod.py Sun Feb 10 16:55:01 2013 +0000
+++ b/mercurial/hgweb/hgweb_mod.py Mon Feb 11 01:21:24 2013 +0100
@@ -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 @@
# 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 @@
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(.+)(?:(?<=\\\\)|(?<!\\))%s(.*)%s([ilmsux])*$'
+ % (delim, delim, delim), pattern)
+ if not match:
+ self.repo.ui.warn(_("websub: invalid pattern for %s: %s\n")
+ % (key, pattern))
+ continue
+
+ # we need to unescape the delimiter for regexp and format
+ delim_re = re.compile(r'(?<!\\)\\%s' % delim)
+ regexp = delim_re.sub(unesc, match.group(1))
+ format = delim_re.sub(unesc, match.group(2))
+
+ # the pattern allows for 6 regexp flags, so set them if necessary
+ flagin = match.group(3)
+ flags = 0
+ if flagin:
+ for flag in flagin.upper():
+ flags |= re.__dict__[flag]
+
+ try:
+ regexp = re.compile(regexp, flags)
+ websubtable.append((regexp, format))
+ except re.error:
+ self.repo.ui.warn(_("websub: invalid regexp for %s: %s\n")
+ % (key, regexp))
+ return websubtable
+
def templater(self, req):
# determine scheme, port and server name
@@ -311,9 +355,13 @@
or req.env.get('REPO_NAME')
or req.url.strip('/') or self.repo.root)
+ def websubfilter(text):
+ return websub(text, self.websubtable)
+
# create the templater
tmpl = templater.templater(mapfile,
+ filters={"websub": websubfilter},
defaults={"url": req.url,
"logourl": logourl,
"logoimg": logoimg,
--- a/mercurial/scmutil.py Sun Feb 10 16:55:01 2013 +0000
+++ b/mercurial/scmutil.py Mon Feb 11 01:21:24 2013 +0100
@@ -184,6 +184,13 @@
# want to add "foo/bar/baz" before checking if there's a "foo/.hg"
self.auditeddir.update(prefixes)
+ def check(self, path):
+ try:
+ self(path)
+ return True
+ except (OSError, util.Abort):
+ return False
+
class abstractvfs(object):
"""Abstract base class; cannot be instantiated"""
@@ -745,21 +752,14 @@
ctx = repo[None]
walkresults = repo.dirstate.walk(m, sorted(ctx.substate), True, False)
for abs in sorted(walkresults):
- good = True
- try:
- audit_path(abs)
- except (OSError, util.Abort):
- good = False
-
st = walkresults[abs]
dstate = repo.dirstate[abs]
- if good and dstate == '?':
+ if dstate == '?' and audit_path.check(abs):
unknown.append(abs)
if repo.ui.verbose or not m.exact(abs):
rel = m.rel(abs)
repo.ui.status(_('adding %s\n') % ((pats and rel) or abs))
- elif (dstate != 'r' and
- (not good or not st or
+ elif (dstate != 'r' and (not st or
(stat.S_ISDIR(st.st_mode) and not stat.S_ISLNK(st.st_mode)))):
deleted.append(abs)
if repo.ui.verbose or not m.exact(abs):
--- a/mercurial/templatefilters.py Sun Feb 10 16:55:01 2013 +0000
+++ b/mercurial/templatefilters.py Mon Feb 11 01:21:24 2013 +0100
@@ -391,6 +391,15 @@
"xmlescape": xmlescape,
}
+def websub(text, websubtable):
+ """:websub: Any text. Only applies to hgweb. Applies the regular
+ expression replacements defined in the websub section.
+ """
+ if websubtable:
+ for regexp, format in websubtable:
+ text = regexp.sub(format, text)
+ return text
+
def fillfunc(context, mapping, args):
if not (1 <= len(args) <= 2):
raise error.ParseError(_("fill expects one or two arguments"))
--- a/mercurial/templates/gitweb/changelogentry.tmpl Sun Feb 10 16:55:01 2013 +0000
+++ b/mercurial/templates/gitweb/changelogentry.tmpl Mon Feb 11 01:21:24 2013 +0100
@@ -8,7 +8,7 @@
<i>{author|obfuscate} [{date|rfc822date}] rev {rev}</i><br/>
</div>
<div class="log_body">
-{desc|strip|escape|addbreaks|nonempty}
+{desc|strip|escape|websub|addbreaks|nonempty}
<br/>
<br/>
</div>
--- a/mercurial/templates/gitweb/changeset.tmpl Sun Feb 10 16:55:01 2013 +0000
+++ b/mercurial/templates/gitweb/changeset.tmpl Mon Feb 11 01:21:24 2013 +0100
@@ -41,7 +41,7 @@
</table></div>
<div class="page_body">
-{desc|strip|escape|addbreaks|nonempty}
+{desc|strip|escape|websub|addbreaks|nonempty}
</div>
<div class="list_head"></div>
<div class="title_text">
--- a/mercurial/templates/gitweb/fileannotate.tmpl Sun Feb 10 16:55:01 2013 +0000
+++ b/mercurial/templates/gitweb/fileannotate.tmpl Mon Feb 11 01:21:24 2013 +0100
@@ -56,7 +56,7 @@
</div>
<div class="page_path">
-{desc|strip|escape|addbreaks|nonempty}
+{desc|strip|escape|websub|addbreaks|nonempty}
</div>
<div class="page_body">
<table>
--- a/mercurial/templates/gitweb/filerevision.tmpl Sun Feb 10 16:55:01 2013 +0000
+++ b/mercurial/templates/gitweb/filerevision.tmpl Mon Feb 11 01:21:24 2013 +0100
@@ -56,7 +56,7 @@
</div>
<div class="page_path">
-{desc|strip|escape|addbreaks|nonempty}
+{desc|strip|escape|websub|addbreaks|nonempty}
</div>
<div class="page_body">
--- a/mercurial/templates/monoblue/changelogentry.tmpl Sun Feb 10 16:55:01 2013 +0000
+++ b/mercurial/templates/monoblue/changelogentry.tmpl Mon Feb 11 01:21:24 2013 +0100
@@ -2,5 +2,5 @@
<ul class="changelog-entry">
<li class="age">{date|rfc822date}</li>
<li>by <span class="name">{author|obfuscate}</span> <span class="revdate">[{date|rfc822date}] rev {rev}</span></li>
- <li class="description">{desc|strip|escape|addbreaks|nonempty}</li>
+ <li class="description">{desc|strip|escape|websub|addbreaks|nonempty}</li>
</ul>
--- a/mercurial/templates/monoblue/changeset.tmpl Sun Feb 10 16:55:01 2013 +0000
+++ b/mercurial/templates/monoblue/changeset.tmpl Mon Feb 11 01:21:24 2013 +0100
@@ -52,7 +52,7 @@
{child%changesetchild}
</dl>
- <p class="description">{desc|strip|escape|addbreaks|nonempty}</p>
+ <p class="description">{desc|strip|escape|websub|addbreaks|nonempty}</p>
<table>
{files}
--- a/mercurial/templates/monoblue/fileannotate.tmpl Sun Feb 10 16:55:01 2013 +0000
+++ b/mercurial/templates/monoblue/fileannotate.tmpl Mon Feb 11 01:21:24 2013 +0100
@@ -57,7 +57,7 @@
<dd>{permissions|permissions}</dd>
</dl>
- <p class="description">{desc|strip|escape|addbreaks|nonempty}</p>
+ <p class="description">{desc|strip|escape|websub|addbreaks|nonempty}</p>
<table class="annotated">
{annotate%annotateline}
--- a/mercurial/templates/monoblue/filerevision.tmpl Sun Feb 10 16:55:01 2013 +0000
+++ b/mercurial/templates/monoblue/filerevision.tmpl Mon Feb 11 01:21:24 2013 +0100
@@ -57,7 +57,7 @@
<dd>{permissions|permissions}</dd>
</dl>
- <p class="description">{desc|strip|escape|addbreaks|nonempty}</p>
+ <p class="description">{desc|strip|escape|websub|addbreaks|nonempty}</p>
<div class="source">
{text%fileline}
--- a/mercurial/templates/paper/changeset.tmpl Sun Feb 10 16:55:01 2013 +0000
+++ b/mercurial/templates/paper/changeset.tmpl Mon Feb 11 01:21:24 2013 +0100
@@ -40,7 +40,7 @@
files, or words in the commit message</div>
</form>
-<div class="description">{desc|strip|escape|nonempty}</div>
+<div class="description">{desc|strip|escape|websub|nonempty}</div>
<table id="changesetEntry">
<tr>
--- a/mercurial/templates/paper/fileannotate.tmpl Sun Feb 10 16:55:01 2013 +0000
+++ b/mercurial/templates/paper/fileannotate.tmpl Mon Feb 11 01:21:24 2013 +0100
@@ -46,7 +46,7 @@
files, or words in the commit message</div>
</form>
-<div class="description">{desc|strip|escape|nonempty}</div>
+<div class="description">{desc|strip|escape|websub|nonempty}</div>
<table id="changesetEntry">
<tr>
--- a/mercurial/templates/paper/filecomparison.tmpl Sun Feb 10 16:55:01 2013 +0000
+++ b/mercurial/templates/paper/filecomparison.tmpl Mon Feb 11 01:21:24 2013 +0100
@@ -45,7 +45,7 @@
files, or words in the commit message</div>
</form>
-<div class="description">{desc|strip|escape|nonempty}</div>
+<div class="description">{desc|strip|escape|websub|nonempty}</div>
<table id="changesetEntry">
<tr>
--- a/mercurial/templates/paper/filediff.tmpl Sun Feb 10 16:55:01 2013 +0000
+++ b/mercurial/templates/paper/filediff.tmpl Mon Feb 11 01:21:24 2013 +0100
@@ -45,7 +45,7 @@
files, or words in the commit message</div>
</form>
-<div class="description">{desc|strip|escape|nonempty}</div>
+<div class="description">{desc|strip|escape|websub|nonempty}</div>
<table id="changesetEntry">
<tr>
--- a/mercurial/templates/paper/filerevision.tmpl Sun Feb 10 16:55:01 2013 +0000
+++ b/mercurial/templates/paper/filerevision.tmpl Mon Feb 11 01:21:24 2013 +0100
@@ -44,7 +44,7 @@
files, or words in the commit message</div>
</form>
-<div class="description">{desc|strip|escape|nonempty}</div>
+<div class="description">{desc|strip|escape|websub|nonempty}</div>
<table id="changesetEntry">
<tr>
--- a/mercurial/templates/spartan/changeset.tmpl Sun Feb 10 16:55:01 2013 +0000
+++ b/mercurial/templates/spartan/changeset.tmpl Mon Feb 11 01:21:24 2013 +0100
@@ -39,7 +39,7 @@
</tr>
<tr>
<th class="description">description:</th>
- <td class="description">{desc|strip|escape|addbreaks|nonempty}</td>
+ <td class="description">{desc|strip|escape|websub|addbreaks|nonempty}</td>
</tr>
</table>
--- a/mercurial/templates/spartan/fileannotate.tmpl Sun Feb 10 16:55:01 2013 +0000
+++ b/mercurial/templates/spartan/fileannotate.tmpl Mon Feb 11 01:21:24 2013 +0100
@@ -38,7 +38,7 @@
</tr>
<tr>
<td class="metatag">description:</td>
- <td>{desc|strip|escape|addbreaks|nonempty}</td>
+ <td>{desc|strip|escape|websub|addbreaks|nonempty}</td>
</tr>
</table>
--- a/mercurial/templates/spartan/filerevision.tmpl Sun Feb 10 16:55:01 2013 +0000
+++ b/mercurial/templates/spartan/filerevision.tmpl Mon Feb 11 01:21:24 2013 +0100
@@ -36,7 +36,7 @@
<td>{permissions|permissions}</td></tr>
<tr>
<td class="metatag">description:</td>
- <td>{desc|strip|escape|addbreaks|nonempty}</td>
+ <td>{desc|strip|escape|websub|addbreaks|nonempty}</td>
</tr>
</table>
--- a/tests/test-interhg.t Sun Feb 10 16:55:01 2013 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +0,0 @@
- $ "$TESTDIR/hghave" serve || exit 80
-
- $ hg init test
- $ cd test
-
- $ cat > .hg/hgrc <<EOF
- > [extensions]
- > interhg =
- >
- > [interhg]
- > issues = s|Issue(\d+)|<a href="http://bts.example.org/issue\1">Issue\1</a>|
- >
- > # yes, 'x' is a weird delimiter...
- > markbugs = sxbugx<i class="\x">bug</i>x
- > EOF
-
- $ touch foo
- $ hg add foo
- $ hg commit -d '1 0' -m 'Issue123: fixed the bug!'
-
- $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
- $ cat hg.pid >> $DAEMON_PIDS
-
-log
-
- $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT '' | grep bts
- <td class="description"><a href="/rev/1b0e7ece6bd6"><a href="http://bts.example.org/issue123">Issue123</a>: fixed the <i class="x">bug</i>!</a><span class="branchhead">default</span> <span class="tag">tip</span> </td>
-
-errors
-
- $ cat errors.log
-
- $ cd ..
--- a/tests/test-symlinks.t Sun Feb 10 16:55:01 2013 +0000
+++ b/tests/test-symlinks.t Mon Feb 11 01:21:24 2013 +0100
@@ -149,6 +149,10 @@
adding foo/a
$ mv foo bar
$ ln -s bar foo
+ $ hg status
+ ! foo/a
+ ? bar/a
+ ? foo
now addremove should remove old files
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-websub.t Mon Feb 11 01:21:24 2013 +0100
@@ -0,0 +1,36 @@
+ $ "$TESTDIR/hghave" serve || exit 80
+
+ $ hg init test
+ $ cd test
+
+ $ cat > .hg/hgrc <<EOF
+ > [extensions]
+ > # this is only necessary to check that the mapping from
+ > # interhg to websub works
+ > interhg =
+ >
+ > [websub]
+ > issues = s|Issue(\d+)|<a href="http://bts.example.org/issue\1">Issue\1</a>|
+ >
+ > [interhg]
+ > # check that we maintain some interhg backwards compatibility...
+ > # yes, 'x' is a weird delimiter...
+ > markbugs = sxbugx<i class="\x">bug</i>x
+ > EOF
+
+ $ touch foo
+ $ hg add foo
+ $ hg commit -d '1 0' -m 'Issue123: fixed the bug!'
+
+ $ hg serve -n test -p $HGPORT -d --pid-file=hg.pid -A access.log -E errors.log
+ $ cat hg.pid >> $DAEMON_PIDS
+
+log
+
+ $ "$TESTDIR/get-with-headers.py" localhost:$HGPORT "rev/tip" | grep bts
+ <div class="description"><a href="http://bts.example.org/issue123">Issue123</a>: fixed the <i class="x">bug</i>!</div>
+errors
+
+ $ cat errors.log
+
+ $ cd ..