--- a/hgext/pushlog/__init__.py
+++ b/hgext/pushlog/__init__.py
@@ -618,17 +618,18 @@ def pretxnchangegrouphook(ui, repo, node
repo.pushlog.recordpush(revs, pushuser, t)
ui.write('recorded push in pushlog\n')
return 0
except Exception:
ui.write('error recording into pushlog; please retry your push\n')
return 1
-@revsetpredicate('pushhead()')
+
+@revsetpredicate('pushhead()', safe=True)
def revset_pushhead(repo, subset, x):
"""Changesets that were heads when they were pushed.
A push head is a changeset that was a head at the time it was pushed.
"""
revset.getargs(x, 0, 0, 'pushhead takes no arguments')
# Iterating over all pushlog data is unfortunate, as there is overhead
@@ -637,33 +638,35 @@ def revset_pushhead(repo, subset, x):
# this optimal by batching SQL, but that adds complexity. For now,
# simplicity wins.
def getrevs():
for push in repo.pushlog.pushes():
yield repo[push.nodes[-1]].rev()
return subset & revset.generatorset(getrevs())
-@revsetpredicate('pushdate(interval)')
+
+@revsetpredicate('pushdate(interval)', safe=True)
def revset_pushdate(repo, subset, x):
"""Changesets that were pushed within the interval, see :hg:`help dates`."""
l = revset.getargs(x, 1, 1, 'pushdate requires one argument')
ds = revset.getstring(l[0], 'pushdate requires a string argument')
dm = util.matchdate(ds)
def getrevs():
for push in repo.pushlog.pushes():
if dm(push.when):
for node in push.nodes:
yield repo[node].rev()
return subset & revset.generatorset(getrevs())
-@revsetpredicate('pushuser(string)')
+
+@revsetpredicate('pushuser(string)', safe=True)
def revset_pushuser(repo, subset, x):
"""User name that pushed the changeset contains string.
The match is case-insensitive.
If `string` starts with `re:`, the remainder of the string is treated as
a regular expression. To match a user that actually contains `re:`, use
the prefix `literal:`.
@@ -675,17 +678,18 @@ def revset_pushuser(repo, subset, x):
def getrevs():
for push in repo.pushlog.pushes():
if matcher(encoding.lower(push.user)):
for node in push.nodes:
yield repo[node].rev()
return subset & revset.generatorset(getrevs())
-@revsetpredicate('pushid(int)')
+
+@revsetpredicate('pushid(int)', safe=True)
def revset_pushid(repo, subset, x):
"""Changesets that were part of the specified numeric push id."""
l = revset.getargs(x, 1, 1, 'pushid requires one argument')
try:
pushid = int(revset.getstring(l[0], 'pushid requires a number'))
except (TypeError, ValueError):
raise error.ParseError('pushid expects a number')
@@ -699,17 +703,18 @@ def revset_pushid(repo, subset, x):
for node in push.nodes:
try:
pushrevs.add(repo[node].rev())
except RepoLookupError:
pass
return subset & pushrevs
-@revsetpredicate('pushrev(set)')
+
+@revsetpredicate('pushrev(set)', safe=True)
def revset_pushrev(repo, subset, x):
"""Changesets that were part of the same push as the specified changeset(s)."""
l = revset.getset(repo, subset, x)
# This isn't the most optimal implementation, especially if the input
# set is large. But it gets the job done.
revs = set()
for rev in l:
--- a/hgext/pushlog/tests/test-hgweb.t
+++ b/hgext/pushlog/tests/test-hgweb.t
@@ -50,8 +50,258 @@ Push info should show up in changeset vi
<tr><td>push date</td><td>*</td></tr> (glob)
$ http http://localhost:$HGPORT/log --body-file body > /dev/null
$ grep push body
<a href="/pushloghtml">pushlog</a> |
Push <a href="/pushloghtml?changeset=82f53df85e9f">2</a> by user2@example.com at *<br /> (glob)
Push <a href="/pushloghtml?changeset=6c9721b3b4df">2</a> by user2@example.com at *<br /> (glob)
Push <a href="/pushloghtml?changeset=55482a6fb4b1">1</a> by user1@example.com at *<br /> (glob)
+
+pushhead() works in search
+
+ $ http "http://localhost:$HGPORT/json-log?rev=pushhead()" --body-file body > /dev/null
+ $ python -m json.tool < body
+ {
+ "entries": [
+ {
+ "bookmarks": [],
+ "branch": "default",
+ "date": [
+ 0.0,
+ 0
+ ],
+ "desc": "third",
+ "node": "82f53df85e9f23d81dbcfbf7debf9900cdc1e2ce",
+ "parents": [
+ "6c9721b3b4dfc8c1f2d3103595e8bb2ffe5b8ff2"
+ ],
+ "phase": "public",
+ "pushdate": [
+ \d+, (re)
+ 0
+ ],
+ "pushid": 2,
+ "tags": [
+ "tip"
+ ],
+ "user": "test"
+ },
+ {
+ "bookmarks": [],
+ "branch": "default",
+ "date": [
+ 0.0,
+ 0
+ ],
+ "desc": "initial",
+ "node": "55482a6fb4b1881fa8f746fd52cf6f096bb21c89",
+ "parents": [],
+ "phase": "public",
+ "pushdate": [
+ \d+, (re)
+ 0
+ ],
+ "pushid": 1,
+ "tags": [],
+ "user": "test"
+ }
+ ],
+ "node": "82f53df85e9f23d81dbcfbf7debf9900cdc1e2ce",
+ "query": "pushhead()"
+ }
+
+pushdate() works in search
+
+ $ http "http://localhost:$HGPORT/json-log?rev=pushdate('>2017')" --body-file body > /dev/null
+ $ python -m json.tool < body
+ {
+ "entries": [
+ {
+ "bookmarks": [],
+ "branch": "default",
+ "date": [
+ 0.0,
+ 0
+ ],
+ "desc": "third",
+ "node": "82f53df85e9f23d81dbcfbf7debf9900cdc1e2ce",
+ "parents": [
+ "6c9721b3b4dfc8c1f2d3103595e8bb2ffe5b8ff2"
+ ],
+ "phase": "public",
+ "pushdate": [
+ \d+, (re)
+ 0
+ ],
+ "pushid": 2,
+ "tags": [
+ "tip"
+ ],
+ "user": "test"
+ },
+ {
+ "bookmarks": [],
+ "branch": "default",
+ "date": [
+ 0.0,
+ 0
+ ],
+ "desc": "second",
+ "node": "6c9721b3b4dfc8c1f2d3103595e8bb2ffe5b8ff2",
+ "parents": [
+ "55482a6fb4b1881fa8f746fd52cf6f096bb21c89"
+ ],
+ "phase": "public",
+ "pushdate": [
+ \d+, (re)
+ 0
+ ],
+ "pushid": 2,
+ "tags": [],
+ "user": "test"
+ },
+ {
+ "bookmarks": [],
+ "branch": "default",
+ "date": [
+ 0.0,
+ 0
+ ],
+ "desc": "initial",
+ "node": "55482a6fb4b1881fa8f746fd52cf6f096bb21c89",
+ "parents": [],
+ "phase": "public",
+ "pushdate": [
+ \d+, (re)
+ 0
+ ],
+ "pushid": 1,
+ "tags": [],
+ "user": "test"
+ }
+ ],
+ "node": "82f53df85e9f23d81dbcfbf7debf9900cdc1e2ce",
+ "query": "pushdate('>2017')"
+ }
+
+pushuser() works in search
+
+ $ http "http://localhost:$HGPORT/json-log?rev=pushuser(user1)" --body-file body > /dev/null
+ $ python -m json.tool < body
+ {
+ "entries": [
+ {
+ "bookmarks": [],
+ "branch": "default",
+ "date": [
+ 0.0,
+ 0
+ ],
+ "desc": "initial",
+ "node": "55482a6fb4b1881fa8f746fd52cf6f096bb21c89",
+ "parents": [],
+ "phase": "public",
+ "pushdate": [
+ \d+, (re)
+ 0
+ ],
+ "pushid": 1,
+ "tags": [],
+ "user": "test"
+ }
+ ],
+ "node": "82f53df85e9f23d81dbcfbf7debf9900cdc1e2ce",
+ "query": "pushuser(user1)"
+ }
+
+pushid() works in search
+
+ $ http "http://localhost:$HGPORT/json-log?rev=pushid(1)" --body-file body > /dev/null
+ $ python -m json.tool < body
+ {
+ "entries": [
+ {
+ "bookmarks": [],
+ "branch": "default",
+ "date": [
+ 0.0,
+ 0
+ ],
+ "desc": "initial",
+ "node": "55482a6fb4b1881fa8f746fd52cf6f096bb21c89",
+ "parents": [],
+ "phase": "public",
+ "pushdate": [
+ \d+, (re)
+ 0
+ ],
+ "pushid": 1,
+ "tags": [],
+ "user": "test"
+ }
+ ],
+ "node": "82f53df85e9f23d81dbcfbf7debf9900cdc1e2ce",
+ "query": "pushid(1)"
+ }
+
+ $ http "http://localhost:$HGPORT/json-log?rev=pushid(3)" --body-file body > /dev/null
+ $ python -m json.tool < body
+ {
+ "entries": [],
+ "node": "82f53df85e9f23d81dbcfbf7debf9900cdc1e2ce",
+ "query": "pushid(3)"
+ }
+
+pushrev() works in search
+
+ $ http "http://localhost:$HGPORT/json-log?rev=pushrev(1)" --body-file body > /dev/null
+ $ python -m json.tool < body
+ {
+ "entries": [
+ {
+ "bookmarks": [],
+ "branch": "default",
+ "date": [
+ 0.0,
+ 0
+ ],
+ "desc": "third",
+ "node": "82f53df85e9f23d81dbcfbf7debf9900cdc1e2ce",
+ "parents": [
+ "6c9721b3b4dfc8c1f2d3103595e8bb2ffe5b8ff2"
+ ],
+ "phase": "public",
+ "pushdate": [
+ \d+, (re)
+ 0
+ ],
+ "pushid": 2,
+ "tags": [
+ "tip"
+ ],
+ "user": "test"
+ },
+ {
+ "bookmarks": [],
+ "branch": "default",
+ "date": [
+ 0.0,
+ 0
+ ],
+ "desc": "second",
+ "node": "6c9721b3b4dfc8c1f2d3103595e8bb2ffe5b8ff2",
+ "parents": [
+ "55482a6fb4b1881fa8f746fd52cf6f096bb21c89"
+ ],
+ "phase": "public",
+ "pushdate": [
+ \d+, (re)
+ 0
+ ],
+ "pushid": 2,
+ "tags": [],
+ "user": "test"
+ }
+ ],
+ "node": "82f53df85e9f23d81dbcfbf7debf9900cdc1e2ce",
+ "query": "pushrev(1)"
+ }