Show More
@@ -0,0 +1,55 | |||
|
1 | # exchangev2.py - repository exchange for wire protocol version 2 | |
|
2 | # | |
|
3 | # Copyright 2018 Gregory Szorc <gregory.szorc@gmail.com> | |
|
4 | # | |
|
5 | # This software may be used and distributed according to the terms of the | |
|
6 | # GNU General Public License version 2 or any later version. | |
|
7 | ||
|
8 | from __future__ import absolute_import | |
|
9 | ||
|
10 | from .node import ( | |
|
11 | nullid, | |
|
12 | ) | |
|
13 | from . import ( | |
|
14 | setdiscovery, | |
|
15 | ) | |
|
16 | ||
|
17 | def pull(pullop): | |
|
18 | """Pull using wire protocol version 2.""" | |
|
19 | repo = pullop.repo | |
|
20 | remote = pullop.remote | |
|
21 | ||
|
22 | # Figure out what needs to be fetched. | |
|
23 | common, fetch, remoteheads = _pullchangesetdiscovery( | |
|
24 | repo, remote, pullop.heads, abortwhenunrelated=pullop.force) | |
|
25 | ||
|
26 | def _pullchangesetdiscovery(repo, remote, heads, abortwhenunrelated=True): | |
|
27 | """Determine which changesets need to be pulled.""" | |
|
28 | ||
|
29 | if heads: | |
|
30 | knownnode = repo.changelog.hasnode | |
|
31 | if all(knownnode(head) for head in heads): | |
|
32 | return heads, False, heads | |
|
33 | ||
|
34 | # TODO wire protocol version 2 is capable of more efficient discovery | |
|
35 | # than setdiscovery. Consider implementing something better. | |
|
36 | common, fetch, remoteheads = setdiscovery.findcommonheads( | |
|
37 | repo.ui, repo, remote, abortwhenunrelated=abortwhenunrelated) | |
|
38 | ||
|
39 | common = set(common) | |
|
40 | remoteheads = set(remoteheads) | |
|
41 | ||
|
42 | # If a remote head is filtered locally, put it back in the common set. | |
|
43 | # See the comment in exchange._pulldiscoverychangegroup() for more. | |
|
44 | ||
|
45 | if fetch and remoteheads: | |
|
46 | nodemap = repo.unfiltered().changelog.nodemap | |
|
47 | ||
|
48 | common |= {head for head in remoteheads if head in nodemap} | |
|
49 | ||
|
50 | if set(remoteheads).issubset(common): | |
|
51 | fetch = [] | |
|
52 | ||
|
53 | common.discard(nullid) | |
|
54 | ||
|
55 | return common, fetch, remoteheads |
@@ -0,0 +1,53 | |||
|
1 | Tests for wire protocol version 2 exchange. | |
|
2 | Tests in this file should be folded into existing tests once protocol | |
|
3 | v2 has enough features that it can be enabled via #testcase in existing | |
|
4 | tests. | |
|
5 | ||
|
6 | $ . $TESTDIR/wireprotohelpers.sh | |
|
7 | $ enablehttpv2client | |
|
8 | ||
|
9 | $ hg init server-simple | |
|
10 | $ enablehttpv2 server-simple | |
|
11 | $ cd server-simple | |
|
12 | $ cat >> .hg/hgrc << EOF | |
|
13 | > [phases] | |
|
14 | > publish = false | |
|
15 | > EOF | |
|
16 | $ echo a0 > a | |
|
17 | $ echo b0 > b | |
|
18 | $ hg -q commit -A -m 'commit 0' | |
|
19 | ||
|
20 | $ echo a1 > a | |
|
21 | $ hg commit -m 'commit 1' | |
|
22 | $ hg phase --public -r . | |
|
23 | $ echo a2 > a | |
|
24 | $ hg commit -m 'commit 2' | |
|
25 | ||
|
26 | $ hg -q up -r 0 | |
|
27 | $ echo b1 > b | |
|
28 | $ hg -q commit -m 'head 2 commit 1' | |
|
29 | $ echo b2 > b | |
|
30 | $ hg -q commit -m 'head 2 commit 2' | |
|
31 | ||
|
32 | $ hg serve -p $HGPORT -d --pid-file hg.pid -E error.log | |
|
33 | $ cat hg.pid > $DAEMON_PIDS | |
|
34 | ||
|
35 | $ cd .. | |
|
36 | ||
|
37 | Test basic clone | |
|
38 | ||
|
39 | $ hg --debug clone -U http://localhost:$HGPORT client-simple | |
|
40 | using http://localhost:$HGPORT/ | |
|
41 | sending capabilities command | |
|
42 | query 1; heads | |
|
43 | sending 2 commands | |
|
44 | sending command heads: {} | |
|
45 | sending command known: { | |
|
46 | 'nodes': [] | |
|
47 | } | |
|
48 | received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) | |
|
49 | received frame(size=43; request=1; stream=2; streamflags=; type=command-response; flags=continuation) | |
|
50 | received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) | |
|
51 | received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation) | |
|
52 | received frame(size=1; request=3; stream=2; streamflags=; type=command-response; flags=continuation) | |
|
53 | received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos) |
@@ -26,6 +26,7 from . import ( | |||
|
26 | 26 | changegroup, |
|
27 | 27 | discovery, |
|
28 | 28 | error, |
|
29 | exchangev2, | |
|
29 | 30 | lock as lockmod, |
|
30 | 31 | logexchange, |
|
31 | 32 | narrowspec, |
@@ -1506,6 +1507,10 def pull(repo, remote, heads=None, force | |||
|
1506 | 1507 | |
|
1507 | 1508 | pullop.trmanager = transactionmanager(repo, 'pull', remote.url()) |
|
1508 | 1509 | with repo.wlock(), repo.lock(), pullop.trmanager: |
|
1510 | # Use the modern wire protocol, if available. | |
|
1511 | if remote.capable('exchangev2'): | |
|
1512 | exchangev2.pull(pullop) | |
|
1513 | else: | |
|
1509 | 1514 | # This should ideally be in _pullbundle2(). However, it needs to run |
|
1510 | 1515 | # before discovery to avoid extra work. |
|
1511 | 1516 | _maybeapplyclonebundle(pullop) |
@@ -802,7 +802,8 class httpv2peer(object): | |||
|
802 | 802 | return True |
|
803 | 803 | |
|
804 | 804 | # Other concepts. |
|
805 | if name in ('bundle2',): | |
|
805 | # TODO remove exchangev2 once we have a command implemented. | |
|
806 | if name in ('bundle2', 'exchangev2'): | |
|
806 | 807 | return True |
|
807 | 808 | |
|
808 | 809 | # Alias command-* to presence of command of that name. |
General Comments 0
You need to be logged in to leave comments.
Login now