mozext: obtain pushlog data via wire protocol (
bug 1236618); r?nalexander
It is faster to obtain the pushlog via the wire protocol via an already
established TCP connection than to fetch it via multiple HTTP requests
from the Mercurial JSON web API.
Before: ~20.3s
After: ~13.3s
This does create some duplicate pushlog fetch code. And `hg pushlogsync`
doesn't use the new API. But progress is progress. We should probably
clone the tracking bug to track doing this more robustly.
--- a/hgext/mozext/__init__.py
+++ b/hgext/mozext/__init__.py
@@ -289,16 +289,17 @@ from mercurial.i18n import _
from mercurial.error import (
ParseError,
RepoError,
)
from mercurial.localrepo import (
repofilecache,
)
from mercurial.node import (
+ bin,
hex,
short,
)
from mercurial import (
commands,
cmdutil,
demandimport,
encoding,
@@ -393,18 +394,48 @@ def exchangepullpushlog(orig, pullop):
return res
repo = pullop.repo
tree = resolve_uri_to_tree(pullop.remote.url())
if not tree or not repo.changetracker or tree == "try":
return res
- repo.ui.status('fetching pushlog\n')
- repo.changetracker.load_pushlog(tree)
+ lastpushid = repo.changetracker.last_push_id(tree)
+ fetchfrom = lastpushid + 1 if lastpushid is not None else 0
+
+ lines = pullop.remote._call('pushlog', firstpush=str(fetchfrom))
+ lines = iter(lines.splitlines())
+
+ statusline = lines.next()
+ if statusline[0] == '0':
+ raise error.Abort('remote error fetching pushlog: %s' % lines.next())
+ elif statusline != '1':
+ raise error.Abort('error fetching pushlog: unexpected response: %s\n' %
+ statusline)
+
+ pushes = []
+ for line in lines:
+ pushid, who, when, nodes = line.split(' ', 3)
+ nodes = [bin(n) for n in nodes.split()]
+
+ # Verify incoming changesets are known and stop processing when we see
+ # an unknown changeset. This can happen when we're pulling a former
+ # head instead of all changesets.
+ try:
+ [repo[n] for n in nodes]
+ except error.RepoLookupError:
+ repo.ui.warn('received pushlog entry for unknown changeset; ignoring\n')
+ break
+
+ pushes.append((int(pushid), who, int(when), nodes))
+
+ if pushes:
+ repo.changetracker.add_pushes(tree, pushes)
+ repo.ui.status('added %d pushes\n' % len(pushes))
return res
def critique(ui, repo, entire=False, node=None, **kwargs):
"""Perform a critique of a changeset."""
demandimport.disable()
from flake8.engine import get_style_guide