From eaa06853a161d87b1623cf56f75d3ec404ba06f6 Mon Sep 17 00:00:00 2001 From: Richard Maw Date: Wed, 29 Apr 2015 11:16:54 +0000 Subject: RemoteRefManager: Fail all ref updates when one fails There's no API to do it in one push yet, but we can send a delete for all the branches that *did* commit. Change-Id: I671e9384b84657a3e9034d62818caa0ac0d8de1e --- morphlib/branchmanager.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'morphlib/branchmanager.py') diff --git a/morphlib/branchmanager.py b/morphlib/branchmanager.py index 92a1f4be..ebec7fe6 100644 --- a/morphlib/branchmanager.py +++ b/morphlib/branchmanager.py @@ -17,6 +17,7 @@ import cliapp import collections import morphlib +from morphlib.gitdir import PushFailureError as _PushFailureError class RefCleanupError(cliapp.AppException): @@ -212,11 +213,36 @@ class RemoteRefManager(object): after the end of the block the with statement the RemoteRefManager is used in. + If any of the refspecs failed to push, then they are all rolled back. + The result includes ones that had succeeded, but if you want to re-try + some refspecs, you need to re-try the ones that succeeded as well as + the ones that failed. + ''' # Calculate the refspecs required to undo the pushed changes. delete_specs = tuple(rs.revert() for rs in refspecs) - result = remote.push(*refspecs) + try: + result = remote.push(*refspecs) + except _PushFailureError as e: # pragma: no cover + results = set(e.results) + e.results = results + # Skip deletes if we didn't fail because a ref update failed + if not results: + raise + + undorefspecs = set() + for flag, sha1, target, summary, reason in results: + for rs in refspecs: + if rs.target == target and rs.source == sha1: + break + if flag != '!': + undorefspecs.add(rs.revert()) + # We may have nothing to undo because all our pushes failed + if undorefspecs: + remote.push(*undorefspecs) + raise + # Register cleanup after pushing, so that if this push fails, # we don't try to undo it. self._cleanup.append((remote, delete_specs)) -- cgit v1.2.1