comparison mercurial/bundle2.py @ 34150:e9e0e1143fc5

bundle2: move part iterator a separate class Currently, the part iterator logic is tightly coupled with the part handling logic, which means it's hard to replace the part handling logic without duplicating the part iterator bits. In a future diff we'll want to be able to replace all part handling, so let's begin refactoring the part iterator logic to it's own class. Differential Revision: https://phab.mercurial-scm.org/D703
author Durham Goode <durham@fb.com>
date Wed, 13 Sep 2017 17:16:45 -0700
parents 5ede882c249c
children 550343626bb2
comparison
equal deleted inserted replaced
34149:75cc1f1e11f2 34150:e9e0e1143fc5
344 else: 344 else:
345 # the transactiongetter won't be used, but we might as well set it 345 # the transactiongetter won't be used, but we might as well set it
346 op = bundleoperation(repo, lambda: tr) 346 op = bundleoperation(repo, lambda: tr)
347 _processchangegroup(op, unbundler, tr, source, url, **kwargs) 347 _processchangegroup(op, unbundler, tr, source, url, **kwargs)
348 return op 348 return op
349
350 class partiterator(object):
351 def __init__(self, unbundler):
352 self.unbundler = unbundler
353
354 def __enter__(self):
355 return enumerate(self.unbundler.iterparts())
356
357 def __exit__(self, type, value, tb):
358 pass
349 359
350 def processbundle(repo, unbundler, transactiongetter=None, op=None): 360 def processbundle(repo, unbundler, transactiongetter=None, op=None):
351 """This function process a bundle, apply effect to/from a repo 361 """This function process a bundle, apply effect to/from a repo
352 362
353 It iterates over each part then searches for and uses the proper handling 363 It iterates over each part then searches for and uses the proper handling
376 msg.append(' no-transaction') 386 msg.append(' no-transaction')
377 else: 387 else:
378 msg.append(' with-transaction') 388 msg.append(' with-transaction')
379 msg.append('\n') 389 msg.append('\n')
380 repo.ui.debug(''.join(msg)) 390 repo.ui.debug(''.join(msg))
381 iterparts = enumerate(unbundler.iterparts()) 391
382 part = None 392 with partiterator(unbundler) as parts:
383 nbpart = 0 393 part = None
384 try: 394 nbpart = 0
385 for nbpart, part in iterparts:
386 _processpart(op, part)
387 except Exception as exc:
388 # Any exceptions seeking to the end of the bundle at this point are
389 # almost certainly related to the underlying stream being bad.
390 # And, chances are that the exception we're handling is related to
391 # getting in that bad state. So, we swallow the seeking error and
392 # re-raise the original error.
393 seekerror = False
394 try: 395 try:
395 for nbpart, part in iterparts: 396 for nbpart, part in parts:
396 # consume the bundle content 397 _processpart(op, part)
397 part.seek(0, 2) 398 except Exception as exc:
398 except Exception: 399 # Any exceptions seeking to the end of the bundle at this point are
399 seekerror = True 400 # almost certainly related to the underlying stream being bad.
400 401 # And, chances are that the exception we're handling is related to
401 # Small hack to let caller code distinguish exceptions from bundle2 402 # getting in that bad state. So, we swallow the seeking error and
402 # processing from processing the old format. This is mostly 403 # re-raise the original error.
403 # needed to handle different return codes to unbundle according to the 404 seekerror = False
404 # type of bundle. We should probably clean up or drop this return code 405 try:
405 # craziness in a future version. 406 for nbpart, part in parts:
406 exc.duringunbundle2 = True 407 # consume the bundle content
407 salvaged = [] 408 part.seek(0, 2)
408 replycaps = None 409 except Exception:
409 if op.reply is not None: 410 seekerror = True
410 salvaged = op.reply.salvageoutput() 411
411 replycaps = op.reply.capabilities 412 # Small hack to let caller code distinguish exceptions from bundle2
412 exc._replycaps = replycaps 413 # processing from processing the old format. This is mostly needed
413 exc._bundle2salvagedoutput = salvaged 414 # to handle different return codes to unbundle according to the type
414 415 # of bundle. We should probably clean up or drop this return code
415 # Re-raising from a variable loses the original stack. So only use 416 # craziness in a future version.
416 # that form if we need to. 417 exc.duringunbundle2 = True
417 if seekerror: 418 salvaged = []
418 raise exc 419 replycaps = None
419 else: 420 if op.reply is not None:
420 raise 421 salvaged = op.reply.salvageoutput()
421 finally: 422 replycaps = op.reply.capabilities
422 repo.ui.debug('bundle2-input-bundle: %i parts total\n' % nbpart) 423 exc._replycaps = replycaps
424 exc._bundle2salvagedoutput = salvaged
425
426 # Re-raising from a variable loses the original stack. So only use
427 # that form if we need to.
428 if seekerror:
429 raise exc
430 else:
431 raise
432 finally:
433 repo.ui.debug('bundle2-input-bundle: %i parts total\n' % nbpart)
423 434
424 return op 435 return op
425 436
426 def _processchangegroup(op, cg, tr, source, url, **kwargs): 437 def _processchangegroup(op, cg, tr, source, url, **kwargs):
427 ret = cg.apply(op.repo, tr, source, url, **kwargs) 438 ret = cg.apply(op.repo, tr, source, url, **kwargs)