comparison mercurial/wireproto.py @ 11593:d054cc5c7737

protocol: unify unbundle on the server side
author Matt Mackall <mpm@selenic.com>
date Thu, 15 Jul 2010 11:24:42 -0500
parents 26e0782b8380
children 67863f9d805f
comparison
equal deleted inserted replaced
11592:26e0782b8380 11593:d054cc5c7737
3 # Copyright 2005-2010 Matt Mackall <mpm@selenic.com> 3 # Copyright 2005-2010 Matt Mackall <mpm@selenic.com>
4 # 4 #
5 # This software may be used and distributed according to the terms of the 5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version. 6 # GNU General Public License version 2 or any later version.
7 7
8 import urllib, tempfile, os
8 from i18n import _ 9 from i18n import _
9 from node import bin, hex 10 from node import bin, hex
10 import urllib 11 import changegroup as changegroupmod
11 import streamclone, repo, error, encoding 12 import streamclone, repo, error, encoding, util
12 import pushkey as pushkey_ 13 import pushkey as pushkey_
13 14
14 # client side 15 # client side
15 16
16 class wirerepository(repo.repository): 17 class wirerepository(repo.repository):
196 try: 197 try:
197 proto.sendstream(streamclone.stream_out(repo)) 198 proto.sendstream(streamclone.stream_out(repo))
198 except streamclone.StreamException, inst: 199 except streamclone.StreamException, inst:
199 return str(inst) 200 return str(inst)
200 201
202 def unbundle(repo, proto, heads):
203 their_heads = heads.split()
204
205 def check_heads():
206 heads = map(hex, repo.heads())
207 return their_heads == [hex('force')] or their_heads == heads
208
209 # fail early if possible
210 if not check_heads():
211 repo.respond(_('unsynced changes'))
212 return
213
214 # write bundle data to temporary file because it can be big
215 fd, tempname = tempfile.mkstemp(prefix='hg-unbundle-')
216 fp = os.fdopen(fd, 'wb+')
217 r = 0
218 proto.redirect()
219 try:
220 proto.getfile(fp)
221 lock = repo.lock()
222 try:
223 if not check_heads():
224 # someone else committed/pushed/unbundled while we
225 # were transferring data
226 proto.respond(_('unsynced changes'))
227 return
228
229 # push can proceed
230 fp.seek(0)
231 header = fp.read(6)
232 if header.startswith('HG'):
233 if not header.startswith('HG10'):
234 raise ValueError('unknown bundle version')
235 elif header not in changegroupmod.bundletypes:
236 raise ValueError('unknown bundle compression type')
237 gen = changegroupmod.unbundle(header, fp)
238
239 try:
240 r = repo.addchangegroup(gen, 'serve', proto._client(),
241 lock=lock)
242 except util.Abort, inst:
243 sys.stderr.write("abort: %s\n" % inst)
244 finally:
245 lock.release()
246 proto.respondpush(r)
247
248 finally:
249 fp.close()
250 os.unlink(tempname)
251
201 commands = { 252 commands = {
202 'between': (between, 'pairs'), 253 'between': (between, 'pairs'),
203 'branchmap': (branchmap, ''), 254 'branchmap': (branchmap, ''),
204 'branches': (branches, 'nodes'), 255 'branches': (branches, 'nodes'),
205 'changegroup': (changegroup, 'roots'), 256 'changegroup': (changegroup, 'roots'),
207 'heads': (heads, ''), 258 'heads': (heads, ''),
208 'listkeys': (listkeys, 'namespace'), 259 'listkeys': (listkeys, 'namespace'),
209 'lookup': (lookup, 'key'), 260 'lookup': (lookup, 'key'),
210 'pushkey': (pushkey, 'namespace key old new'), 261 'pushkey': (pushkey, 'namespace key old new'),
211 'stream_out': (stream, ''), 262 'stream_out': (stream, ''),
263 'unbundle': (unbundle, 'heads'),
212 } 264 }