##// END OF EJS Templates
exchangev2: start to implement pull with wire protocol v2...
Gregory Szorc -
r39665:a86d21e7 default
parent child Browse files
Show More
@@ -0,0 +1,55 b''
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 b''
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 b' from . import ('
26 changegroup,
26 changegroup,
27 discovery,
27 discovery,
28 error,
28 error,
29 exchangev2,
29 lock as lockmod,
30 lock as lockmod,
30 logexchange,
31 logexchange,
31 narrowspec,
32 narrowspec,
@@ -1506,17 +1507,21 b' def pull(repo, remote, heads=None, force'
1506
1507
1507 pullop.trmanager = transactionmanager(repo, 'pull', remote.url())
1508 pullop.trmanager = transactionmanager(repo, 'pull', remote.url())
1508 with repo.wlock(), repo.lock(), pullop.trmanager:
1509 with repo.wlock(), repo.lock(), pullop.trmanager:
1509 # This should ideally be in _pullbundle2(). However, it needs to run
1510 # Use the modern wire protocol, if available.
1510 # before discovery to avoid extra work.
1511 if remote.capable('exchangev2'):
1511 _maybeapplyclonebundle(pullop)
1512 exchangev2.pull(pullop)
1512 streamclone.maybeperformlegacystreamclone(pullop)
1513 else:
1513 _pulldiscovery(pullop)
1514 # This should ideally be in _pullbundle2(). However, it needs to run
1514 if pullop.canusebundle2:
1515 # before discovery to avoid extra work.
1515 _fullpullbundle2(repo, pullop)
1516 _maybeapplyclonebundle(pullop)
1516 _pullchangeset(pullop)
1517 streamclone.maybeperformlegacystreamclone(pullop)
1517 _pullphase(pullop)
1518 _pulldiscovery(pullop)
1518 _pullbookmarks(pullop)
1519 if pullop.canusebundle2:
1519 _pullobsolete(pullop)
1520 _fullpullbundle2(repo, pullop)
1521 _pullchangeset(pullop)
1522 _pullphase(pullop)
1523 _pullbookmarks(pullop)
1524 _pullobsolete(pullop)
1520
1525
1521 # storing remotenames
1526 # storing remotenames
1522 if repo.ui.configbool('experimental', 'remotenames'):
1527 if repo.ui.configbool('experimental', 'remotenames'):
@@ -802,7 +802,8 b' class httpv2peer(object):'
802 return True
802 return True
803
803
804 # Other concepts.
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 return True
807 return True
807
808
808 # Alias command-* to presence of command of that name.
809 # Alias command-* to presence of command of that name.
@@ -56,3 +56,10 b' web.apiserver = true'
56 web.api.http-v2 = true
56 web.api.http-v2 = true
57 EOF
57 EOF
58 }
58 }
59
60 enablehttpv2client() {
61 cat >> $HGRCPATH << EOF
62 [experimental]
63 httppeer.advertise-v2 = true
64 EOF
65 }
General Comments 0
You need to be logged in to leave comments. Login now