diff --git a/mercurial/exchangev2.py b/mercurial/exchangev2.py --- a/mercurial/exchangev2.py +++ b/mercurial/exchangev2.py @@ -16,6 +16,7 @@ ) from . import ( mdiff, + phases, pycompat, setdiscovery, ) @@ -30,8 +31,25 @@ common, fetch, remoteheads = _pullchangesetdiscovery( repo, remote, pullop.heads, abortwhenunrelated=pullop.force) + # And fetch the data. pullheads = pullop.heads or remoteheads - _fetchchangesets(repo, tr, remote, common, fetch, pullheads) + csetres = _fetchchangesets(repo, tr, remote, common, fetch, pullheads) + + # New revisions are written to the changelog. But all other updates + # are deferred. Do those now. + + # Ensure all new changesets are draft by default. If the repo is + # publishing, the phase will be adjusted by the loop below. + if csetres['added']: + phases.registernew(repo, tr, phases.draft, csetres['added']) + + # And adjust the phase of all changesets accordingly. + for phase in phases.phasenames: + if phase == b'secret' or not csetres['nodesbyphase'][phase]: + continue + + phases.advanceboundary(repo, tr, phases.phasenames.index(phase), + csetres['nodesbyphase'][phase]) def _pullchangesetdiscovery(repo, remote, heads, abortwhenunrelated=True): """Determine which changesets need to be pulled.""" @@ -65,9 +83,6 @@ return common, fetch, remoteheads def _fetchchangesets(repo, tr, remote, common, fetch, remoteheads): - if not fetch: - return - # TODO consider adding a step here where we obtain the DAG shape first # (or ask the server to slice changesets into chunks for us) so that # we can perform multiple fetches in batches. This will facilitate @@ -76,7 +91,7 @@ with remote.commandexecutor() as e: objs = e.callcommand(b'changesetdata', { b'noderange': [sorted(common), sorted(remoteheads)], - b'fields': {b'parents', b'revision'}, + b'fields': {b'parents', b'phase', b'revision'}, }).result() # The context manager waits on all response data when exiting. So @@ -108,15 +123,28 @@ def onchangeset(cl, node): progress.increment() + nodesbyphase = {phase: set() for phase in phases.phasenames} + # addgroup() expects a 7-tuple describing revisions. This normalizes # the wire data to that format. + # + # This loop also aggregates non-revision metadata, such as phase + # data. def iterrevisions(): for cset in objs: - assert b'revisionsize' in cset + node = cset[b'node'] + + if b'phase' in cset: + nodesbyphase[cset[b'phase']].add(node) + + # Some entries might only be metadata only updates. + if b'revisionsize' not in cset: + continue + data = next(objs) yield ( - cset[b'node'], + node, cset[b'parents'][0], cset[b'parents'][1], # Linknode is always itself for changesets. @@ -135,4 +163,5 @@ return { 'added': added, + 'nodesbyphase': nodesbyphase, } diff --git a/tests/test-wireproto-exchangev2.t b/tests/test-wireproto-exchangev2.t --- a/tests/test-wireproto-exchangev2.t +++ b/tests/test-wireproto-exchangev2.t @@ -55,6 +55,7 @@ sending command changesetdata: { 'fields': set([ 'parents', + 'phase', 'revision' ]), 'noderange': [ @@ -66,7 +67,7 @@ ] } received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) - received frame(size=809; request=1; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=871; request=1; stream=2; streamflags=; type=command-response; flags=continuation) received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) add changeset 3390ef850073 add changeset 4432d83626e8 @@ -87,11 +88,11 @@ 4 4 caa2a465451d e96ae20f4188 000000000000 $ hg -R client-simple log -G -T '{rev} {node} {phase}\n' - o 4 caa2a465451dd1facda0f5b12312c355584188a1 public + o 4 caa2a465451dd1facda0f5b12312c355584188a1 draft | - o 3 e96ae20f4188487b9ae4ef3941c27c81143146e5 public + o 3 e96ae20f4188487b9ae4ef3941c27c81143146e5 draft | - | o 2 cd2534766bece138c7c1afdc6825302f0f62d81f public + | o 2 cd2534766bece138c7c1afdc6825302f0f62d81f draft | | | o 1 4432d83626e8a98655f062ec1f2a43b07f7fbbb0 public |/ @@ -126,6 +127,7 @@ sending command changesetdata: { 'fields': set([ 'parents', + 'phase', 'revision' ]), 'noderange': [ @@ -136,7 +138,7 @@ ] } received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) - received frame(size=327; request=1; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=353; request=1; stream=2; streamflags=; type=command-response; flags=continuation) received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) add changeset 3390ef850073 add changeset 4432d83626e8 @@ -177,6 +179,7 @@ sending command changesetdata: { 'fields': set([ 'parents', + 'phase', 'revision' ]), 'noderange': [ @@ -190,7 +193,7 @@ ] } received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) - received frame(size=495; request=1; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=571; request=1; stream=2; streamflags=; type=command-response; flags=continuation) received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) add changeset cd2534766bec add changeset e96ae20f4188 @@ -200,11 +203,71 @@ (run 'hg update' to get a working copy) $ hg log -G -T '{rev} {node} {phase}\n' + o 4 caa2a465451dd1facda0f5b12312c355584188a1 draft + | + o 3 e96ae20f4188487b9ae4ef3941c27c81143146e5 draft + | + | o 2 cd2534766bece138c7c1afdc6825302f0f62d81f draft + | | + | o 1 4432d83626e8a98655f062ec1f2a43b07f7fbbb0 public + |/ + o 0 3390ef850073fbc2f0dfff2244342c8e9229013a public + + +Phase-only update works + + $ hg -R ../server-simple phase --public -r caa2a465451dd + $ hg --debug pull + pulling from http://localhost:$HGPORT/ + using http://localhost:$HGPORT/ + sending capabilities command + query 1; heads + sending 2 commands + sending command heads: {} + sending command known: { + 'nodes': [ + '\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f', + '\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1' + ] + } + received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) + received frame(size=43; request=1; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) + received frame(size=11; request=3; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=3; request=3; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=0; request=3; stream=2; streamflags=; type=command-response; flags=eos) + searching for changes + all remote heads known locally + sending 1 commands + sending command changesetdata: { + 'fields': set([ + 'parents', + 'phase', + 'revision' + ]), + 'noderange': [ + [ + '\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1', + '\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f' + ], + [ + '\xca\xa2\xa4eE\x1d\xd1\xfa\xcd\xa0\xf5\xb1#\x12\xc3UXA\x88\xa1', + '\xcd%4vk\xec\xe18\xc7\xc1\xaf\xdch%0/\x0fb\xd8\x1f' + ] + ] + } + received frame(size=11; request=1; stream=2; streamflags=stream-begin; type=command-response; flags=continuation) + received frame(size=92; request=1; stream=2; streamflags=; type=command-response; flags=continuation) + received frame(size=0; request=1; stream=2; streamflags=; type=command-response; flags=eos) + 2 local changesets published + (run 'hg update' to get a working copy) + + $ hg log -G -T '{rev} {node} {phase}\n' o 4 caa2a465451dd1facda0f5b12312c355584188a1 public | o 3 e96ae20f4188487b9ae4ef3941c27c81143146e5 public | - | o 2 cd2534766bece138c7c1afdc6825302f0f62d81f public + | o 2 cd2534766bece138c7c1afdc6825302f0f62d81f draft | | | o 1 4432d83626e8a98655f062ec1f2a43b07f7fbbb0 public |/