Mercurial > hg
comparison 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 |
comparison
equal
deleted
inserted
replaced
13941:924f40b977ee | 13942:88f0e41d8802 |
---|---|
137 '''Send cg (a readable file-like object representing the | 137 '''Send cg (a readable file-like object representing the |
138 changegroup to push, typically a chunkbuffer object) to the | 138 changegroup to push, typically a chunkbuffer object) to the |
139 remote server as a bundle. Return an integer indicating the | 139 remote server as a bundle. Return an integer indicating the |
140 result of the push (see localrepository.addchangegroup()).''' | 140 result of the push (see localrepository.addchangegroup()).''' |
141 | 141 |
142 ret, output = self._callpush("unbundle", cg, heads=encodelist(heads)) | 142 if self.capable('unbundlehash'): |
143 heads = encodelist(['hashed', | |
144 util.sha1(''.join(sorted(heads))).digest()]) | |
145 else: | |
146 heads = encodelist(heads) | |
147 | |
148 ret, output = self._callpush("unbundle", cg, heads=heads) | |
143 if ret == "": | 149 if ret == "": |
144 raise error.ResponseError( | 150 raise error.ResponseError( |
145 _('push failed:'), output) | 151 _('push failed:'), output) |
146 try: | 152 try: |
147 ret = int(ret) | 153 ret = int(ret) |
214 for b in repo.branches(nodes): | 220 for b in repo.branches(nodes): |
215 r.append(encodelist(b) + "\n") | 221 r.append(encodelist(b) + "\n") |
216 return "".join(r) | 222 return "".join(r) |
217 | 223 |
218 def capabilities(repo, proto): | 224 def capabilities(repo, proto): |
219 caps = 'lookup changegroupsubset branchmap pushkey known getbundle'.split() | 225 caps = ('lookup changegroupsubset branchmap pushkey known getbundle ' |
226 'unbundlehash').split() | |
220 if _allowstream(repo.ui): | 227 if _allowstream(repo.ui): |
221 requiredformats = repo.requirements & repo.supportedformats | 228 requiredformats = repo.requirements & repo.supportedformats |
222 # if our local revlogs are just revlogv1, add 'stream' cap | 229 # if our local revlogs are just revlogv1, add 'stream' cap |
223 if not requiredformats - set(('revlogv1',)): | 230 if not requiredformats - set(('revlogv1',)): |
224 caps.append('stream') | 231 caps.append('stream') |
351 def unbundle(repo, proto, heads): | 358 def unbundle(repo, proto, heads): |
352 their_heads = decodelist(heads) | 359 their_heads = decodelist(heads) |
353 | 360 |
354 def check_heads(): | 361 def check_heads(): |
355 heads = repo.heads() | 362 heads = repo.heads() |
356 return their_heads == ['force'] or their_heads == heads | 363 heads_hash = util.sha1(''.join(sorted(heads))).digest() |
364 return (their_heads == ['force'] or their_heads == heads or | |
365 their_heads == ['hashed', heads_hash]) | |
357 | 366 |
358 proto.redirect() | 367 proto.redirect() |
359 | 368 |
360 # fail early if possible | 369 # fail early if possible |
361 if not check_heads(): | 370 if not check_heads(): |