Merge "Delay initialization of local repos"
diff --git a/tests/fixtures/layout-delayed-repo-init.yaml b/tests/fixtures/layout-delayed-repo-init.yaml
new file mode 100644
index 0000000..79f9898
--- /dev/null
+++ b/tests/fixtures/layout-delayed-repo-init.yaml
@@ -0,0 +1,44 @@
+pipelines:
+ - name: check
+ manager: IndependentPipelineManager
+ trigger:
+ - event: patchset-created
+ success:
+ verified: 1
+ failure:
+ verified: -1
+
+ - name: post
+ manager: IndependentPipelineManager
+ trigger:
+ - event: ref-updated
+ ref: ^(?!refs/).*$
+
+ - name: gate
+ manager: DependentPipelineManager
+ failure-message: Build failed. For information on how to proceed, see http://wiki.example.org/Test_Failures
+ trigger:
+ - event: comment-added
+ approval:
+ - approved: 1
+ success:
+ verified: 2
+ submit: true
+ failure:
+ verified: -2
+ start:
+ verified: 0
+ precedence: high
+
+projects:
+ - name: org/new-project
+ check:
+ - project-merge:
+ - project-test1
+ - project-test2
+ gate:
+ - project-merge:
+ - project-test1
+ - project-test2
+ post:
+ - project-post
diff --git a/tests/test_scheduler.py b/tests/test_scheduler.py
index 4e59db8..85eb8ad 100644
--- a/tests/test_scheduler.py
+++ b/tests/test_scheduler.py
@@ -148,7 +148,11 @@
f.close()
repo.index.add([fn])
- return repo.index.commit(msg)
+ r = repo.index.commit(msg)
+ repo.head.reference = 'master'
+ repo.head.reset(index=True, working_tree=True)
+ repo.git.clean('-x', '-f', '-d')
+ return r
def addPatchset(self, files=[], large=False):
self.latest_patchset += 1
@@ -2445,4 +2449,23 @@
'SUCCESS')
self.assertEqual(A.data['status'], 'MERGED')
self.assertEqual(A.reported, 2)
- self.assertEmptyQueues()
+
+ def test_delayed_repo_init(self):
+ self.config.set('zuul', 'layout_config',
+ 'tests/fixtures/layout-delayed-repo-init.yaml')
+ self.sched.reconfigure(self.config)
+
+ self.init_repo("org/new-project")
+ A = self.fake_gerrit.addFakeChange('org/new-project', 'master', 'A')
+
+ A.addApproval('CRVW', 2)
+ self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
+ self.waitUntilSettled()
+ self.assertEqual(self.getJobFromHistory('project-merge').result,
+ 'SUCCESS')
+ self.assertEqual(self.getJobFromHistory('project-test1').result,
+ 'SUCCESS')
+ self.assertEqual(self.getJobFromHistory('project-test2').result,
+ 'SUCCESS')
+ self.assertEqual(A.data['status'], 'MERGED')
+ self.assertEqual(A.reported, 2)
diff --git a/zuul/merger.py b/zuul/merger.py
index 8ab3ee8..94db499 100644
--- a/zuul/merger.py
+++ b/zuul/merger.py
@@ -29,24 +29,37 @@
def __init__(self, remote, local, email, username):
self.remote_url = remote
self.local_path = local
- self._ensure_cloned()
- self.repo = git.Repo(self.local_path)
- if email:
- self.repo.config_writer().set_value('user', 'email', email)
- if username:
- self.repo.config_writer().set_value('user', 'name', username)
- self.repo.config_writer().write()
+ self.email = email
+ self.username = username
+ self._initialized = False
+ try:
+ self._ensure_cloned()
+ except:
+ self.log.exception("Unable to initialize repo for %s" % remote)
def _ensure_cloned(self):
+ if self._initialized:
+ return
if not os.path.exists(self.local_path):
self.log.debug("Cloning from %s to %s" % (self.remote_url,
self.local_path))
git.Repo.clone_from(self.remote_url, self.local_path)
+ self.repo = git.Repo(self.local_path)
+ if self.email:
+ self.repo.config_writer().set_value('user', 'email',
+ self.email)
+ if self.username:
+ self.repo.config_writer().set_value('user', 'name',
+ self.username)
+ self.repo.config_writer().write()
+ self._initialized = True
def recreateRepoObject(self):
+ self._ensure_cloned()
self.repo = git.Repo(self.local_path)
def reset(self):
+ self._ensure_cloned()
self.log.debug("Resetting repository %s" % self.local_path)
self.update()
origin = self.repo.remotes.origin
@@ -64,21 +77,25 @@
return self.repo.heads[branch]
def checkout(self, ref):
+ self._ensure_cloned()
self.log.debug("Checking out %s" % ref)
self.repo.head.reference = ref
self.repo.head.reset(index=True, working_tree=True)
def cherryPick(self, ref):
+ self._ensure_cloned()
self.log.debug("Cherry-picking %s" % ref)
self.fetch(ref)
self.repo.git.cherry_pick("FETCH_HEAD")
def merge(self, ref):
+ self._ensure_cloned()
self.log.debug("Merging %s" % ref)
self.fetch(ref)
self.repo.git.merge("FETCH_HEAD")
def fetch(self, ref):
+ self._ensure_cloned()
# The git.remote.fetch method may read in git progress info and
# interpret it improperly causing an AssertionError. Because the
# data was fetched properly subsequent fetches don't seem to fail.
@@ -97,16 +114,19 @@
self.repo = git.Repo(self.local_path)
def createZuulRef(self, ref, commit='HEAD'):
+ self._ensure_cloned()
self.log.debug("CreateZuulRef %s at %s " % (ref, commit))
ref = ZuulReference.create(self.repo, ref, commit)
return ref.commit
def push(self, local, remote):
+ self._ensure_cloned()
self.log.debug("Pushing %s:%s to %s " % (local, remote,
self.remote_url))
self.repo.remotes.origin.push('%s:%s' % (local, remote))
def update(self):
+ self._ensure_cloned()
self.log.debug("Updating repository %s" % self.local_path)
origin = self.repo.remotes.origin
origin.update()
@@ -151,7 +171,7 @@
self.repos[project] = repo
except:
- self.log.exception("Unable to initialize repo for %s" % project)
+ self.log.exception("Unable to add project %s" % project)
def getRepo(self, project):
r = self.repos.get(project, None)