Reset repos with files named 'HEAD'
If a git repo has the misfortune to have a file with the name "HEAD" at the root level of the repo, git will return an error because it is unsure whether the file or ref is meant. Call 'git reset' with '--' at the end of the command to disambiguate and instruct git that the HEAD ref is meant. Change-Id: Icb19063afafa1e0719b3354470c14df8168a64b5
This commit is contained in:
parent
1c42a2ab47
commit
879dafb5b9
@ -47,8 +47,9 @@ import zuul.webapp
|
||||
import zuul.rpclistener
|
||||
import zuul.launcher.gearman
|
||||
import zuul.lib.swift
|
||||
import zuul.merger.server
|
||||
import zuul.merger.client
|
||||
import zuul.merger.merger
|
||||
import zuul.merger.server
|
||||
import zuul.reporter.gerrit
|
||||
import zuul.reporter.smtp
|
||||
import zuul.trigger.gerrit
|
||||
@ -145,7 +146,7 @@ class FakeChange(object):
|
||||
self.latest_patchset),
|
||||
'refs/tags/init')
|
||||
repo.head.reference = ref
|
||||
repo.head.reset(index=True, working_tree=True)
|
||||
zuul.merger.merger.reset_repo_to_head(repo)
|
||||
repo.git.clean('-x', '-f', '-d')
|
||||
|
||||
path = os.path.join(self.upstream_root, self.project)
|
||||
@ -167,7 +168,7 @@ class FakeChange(object):
|
||||
|
||||
r = repo.index.commit(msg)
|
||||
repo.head.reference = 'master'
|
||||
repo.head.reset(index=True, working_tree=True)
|
||||
zuul.merger.merger.reset_repo_to_head(repo)
|
||||
repo.git.clean('-x', '-f', '-d')
|
||||
repo.heads['master'].checkout()
|
||||
return r
|
||||
@ -1045,7 +1046,7 @@ class ZuulTestCase(BaseTestCase):
|
||||
repo.create_tag('init')
|
||||
|
||||
repo.head.reference = master
|
||||
repo.head.reset(index=True, working_tree=True)
|
||||
zuul.merger.merger.reset_repo_to_head(repo)
|
||||
repo.git.clean('-x', '-f', '-d')
|
||||
|
||||
self.create_branch(project, 'mp')
|
||||
@ -1064,7 +1065,7 @@ class ZuulTestCase(BaseTestCase):
|
||||
repo.index.commit('%s commit' % branch)
|
||||
|
||||
repo.head.reference = repo.heads['master']
|
||||
repo.head.reset(index=True, working_tree=True)
|
||||
zuul.merger.merger.reset_repo_to_head(repo)
|
||||
repo.git.clean('-x', '-f', '-d')
|
||||
|
||||
def ref_has_change(self, ref, change):
|
||||
|
@ -2036,6 +2036,30 @@ class TestScheduler(ZuulTestCase):
|
||||
self.assertEqual(self.history[0].name, 'gate-noop')
|
||||
self.assertEqual(self.history[0].result, 'SUCCESS')
|
||||
|
||||
def test_file_head(self):
|
||||
# This is a regression test for an observed bug. A change
|
||||
# with a file named "HEAD" in the root directory of the repo
|
||||
# was processed by a merger. It then was unable to reset the
|
||||
# repo because of:
|
||||
# GitCommandError: 'git reset --hard HEAD' returned
|
||||
# with exit code 128
|
||||
# stderr: 'fatal: ambiguous argument 'HEAD': both revision
|
||||
# and filename
|
||||
# Use '--' to separate filenames from revisions'
|
||||
|
||||
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
||||
A.addPatchset(['HEAD'])
|
||||
B = self.fake_gerrit.addFakeChange('org/project', 'master', 'B')
|
||||
|
||||
self.fake_gerrit.addEvent(A.getPatchsetCreatedEvent(2))
|
||||
self.waitUntilSettled()
|
||||
|
||||
self.fake_gerrit.addEvent(B.getPatchsetCreatedEvent(1))
|
||||
self.waitUntilSettled()
|
||||
|
||||
self.assertIn('Build succeeded', A.messages[0])
|
||||
self.assertIn('Build succeeded', B.messages[0])
|
||||
|
||||
def test_file_jobs(self):
|
||||
"Test that file jobs run only when appropriate"
|
||||
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
|
||||
|
@ -20,6 +20,21 @@ import logging
|
||||
import zuul.model
|
||||
|
||||
|
||||
def reset_repo_to_head(repo):
|
||||
# This lets us reset the repo even if there is a file in the root
|
||||
# directory named 'HEAD'. Currently, GitPython does not allow us
|
||||
# to instruct it to always include the '--' to disambiguate. This
|
||||
# should no longer be necessary if this PR merges:
|
||||
# https://github.com/gitpython-developers/GitPython/pull/319
|
||||
try:
|
||||
repo.git.reset('--hard', 'HEAD', '--')
|
||||
except git.GitCommandError as e:
|
||||
# git nowadays may use 1 as status to indicate there are still unstaged
|
||||
# modifications after the reset
|
||||
if e.status != 1:
|
||||
raise
|
||||
|
||||
|
||||
class ZuulReference(git.Reference):
|
||||
_common_path_default = "refs/zuul"
|
||||
_points_to_commits_only = True
|
||||
@ -82,7 +97,7 @@ class Repo(object):
|
||||
|
||||
# Reset to remote HEAD (usually origin/master)
|
||||
repo.head.reference = origin.refs['HEAD']
|
||||
repo.head.reset(index=True, working_tree=True)
|
||||
reset_repo_to_head(repo)
|
||||
repo.git.clean('-x', '-f', '-d')
|
||||
|
||||
def prune(self):
|
||||
@ -114,7 +129,7 @@ class Repo(object):
|
||||
repo = self.createRepoObject()
|
||||
self.log.debug("Checking out %s" % ref)
|
||||
repo.head.reference = ref
|
||||
repo.head.reset(index=True, working_tree=True)
|
||||
reset_repo_to_head(repo)
|
||||
|
||||
def cherryPick(self, ref):
|
||||
repo = self.createRepoObject()
|
||||
|
Loading…
Reference in New Issue
Block a user