diff mercurial/wireproto.py @ 13942:88f0e41d8802

wireproto: allow unbundle with hashed heads parameter (issue2126) Current wire protocol of unbundle sends the list of all heads in the remote repository to avoid race condition. This causes "URL too long" error on HTTP server when the repository has many heads. This change allows clients to send SHA1 hash of sorted head hashes instead. Also, this introduces "unbundlehash" capability to inform them that the server accepts hashed heads parameter.
author Shuhei Takahashi <takahashi.shuhei@gmail.com>
date Sat, 16 Apr 2011 01:05:56 +0900
parents b51bf961b3cb
children 58e58406ed19
line wrap: on
line diff
--- a/mercurial/wireproto.py	Fri Apr 15 23:46:59 2011 -0500
+++ b/mercurial/wireproto.py	Sat Apr 16 01:05:56 2011 +0900
@@ -139,7 +139,13 @@
         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 @@
     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 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()