diff --git a/mercurial/exchange.py b/mercurial/exchange.py --- a/mercurial/exchange.py +++ b/mercurial/exchange.py @@ -1351,9 +1351,24 @@ # before discovery to avoid extra work. _maybeapplyclonebundle(pullop) streamclone.maybeperformlegacystreamclone(pullop) - _pulldiscovery(pullop) - if pullop.canusebundle2: + while True: + _pulldiscovery(pullop) + if not pullop.canusebundle2: + break _pullbundle2(pullop) + # The server may send a partial reply, i.e. when inlining + # pre-computed bundles. In that case, re-run the discovery + # phase and bundle again. There are two indicators that the + # process is finished: + # - no changes have been received (cgresult) + # - all remote heads are known locally + # The head check must use the unfiltered view as obsoletion + # markers can hide heads. + if not pullop.cgresult: + break + unficl = repo.unfiltered().changelog + if all(unficl.hasnode(n) for n in pullop.rheads): + break _pullchangeset(pullop) _pullphase(pullop) _pullbookmarks(pullop) diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py --- a/mercurial/wireproto.py +++ b/mercurial/wireproto.py @@ -915,8 +915,7 @@ common = set(opts.get('common', set())) common.discard(nullid) - if repo.ui.configbool('server', 'pullbundle') and - self.capable('partial-pull'): + if repo.ui.configbool('server', 'pullbundle'): # Check if a pre-built bundle covers this request. bundle = find_pullbundle(repo, opts, clheads, heads, common) if bundle: diff --git a/tests/test-pull-r.t b/tests/test-pull-r.t --- a/tests/test-pull-r.t +++ b/tests/test-pull-r.t @@ -201,3 +201,40 @@ sending pullbundle "0.hg" sending pullbundle "1.hg" sending pullbundle "2.hg" + +Test pullbundle functionality for incremental pulls + + $ cd repo + $ hg serve --debug -p $HGPORT2 --pid-file=../repo.pid > ../repo-server.txt 2>&1 & + $ while ! grep listening ../repo-server.txt > /dev/null; do sleep 1; done + $ cat ../repo.pid >> $DAEMON_PIDS + $ cd .. + $ hg clone http://localhost:$HGPORT2/ repo.pullbundle2 + requesting all changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files (+1 heads) + searching for changes + adding changesets + adding manifests + adding file changes + added 1 changesets with 1 changes to 1 files + new changesets bbd179dfa0a7:66e3ba28d0d7 + updating to branch default + 3 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ killdaemons.py + $ grep 'sending pullbundle ' repo-server.txt + sending pullbundle "0.hg" + sending pullbundle "2.hg" + sending pullbundle "1.hg"