summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--morphlib/morphologyfactory.py63
-rw-r--r--morphlib/morphologyfactory_tests.py90
2 files changed, 153 insertions, 0 deletions
diff --git a/morphlib/morphologyfactory.py b/morphlib/morphologyfactory.py
new file mode 100644
index 00000000..5e3bf7f2
--- /dev/null
+++ b/morphlib/morphologyfactory.py
@@ -0,0 +1,63 @@
+#!/usr/bin/python
+#
+# Copyright (C) 2012 Codethink Limited
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+import morphlib
+import cliapp
+
+class MorphologyFactoryError(cliapp.AppException):
+ pass
+
+class AutodetectError(MorphologyFactoryError):
+ def __init__(self, repo_name, ref):
+ MorphologyFactoryError.__init__(self,
+ "Failed to determine the build system of repo %s at "
+ "ref %s" % (repo_name, ref))
+
+class MorphologyFactory(object):
+ '''An way of creating morphologies which will provide a default'''
+
+ def __init__(self, local_repo_cache, remote_repo_cache):
+ self._lrc = local_repo_cache
+ 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)
+ return morphlib.morph2.Morphology(text)
+
+ def _cat_text(self, reponame, sha1, filename):
+ if self._lrc.has_repo(reponame):
+ repo = self._lrc.get_repo(reponame)
+ return repo.cat(sha1, filename)
+ else:
+ return self._rrc.cat_file(reponame, sha1, filename)
+
+ def _autodetect_text(self, reponame, sha1, filename):
+ if self._lrc.has_repo(reponame):
+ repo = self._lrc.get_repo(reponame)
+ files = repo.list_files(sha1)
+ else:
+ files = self._rrc.list_files(reponame, sha1)
+ bs = morphlib.buildsystem.detect_build_system(lambda x: x in files)
+ if bs is None:
+ raise AutodetectError(reponame, sha1)
+ assert filename.endswith('.morph')
+ morph_name = filename[:-len('.morph')]
+ morph_text = bs.get_morphology_text(morph_name)
+ return morph_text
diff --git a/morphlib/morphologyfactory_tests.py b/morphlib/morphologyfactory_tests.py
new file mode 100644
index 00000000..2a0709ed
--- /dev/null
+++ b/morphlib/morphologyfactory_tests.py
@@ -0,0 +1,90 @@
+# Copyright (C) 2012 Codethink Limited
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+
+import unittest
+
+from morphlib.morph2 import Morphology
+from morphlib.morphologyfactory import MorphologyFactory, AutodetectError
+
+class FakeRemoteRepoCache(object):
+ def cat_file(self, reponame, sha1, filename):
+ return '''{
+ "name": "remote-foo",
+ "kind": "chunk",
+ "build-system": "bar"
+ }'''
+ def list_files(self, reponame, sha1):
+ return ['configure', 'Makefile']
+
+class FakeLocalRepo(object):
+ def cat(self, sha1, filename):
+ return '''{
+ "name": "local-foo",
+ "kind": "chunk",
+ "build-system": "bar"
+ }'''
+ def list_files(self, sha1):
+ return ['configure', 'Makefile']
+
+class FakeLocalRepoCache(object):
+ def __init__(self, lr):
+ self.lr = lr
+ def has_repo(self, reponame):
+ return True
+ def get_repo(self, reponame):
+ return self.lr
+
+class MorphologyFactoryTests(unittest.TestCase):
+ def setUp(self):
+ self.lr = FakeLocalRepo()
+ self.lrc = FakeLocalRepoCache(self.lr)
+ self.rrc = FakeRemoteRepoCache()
+ self.mf = MorphologyFactory(self.lrc, self.rrc)
+
+ def nosuchfile(self):
+ raise IOError('File not found')
+ def doesnothaverepo(self, reponame):
+ return False
+
+ def test_gets_morph_from_local_repo(self):
+ morph = self.mf.get_morphology('reponame', 'sha1', 'foo.morph')
+ self.assertEqual('local-foo', morph['name'])
+
+ def test_gets_morph_from_remote_repo(self):
+ self.lrc.has_repo = self.doesnothaverepo
+ morph = self.mf.get_morphology('reponame', 'sha1', 'foo.morph')
+ self.assertEqual('remote-foo', morph['name'])
+
+ def test_autodetects_local_morphology(self):
+ self.lr.cat = self.nosuchfile
+ morph = self.mf.get_morphology('reponame', 'sha1',
+ 'assumed-local.morph')
+ self.assertEqual('assumed-local', morph['name'])
+
+ def test_autodetects_remote_morphology(self):
+ self.lrc.has_repo = self.doesnothaverepo
+ self.rrc.cat_file = self.nosuchfile
+ morph = self.mf.get_morphology('reponame', 'sha1',
+ 'assumed-remote.morph')
+ self.assertEqual('assumed-remote', morph['name'])
+
+ def test_raises_error_when_fails_detect(self):
+ self.lr.cat = self.nosuchfile
+ self.rrc.cat_file = self.nosuchfile
+ self.lr.list_files = lambda x: ['.']
+ self.rrc.list_files = lambda x: ['.']
+ self.assertRaises(AutodetectError, self.mf.get_morphology,
+ 'reponame', 'sha1', 'unreached.morph')