From a907be75dca2d0ca7adac0a025432cbe4eb2e529 Mon Sep 17 00:00:00 2001 From: Sam Thursfield Date: Fri, 24 Aug 2012 18:48:15 +0100 Subject: Always ls-tree before trying to cat-file This provides much better performance in cases where most of the repos do not have a .morph included. --- morphlib/morphologyfactory.py | 60 ++++++++++++++++--------------------- morphlib/morphologyfactory_tests.py | 11 ++++++- 2 files changed, 35 insertions(+), 36 deletions(-) diff --git a/morphlib/morphologyfactory.py b/morphlib/morphologyfactory.py index c03d541e..ab56afde 100644 --- a/morphlib/morphologyfactory.py +++ b/morphlib/morphologyfactory.py @@ -44,10 +44,31 @@ class MorphologyFactory(object): self._rrc = remote_repo_cache def get_morphology(self, reponame, sha1, filename): - try: - text = self._cat_text(reponame, sha1, filename) - except: - text = self._autodetect_text(reponame, sha1, filename) + + text = None + if self._lrc.has_repo(reponame): + repo = self._lrc.get_repo(reponame) + file_list = repo.ls_tree(sha1) + if filename in file_list: + text = repo.cat(sha1, filename) + elif self._rrc is not None: + file_list = self._rrc.ls_tree(reponame, sha1) + if filename in file_list: + text = self._rrc.cat_file(reponame, sha1, filename) + else: + raise NotcachedError(reponame) + + if text is None: + bs = morphlib.buildsystem.detect_build_system(file_list) + if bs is None: + raise AutodetectError(reponame, sha1) + # TODO consider changing how morphs are located to be by morph + # name rather than filename, it would save creating a + # filename only to strip it back to its morph name again + # and would allow future changes like morphologies being + # stored as git metadata instead of as a file in the repo + morph_name = filename[:-len('.morph')] + text = bs.get_morphology_text(morph_name) try: morphology = morphlib.morph2.Morphology(text) @@ -62,37 +83,6 @@ class MorphologyFactory(object): return morphology - def _cat_text(self, reponame, sha1, filename): - if self._lrc.has_repo(reponame): - repo = self._lrc.get_repo(reponame) - return repo.cat(sha1, filename) - elif self._rrc is not None: - return self._rrc.cat_file(reponame, sha1, filename) - else: - raise NotcachedError(reponame) - - def _autodetect_text(self, reponame, sha1, filename): - if self._lrc.has_repo(reponame): - repo = self._lrc.get_repo(reponame) - file_list = repo.ls_tree(sha1) - elif self._rrc is not None: - file_list = self._rrc.ls_tree(reponame, sha1) - else: - raise NotcachedError(reponame) - - bs = morphlib.buildsystem.detect_build_system(file_list) - if bs is None: - raise AutodetectError(reponame, sha1) - # TODO consider changing how morphs are located to be by morph - # name rather than filename, it would save creating a - # filename only to strip it back to its morph name again - # and would allow future changes like morphologies being - # stored as git metadata instead of as a file in the repo - assert filename.endswith('.morph') - morph_name = filename[:-len('.morph')] - morph_text = bs.get_morphology_text(morph_name) - return morph_text - def _check_and_tweak_system(self, morphology, reponame, sha1, filename): '''Check and tweak a system morphology.''' diff --git a/morphlib/morphologyfactory_tests.py b/morphlib/morphologyfactory_tests.py index 9d6900d7..8b69f1de 100644 --- a/morphlib/morphologyfactory_tests.py +++ b/morphlib/morphologyfactory_tests.py @@ -90,7 +90,7 @@ class FakeLocalRepo(object): return 'text' def ls_tree(self, sha1): - return [] + return self.morphologies.keys() class FakeLocalRepoCache(object): @@ -119,6 +119,9 @@ class MorphologyFactoryTests(unittest.TestCase): def noremotefile(self, *args): raise CatFileError('reponame', 'ref', 'filename') + def localmorph(self, *args): + return ['foo.morph'] + def nolocalmorph(self, *args): if args[-1].endswith('.morph'): raise IOError('File not found') @@ -127,6 +130,9 @@ class MorphologyFactoryTests(unittest.TestCase): def autotoolsbuildsystem(self, *args): return ['configure.in'] + def remotemorph(self, *args): + return ['foo.morph'] + def noremotemorph(self, *args): if args[-1].endswith('.morph'): raise CatFileError('reponame', 'ref', 'filename') @@ -136,11 +142,13 @@ class MorphologyFactoryTests(unittest.TestCase): return False def test_gets_morph_from_local_repo(self): + self.lr.ls_tree = self.localmorph morph = self.mf.get_morphology('reponame', 'sha1', 'foo.morph') self.assertEqual('local-foo', morph['name']) def test_gets_morph_from_remote_repo(self): + self.rrc.ls_tree = self.remotemorph self.lrc.has_repo = self.doesnothaverepo morph = self.mf.get_morphology('reponame', 'sha1', 'foo.morph') @@ -174,6 +182,7 @@ class MorphologyFactoryTests(unittest.TestCase): 'reponame', 'sha1', 'unreached.morph') def test_looks_locally_with_no_remote(self): + self.lr.ls_tree = self.localmorph morph = self.lmf.get_morphology('reponame', 'sha1', 'foo.morph') self.assertEqual('local-foo', morph['name']) -- cgit v1.2.1