From 4886f2853395f342db41628958b76989d8772a96 Mon Sep 17 00:00:00 2001 From: "James E. Blair" Date: Thu, 15 Nov 2012 09:27:33 -0800 Subject: [PATCH] Reinitialize the repo object after a fetch. If a large change is fetched, it may arrive in only a pack file, which tickles the invalid cache bug in git-python. Fixes bug 1078946. Change-Id: Ib912967e37c6aed906d86dc35a4b4a65e4f9c3bd Reviewed-on: https://review.openstack.org/16199 Reviewed-by: Monty Taylor Approved: Clark Boylan Reviewed-by: Clark Boylan Tested-by: Jenkins --- tests/test_scheduler.py | 53 ++++++++++++++++++++++++++++++++++------- zuul/merger.py | 7 ++++++ 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/tests/test_scheduler.py b/tests/test_scheduler.py index 8ba6594edc..cbc006ea38 100644 --- a/tests/test_scheduler.py +++ b/tests/test_scheduler.py @@ -29,6 +29,7 @@ import re import urllib2 import urlparse import shutil +import string import git import zuul @@ -93,7 +94,8 @@ def init_repo(project): repo.git.clean('-x', '-f', '-d') -def add_fake_change_to_repo(project, branch, change_num, patchset, msg, fn): +def add_fake_change_to_repo(project, branch, change_num, patchset, msg, fn, + large): path = os.path.join(UPSTREAM_ROOT, project) repo = git.Repo(path) ref = ChangeReference.create(repo, '1/%s/%s' % (change_num, @@ -104,11 +106,21 @@ def add_fake_change_to_repo(project, branch, change_num, patchset, msg, fn): repo.git.clean('-x', '-f', '-d') path = os.path.join(UPSTREAM_ROOT, project) - fn = os.path.join(path, fn) - f = open(fn, 'w') - f.write("test %s %s %s\n" % (branch, change_num, patchset)) - f.close() - repo.index.add([fn]) + if not large: + fn = os.path.join(path, fn) + f = open(fn, 'w') + f.write("test %s %s %s\n" % (branch, change_num, patchset)) + f.close() + repo.index.add([fn]) + else: + for fni in range(100): + fn = os.path.join(path, str(fni)) + f = open(fn, 'w') + for ci in range(4096): + f.write(random.choice(string.printable)) + f.close() + repo.index.add([fn]) + return repo.index.commit(msg) @@ -180,7 +192,7 @@ class FakeChange(object): self.addPatchset() self.data['submitRecords'] = self.getSubmitRecords() - def addPatchset(self, files=None): + def addPatchset(self, files=None, large=False): self.latest_patchset += 1 if files: fn = files[0] @@ -189,7 +201,7 @@ class FakeChange(object): msg = self.subject + '-' + str(self.latest_patchset) c = add_fake_change_to_repo(self.project, self.branch, self.number, self.latest_patchset, - msg, fn) + msg, fn, large) d = {'approvals': [], 'createdOn': time.time(), 'files': [{'file': '/COMMIT_MSG', @@ -1563,6 +1575,31 @@ class testScheduler(unittest.TestCase): assert A.reported == 2 self.assertEmptyQueues() + def test_merger_repack_large_change(self): + "Test that the merger works with large changes after a repack" + # https://bugs.launchpad.net/zuul/+bug/1078946 + A = self.fake_gerrit.addFakeChange('org/project1', 'master', 'A') + A.addPatchset(large=True) + path = os.path.join(UPSTREAM_ROOT, "org/project1") + os.system('git --git-dir=%s/.git repack -afd' % path) + path = os.path.join(GIT_ROOT, "org/project1") + os.system('git --git-dir=%s/.git repack -afd' % path) + + A.addApproval('CRVW', 2) + self.fake_gerrit.addEvent(A.addApproval('APRV', 1)) + self.waitUntilSettled() + jobs = self.fake_jenkins.job_history + job_names = [x['name'] for x in jobs] + assert 'project1-merge' in job_names + assert 'project1-test1' in job_names + assert 'project1-test2' in job_names + assert jobs[0]['result'] == 'SUCCESS' + assert jobs[1]['result'] == 'SUCCESS' + assert jobs[2]['result'] == 'SUCCESS' + assert A.data['status'] == 'MERGED' + assert A.reported == 2 + self.assertEmptyQueues() + def test_nonexistent_job(self): "Test launching a job that doesn't exist" self.fake_jenkins.nonexistent_jobs.append('project-merge') diff --git a/zuul/merger.py b/zuul/merger.py index 8bc4245a09..1141fd1688 100644 --- a/zuul/merger.py +++ b/zuul/merger.py @@ -84,6 +84,13 @@ class Repo(object): except AssertionError: origin.fetch(ref) + # If the repository is packed, and we fetch a change that is + # also entirely packed, the cache may be out of date for the + # same reason as reset() above. Avoid these problems by + # recreating the repo object. + # https://bugs.launchpad.net/zuul/+bug/1078946 + self.repo = git.Repo(self.local_path) + def createZuulRef(self, ref): ref = ZuulReference.create(self.repo, ref, 'HEAD') return ref