Mercurial > public > mercurial-scm > hg
comparison mercurial/bundle2.py @ 34152:21c2df59a1da
bundle2: move exception handling into part iterator
As part of separating the part iteration logic from the part handling logic,
let's move the exception handling to the part iterator class.
Differential Revision: https://phab.mercurial-scm.org/D705
author | Durham Goode <durham@fb.com> |
---|---|
date | Wed, 13 Sep 2017 20:39:01 -0700 |
parents | 550343626bb2 |
children | 8e0358024a36 |
comparison
equal
deleted
inserted
replaced
34151:550343626bb2 | 34152:21c2df59a1da |
---|---|
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 | 349 |
350 class partiterator(object): | 350 class partiterator(object): |
351 def __init__(self, repo, unbundler): | 351 def __init__(self, repo, op, unbundler): |
352 self.repo = repo | 352 self.repo = repo |
353 self.op = op | |
353 self.unbundler = unbundler | 354 self.unbundler = unbundler |
354 self.iterator = None | 355 self.iterator = None |
355 self.count = 0 | 356 self.count = 0 |
356 | 357 |
357 def __enter__(self): | 358 def __enter__(self): |
361 self.count = count | 362 self.count = count |
362 yield p | 363 yield p |
363 self.iterator = func() | 364 self.iterator = func() |
364 return self.iterator | 365 return self.iterator |
365 | 366 |
366 def __exit__(self, type, value, tb): | 367 def __exit__(self, type, exc, tb): |
367 if not self.iterator: | 368 if not self.iterator: |
368 return | 369 return |
370 | |
371 if exc: | |
372 # Any exceptions seeking to the end of the bundle at this point are | |
373 # almost certainly related to the underlying stream being bad. | |
374 # And, chances are that the exception we're handling is related to | |
375 # getting in that bad state. So, we swallow the seeking error and | |
376 # re-raise the original error. | |
377 seekerror = False | |
378 try: | |
379 for part in self.iterator: | |
380 # consume the bundle content | |
381 part.seek(0, 2) | |
382 except Exception: | |
383 seekerror = True | |
384 | |
385 # Small hack to let caller code distinguish exceptions from bundle2 | |
386 # processing from processing the old format. This is mostly needed | |
387 # to handle different return codes to unbundle according to the type | |
388 # of bundle. We should probably clean up or drop this return code | |
389 # craziness in a future version. | |
390 exc.duringunbundle2 = True | |
391 salvaged = [] | |
392 replycaps = None | |
393 if self.op.reply is not None: | |
394 salvaged = self.op.reply.salvageoutput() | |
395 replycaps = self.op.reply.capabilities | |
396 exc._replycaps = replycaps | |
397 exc._bundle2salvagedoutput = salvaged | |
398 | |
399 # Re-raising from a variable loses the original stack. So only use | |
400 # that form if we need to. | |
401 if seekerror: | |
402 raise exc | |
369 | 403 |
370 self.repo.ui.debug('bundle2-input-bundle: %i parts total\n' % | 404 self.repo.ui.debug('bundle2-input-bundle: %i parts total\n' % |
371 self.count) | 405 self.count) |
372 | 406 |
373 def processbundle(repo, unbundler, transactiongetter=None, op=None): | 407 def processbundle(repo, unbundler, transactiongetter=None, op=None): |
400 else: | 434 else: |
401 msg.append(' with-transaction') | 435 msg.append(' with-transaction') |
402 msg.append('\n') | 436 msg.append('\n') |
403 repo.ui.debug(''.join(msg)) | 437 repo.ui.debug(''.join(msg)) |
404 | 438 |
405 with partiterator(repo, unbundler) as parts: | 439 with partiterator(repo, op, unbundler) as parts: |
406 part = None | 440 for part in parts: |
407 try: | 441 _processpart(op, part) |
408 for part in parts: | |
409 _processpart(op, part) | |
410 except Exception as exc: | |
411 # Any exceptions seeking to the end of the bundle at this point are | |
412 # almost certainly related to the underlying stream being bad. | |
413 # And, chances are that the exception we're handling is related to | |
414 # getting in that bad state. So, we swallow the seeking error and | |
415 # re-raise the original error. | |
416 seekerror = False | |
417 try: | |
418 for part in parts: | |
419 # consume the bundle content | |
420 part.seek(0, 2) | |
421 except Exception: | |
422 seekerror = True | |
423 | |
424 # Small hack to let caller code distinguish exceptions from bundle2 | |
425 # processing from processing the old format. This is mostly needed | |
426 # to handle different return codes to unbundle according to the type | |
427 # of bundle. We should probably clean up or drop this return code | |
428 # craziness in a future version. | |
429 exc.duringunbundle2 = True | |
430 salvaged = [] | |
431 replycaps = None | |
432 if op.reply is not None: | |
433 salvaged = op.reply.salvageoutput() | |
434 replycaps = op.reply.capabilities | |
435 exc._replycaps = replycaps | |
436 exc._bundle2salvagedoutput = salvaged | |
437 | |
438 # Re-raising from a variable loses the original stack. So only use | |
439 # that form if we need to. | |
440 if seekerror: | |
441 raise exc | |
442 else: | |
443 raise | |
444 | 442 |
445 return op | 443 return op |
446 | 444 |
447 def _processchangegroup(op, cg, tr, source, url, **kwargs): | 445 def _processchangegroup(op, cg, tr, source, url, **kwargs): |
448 ret = cg.apply(op.repo, tr, source, url, **kwargs) | 446 ret = cg.apply(op.repo, tr, source, url, **kwargs) |