summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Thursfield <sam.thursfield@codethink.co.uk>2012-08-24 18:48:15 +0100
committerSam Thursfield <sam.thursfield@codethink.co.uk>2012-08-24 18:48:15 +0100
commita907be75dca2d0ca7adac0a025432cbe4eb2e529 (patch)
tree905603c1a60763055d77ca4e0257f4e1edeb78c7
parent3525f81ecea60f53d3ef842c1e11c4cab1538511 (diff)
downloadmorph-a907be75dca2d0ca7adac0a025432cbe4eb2e529.tar.gz
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.
-rw-r--r--morphlib/morphologyfactory.py60
-rw-r--r--morphlib/morphologyfactory_tests.py11
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'])