diff --git a/mercurial/wireproto.py b/mercurial/wireproto.py --- a/mercurial/wireproto.py +++ b/mercurial/wireproto.py @@ -139,7 +139,13 @@ class wirerepository(repo.repository): remote server as a bundle. Return an integer indicating the result of the push (see localrepository.addchangegroup()).''' - ret, output = self._callpush("unbundle", cg, heads=encodelist(heads)) + if self.capable('unbundlehash'): + heads = encodelist(['hashed', + util.sha1(''.join(sorted(heads))).digest()]) + else: + heads = encodelist(heads) + + ret, output = self._callpush("unbundle", cg, heads=heads) if ret == "": raise error.ResponseError( _('push failed:'), output) @@ -216,7 +222,8 @@ def branches(repo, proto, nodes): return "".join(r) def capabilities(repo, proto): - caps = 'lookup changegroupsubset branchmap pushkey known getbundle'.split() + caps = ('lookup changegroupsubset branchmap pushkey known getbundle ' + 'unbundlehash').split() if _allowstream(repo.ui): requiredformats = repo.requirements & repo.supportedformats # if our local revlogs are just revlogv1, add 'stream' cap @@ -353,7 +360,9 @@ def unbundle(repo, proto, heads): def check_heads(): heads = repo.heads() - return their_heads == ['force'] or their_heads == heads + heads_hash = util.sha1(''.join(sorted(heads))).digest() + return (their_heads == ['force'] or their_heads == heads or + their_heads == ['hashed', heads_hash]) proto.redirect() diff --git a/tests/test-hgweb-commands.t b/tests/test-hgweb-commands.t --- a/tests/test-hgweb-commands.t +++ b/tests/test-hgweb-commands.t @@ -943,7 +943,7 @@ capabilities $ "$TESTDIR/get-with-headers.py" 127.0.0.1:$HGPORT '?cmd=capabilities'; echo 200 Script output follows - lookup changegroupsubset branchmap pushkey known getbundle unbundle=HG10GZ,HG10BZ,HG10UN + lookup changegroupsubset branchmap pushkey known getbundle unbundlehash unbundle=HG10GZ,HG10BZ,HG10UN heads diff --git a/tests/test-unbundlehash.t b/tests/test-unbundlehash.t new file mode 100644 --- /dev/null +++ b/tests/test-unbundlehash.t @@ -0,0 +1,31 @@ + +Test wire protocol unbundle with hashed heads (capability: unbundlehash) + +Create a remote repository. + + $ hg init remote + $ hg serve -R remote --config web.push_ssl=False --config web.allow_push=* -p $HGPORT -d --pid-file=hg1.pid -E error.log -A access.log + $ cat hg1.pid >> $DAEMON_PIDS + +Clone the repository and push a change. + + $ hg clone http://localhost:$HGPORT/ local + no changes found + updating to branch default + 0 files updated, 0 files merged, 0 files removed, 0 files unresolved + $ touch local/README + $ hg ci -R local -A -m hoge + adding README + $ hg push -R local + pushing to http://localhost:$HGPORT/ + searching for changes + remote: adding changesets + remote: adding manifests + remote: adding file changes + remote: added 1 changesets with 1 changes to 1 files + +Ensure hashed heads format is used. +The hash here is always the same since the remote repository only has the null head. + + $ cat access.log | grep unbundle + * - - [*] "POST /?cmd=unbundle&heads=686173686564+6768033e216468247bd031a0a2d9876d79818f8f HTTP/1.1" 200 - (glob)