diff options
author | Sam Thursfield <sam.thursfield@codethink.co.uk> | 2015-02-19 17:14:15 +0000 |
---|---|---|
committer | Sam Thursfield <sam.thursfield@codethink.co.uk> | 2015-02-20 13:48:33 +0000 |
commit | 9cdeacaea8528c1bc090046715374882e9be0e15 (patch) | |
tree | e5138900758950e066f2a5f28c6814b6c3151664 /morphlib | |
parent | 88e8767791d85aa0d01715f04b7e0f311f54759e (diff) | |
download | morph-9cdeacaea8528c1bc090046715374882e9be0e15.tar.gz |
sourceresolver: Fix LsTreeError raised when constructing build graph
If you had a repo that was not in your local or remote cache in your
definitions, Morph might raise LsTreeError and abort.
The code was assuming the repo would already be cached in the local
cache by the time it got to detecting build systems, but that's not
always true -- if the (reponame, ref) pair was already in the
'resolved_trees' cache but the repo had been deleted from the local
Git cache, to name one possibility.
Also, the remoterepocache.ls_tree operation can fail if the repo is
not hosted in the Trove, so we shouldn't abort the program in that case.
Finally, this patch removes an unused variable.
Diffstat (limited to 'morphlib')
-rw-r--r-- | morphlib/sourceresolver.py | 26 | ||||
-rw-r--r-- | morphlib/sourceresolver_tests.py | 23 |
2 files changed, 40 insertions, 9 deletions
diff --git a/morphlib/sourceresolver.py b/morphlib/sourceresolver.py index 29069d7d..0c2d1a0a 100644 --- a/morphlib/sourceresolver.py +++ b/morphlib/sourceresolver.py @@ -233,6 +233,7 @@ class SourceResolver(object): loader = morphlib.morphloader.MorphologyLoader() + morph = None if defs_filename and os.path.exists(defs_filename): # pragma: no cover morph = loader.load_from_file(defs_filename) elif self.lrc.has_repo(reponame): @@ -245,7 +246,6 @@ class SourceResolver(object): morph = loader.load_from_string(text) except IOError: morph = None - file_list = repo.list_files(ref=sha1, recurse=False) elif self.rrc is not None: self.status(msg="Looking for %(reponame)s:%(filename)s in the " "remote repo cache.", @@ -280,16 +280,28 @@ class SourceResolver(object): "chunk morph from repo's build system" % expected_filename, chatty=True) + file_list = None + if self.lrc.has_repo(reponame): repo = self.lrc.get_repo(reponame) file_list = repo.list_files(ref=sha1, recurse=False) elif self.rrc is not None: - file_list = self.rrc.ls_tree(reponame, sha1) - else: - # We assume that _resolve_ref() must have already been called and - # so the repo in question would have been made available already - # if it had been possible. - raise NotcachedError(reponame) + try: + # This may or may not succeed; if the is repo not + # hosted on the same Git server as the cache server then + # it'll definitely fail. + file_list = self.rrc.ls_tree(reponame, sha1) + except morphlib.remoterepocache.LsTreeError: + pass + if not file_list: + if self.update: + self.status(msg='Caching git repository %(reponame)s', + reponame=reponame) + repo = self.lrc.cache_repo(reponame) + repo.update() + file_list = repo.list_files(ref=sha1, recurse=False) + else: # pragma: no cover + raise NotcachedError(reponame) buildsystem = morphlib.buildsystem.detect_build_system(file_list) diff --git a/morphlib/sourceresolver_tests.py b/morphlib/sourceresolver_tests.py index 2410218a..6d6a83fa 100644 --- a/morphlib/sourceresolver_tests.py +++ b/morphlib/sourceresolver_tests.py @@ -24,7 +24,7 @@ from morphlib.sourceresolver import (SourceResolver, PickleCacheManager, MorphologyNotFoundError, NotcachedError) -from morphlib.remoterepocache import CatFileError +from morphlib.remoterepocache import CatFileError, LsTreeError class FakeRemoteRepoCache(object): @@ -135,6 +135,9 @@ class FakeLocalRepo(object): def list_files(self, ref, recurse): return self.morphologies.keys() + def update(self): + pass + class FakeLocalRepoCache(object): @@ -147,6 +150,9 @@ class FakeLocalRepoCache(object): def get_repo(self, reponame): return self.lr + def cache_repo(self, reponame): + return self.lr + class SourceResolverTests(unittest.TestCase): @@ -188,6 +194,9 @@ class SourceResolverTests(unittest.TestCase): def noremotefile(self, *args): raise CatFileError('reponame', 'ref', 'filename') + def noremoterepo(self, *args): + raise LsTreeError('reponame', 'ref') + def localmorph(self, *args): return ['chunk.morph'] @@ -241,6 +250,15 @@ class SourceResolverTests(unittest.TestCase): 'assumed-local.morph') self.assertEqual('autotools', name) + def test_cache_repo_if_not_in_either_cache(self): + self.lrc.has_repo = self.doesnothaverepo + self.lr.read_file = self.nolocalmorph + self.lr.list_files = self.autotoolsbuildsystem + self.rrc.ls_tree = self.noremoterepo + name = self.sr._detect_build_system('reponame', 'sha1', + 'assumed-local.morph') + self.assertEqual('autotools', name) + def test_autodetects_remote_morphology(self): self.lrc.has_repo = self.doesnothaverepo self.rrc.cat_file = self.noremotemorph @@ -262,7 +280,8 @@ class SourceResolverTests(unittest.TestCase): def test_raises_error_when_repo_does_not_exist(self): self.lrc.has_repo = self.doesnothaverepo - self.assertRaises(NotcachedError, self.lsr._detect_build_system, + self.assertRaises(MorphologyNotFoundError, + self.lsr._detect_build_system, 'reponame', 'sha1', 'non-existent.morph') def test_raises_error_when_failed_to_detect_build_system(self): |