Don't try to delete non-existing local refs

If a remote ref is deleted the merger first deletes the local ref and
then the remote ref. In case the merger was stopped between these two
steps all further reset actions on this repo fail with [1]. This can
be fixed by only deleting existing heads.

[1] Trace:
2018-04-24 11:43:16,401 ERROR zuul.Merger: Unable to update github/org/project
Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/zuul/merger/merger.py", line 446, in updateRepo
    repo.reset()
  File "/usr/lib/python3.6/site-packages/zuul/merger/merger.py", line 195, in reset
    repo.delete_head(ref.remote_head, force=True)
  File "/usr/lib/python3.6/site-packages/git/repo/base.py", line 372, in delete_head
    return Head.delete(self, *heads, **kwargs)
  File "/usr/lib/python3.6/site-packages/git/refs/head.py", line 127, in delete
    repo.git.branch(flag, *heads)
  File "/usr/lib/python3.6/site-packages/git/cmd.py", line 550, in <lambda>
    return lambda *args, **kwargs: self._call_process(name, *args, **kwargs)
  File "/usr/lib/python3.6/site-packages/git/cmd.py", line 1009, in _call_process
    return self.execute(call, **exec_kwargs)
  File "/usr/lib/python3.6/site-packages/git/cmd.py", line 820, in execute
    raise GitCommandError(command, status, stderr_value, stdout_value)
git.exc.GitCommandError: Cmd('git') failed due to: exit code(1)
  cmdline: git branch -D somebranch
  stderr: 'error: branch 'somebranch' not found.'

Change-Id: Ifbfa084ba35d309c2a44fa447e3af1e542b5fdba
This commit is contained in:
Tobias Henkel
2018-04-24 16:22:29 +02:00
parent 623533ab85
commit f30ec067e6
2 changed files with 26 additions and 1 deletions

View File

@@ -150,6 +150,24 @@ class TestMergerRepo(ZuulTestCase):
self.assertTrue(os.path.exists(os.path.join(
self.workspace_root, 'stamp2')))
def test_deleted_local_ref(self):
parent_path = os.path.join(self.upstream_root, 'org/project1')
self.create_branch('org/project1', 'foobar')
work_repo = Repo(parent_path, self.workspace_root,
'none@example.org', 'User Name', '0', '0')
# Delete local ref on the cached repo. This leaves us with a remote
# ref but no local ref anymore.
gitrepo = git.Repo(work_repo.local_path)
gitrepo.delete_head('foobar', force=True)
# Delete the branch upstream.
self.delete_branch('org/project1', 'foobar')
# And now reset the repo again. This should not crash
work_repo.reset()
class TestMergerWithAuthUrl(ZuulTestCase):
config_file = 'zuul-github-driver.conf'

View File

@@ -192,7 +192,14 @@ class Repo(object):
repo.git.clean('-x', '-f', '-d')
for ref in stale_refs:
self.log.debug("Delete stale ref %s", ref.remote_head)
# A stale ref means the upstream branch (e.g. foobar) was deleted
# so we need to delete both our local head (if existing) and the
# remote tracking head. Both repo.heads and ref.remote_head
# contain the pure branch name so they can be compared easily.
for head in repo.heads:
if head.name == ref.remote_head:
repo.delete_head(ref.remote_head, force=True)
break
git.refs.RemoteReference.delete(repo, ref, force=True)
def prune(self):