summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJannis Pohlmann <jannis.pohlmann@codethink.co.uk>2012-04-11 16:58:28 +0100
committerJannis Pohlmann <jannis.pohlmann@codethink.co.uk>2012-04-11 17:06:48 +0100
commitd7a7fc31242ba4ff88252bb0d6eca62ca327f8f0 (patch)
tree46268a3041dc2af15b9e53a5be9cd3105472686f
parentffc01a3572a8f74d2d6664e6e4d4d9c514a14b97 (diff)
downloadmorph-d7a7fc31242ba4ff88252bb0d6eca62ca327f8f0.tar.gz
Add Artifact and LocalArtifactCache classes.
An Artifact represents a thing that morph has built. An example would be eglibc-runtime which morph may have built from the eglibc chunk morphology. Another example would be a ready-to-use system image. The LocalArtifactCache allows to store build artifacts in a local directory. Users of this class can ask it whether it has a certain artifact. They can also optain an I/O handle to read the artifact data from. In addition to just abstracting the way artifacts are stored, LocalArtifactCache also allows to store and retrieve metadata for (a) artifacts and (b) sources (the latter requires a cache key to be provided to the LocalArtifactCache).
-rw-r--r--morphlib/__init__.py2
-rw-r--r--morphlib/artifact.py22
-rw-r--r--morphlib/artifact_tests.py57
-rw-r--r--morphlib/localartifactcache.py79
-rw-r--r--morphlib/localartifactcache_tests.py135
5 files changed, 295 insertions, 0 deletions
diff --git a/morphlib/__init__.py b/morphlib/__init__.py
index 6b0e955b..6c74082c 100644
--- a/morphlib/__init__.py
+++ b/morphlib/__init__.py
@@ -17,6 +17,7 @@
'''Baserock library.'''
+import artifact
import bins
import blobs
import buildcontroller
@@ -30,6 +31,7 @@ import cachedrepo
import execute
import fsutils
import git
+import localartifactcache
import localrepocache
import morph2
import morphology
diff --git a/morphlib/artifact.py b/morphlib/artifact.py
new file mode 100644
index 00000000..db105ebd
--- /dev/null
+++ b/morphlib/artifact.py
@@ -0,0 +1,22 @@
+# 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.
+
+
+class Artifact(object):
+
+ def __init__(self, source, name, cache_key):
+ self.source = source
+ self.name = name
+ self.cache_key = cache_key
diff --git a/morphlib/artifact_tests.py b/morphlib/artifact_tests.py
new file mode 100644
index 00000000..49f8e17f
--- /dev/null
+++ b/morphlib/artifact_tests.py
@@ -0,0 +1,57 @@
+# 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
+
+import morphlib
+
+
+class ArtifactTests(unittest.TestCase):
+
+ def setUp(self):
+ morph = morphlib.morph2.Morphology(
+ '''
+ {
+ "chunk": "chunk",
+ "kind": "chunk",
+ "artifacts": {
+ "chunk-runtime": [
+ "usr/bin",
+ "usr/sbin",
+ "usr/lib",
+ "usr/libexec"
+ ],
+ "chunk-devel": [
+ "usr/include"
+ ]
+ }
+ }
+ ''')
+ self.source = morphlib.source.Source(
+ 'repo', 'ref', 'sha1', morph, 'chunk.morph')
+ self.cache_key = 'cachekey'
+ self.artifact_name = 'chunk-runtime'
+ self.artifact = morphlib.artifact.Artifact(
+ self.source, self.artifact_name, self.cache_key)
+
+ def test_constructor_sets_source(self):
+ self.assertEqual(self.artifact.source, self.source)
+
+ def test_constructor_sets_name(self):
+ self.assertEqual(self.artifact.name, self.artifact_name)
+
+ def test_constructor_sets_cache_key(self):
+ self.assertEqual(self.artifact.cache_key, self.cache_key)
diff --git a/morphlib/localartifactcache.py b/morphlib/localartifactcache.py
new file mode 100644
index 00000000..52b5772c
--- /dev/null
+++ b/morphlib/localartifactcache.py
@@ -0,0 +1,79 @@
+# 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 os
+
+import morphlib
+
+
+class LocalArtifactCache(object):
+
+ def __init__(self, cachedir):
+ self.cachedir = cachedir
+
+ def put(self, artifact):
+ filename = self._artifact_filename(artifact)
+ return morphlib.savefile.SaveFile(filename, mode='w')
+
+ def put_artifact_metadata(self, artifact, name):
+ filename = self._artifact_metadata_filename(artifact, name)
+ return morphlib.savefile.SaveFile(filename, mode='w')
+
+ def put_source_metadata(self, source, cachekey, name):
+ filename = self._source_metadata_filename(source, cachekey, name)
+ return morphlib.savefile.SaveFile(filename, mode='w')
+
+ def has(self, artifact):
+ filename = self._artifact_filename(artifact)
+ return os.path.exists(filename)
+
+ def has_artifact_metadata(self, artifact, name):
+ filename = self._artifact_metadata_filename(artifact, name)
+ return os.path.exists(filename)
+
+ def has_source_metadata(self, source, cachekey, name):
+ filename = self._source_metadata_filename(source, cachekey, name)
+ return os.path.exists(filename)
+
+ def get(self, artifact):
+ filename = self._artifact_filename(artifact)
+ return open(filename)
+
+ def get_artifact_metadata(self, artifact, name):
+ filename = self._artifact_metadata_filename(artifact, name)
+ return open(filename)
+
+ def get_source_metadata(self, source, cachekey, name):
+ filename = self._source_metadata_filename(source, cachekey, name)
+ return open(filename)
+
+ def _artifact_basename(self, artifact):
+ return '%s.%s.%s' % (artifact.cache_key,
+ artifact.source.morphology['kind'],
+ artifact.name)
+
+ def _artifact_filename(self, artifact):
+ basename = self._artifact_basename(artifact)
+ return os.path.join(self.cachedir, basename)
+
+ def _artifact_metadata_filename(self, artifact, name):
+ basename = '%s.%s' % (self._artifact_basename(artifact), name)
+ return os.path.join(self.cachedir, basename)
+
+
+ def _source_metadata_filename(self, source, cachekey, name):
+ basename = '%s.%s' % (cachekey, name)
+ return os.path.join(self.cachedir, basename)
diff --git a/morphlib/localartifactcache_tests.py b/morphlib/localartifactcache_tests.py
new file mode 100644
index 00000000..41eb3d0b
--- /dev/null
+++ b/morphlib/localartifactcache_tests.py
@@ -0,0 +1,135 @@
+# 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
+
+import morphlib
+
+
+class LocalArtifactCacheTests(unittest.TestCase):
+
+ def setUp(self):
+ self.tempdir = morphlib.tempdir.Tempdir()
+
+ morph = morphlib.morph2.Morphology(
+ '''
+ {
+ "chunk": "chunk",
+ "kind": "chunk",
+ "artifacts": {
+ "chunk-runtime": [
+ "usr/bin",
+ "usr/sbin",
+ "usr/lib",
+ "usr/libexec"
+ ],
+ "chunk-devel": [
+ "usr/include"
+ ]
+ }
+ }
+ ''')
+ self.source = morphlib.source.Source(
+ 'repo', 'ref', 'sha1', morph, 'chunk.morph')
+ self.runtime_artifact = morphlib.artifact.Artifact(
+ self.source, 'chunk-runtime', 'cachekey')
+ self.devel_artifact = morphlib.artifact.Artifact(
+ self.source, 'chunk-devel', 'cachekey')
+
+ def tearDown(self):
+ self.tempdir.remove()
+
+ def test_put_artifacts_and_check_whether_the_cache_has_them(self):
+ cache = morphlib.localartifactcache.LocalArtifactCache(
+ self.tempdir.dirname)
+
+ handle = cache.put(self.runtime_artifact)
+ handle.write('runtime')
+ handle.close()
+
+ self.assertTrue(cache.has(self.runtime_artifact))
+
+ handle = cache.put(self.devel_artifact)
+ handle.write('devel')
+ handle.close()
+
+ self.assertTrue(cache.has(self.runtime_artifact))
+ self.assertTrue(cache.has(self.devel_artifact))
+
+ def test_put_artifacts_and_get_them_afterwards(self):
+ cache = morphlib.localartifactcache.LocalArtifactCache(
+ self.tempdir.dirname)
+
+ handle = cache.put(self.runtime_artifact)
+ handle.write('runtime')
+ handle.close()
+
+ handle = cache.get(self.runtime_artifact)
+ stored_data = handle.read()
+ handle.close()
+
+ self.assertEqual(stored_data, 'runtime')
+
+ handle = cache.put(self.devel_artifact)
+ handle.write('devel')
+ handle.close()
+
+ handle = cache.get(self.runtime_artifact)
+ stored_data = handle.read()
+ handle.close()
+
+ self.assertEqual(stored_data, 'runtime')
+
+ handle = cache.get(self.devel_artifact)
+ stored_data = handle.read()
+ handle.close()
+
+ self.assertEqual(stored_data, 'devel')
+
+ def test_put_check_and_get_artifact_metadata(self):
+ cache = morphlib.localartifactcache.LocalArtifactCache(
+ self.tempdir.dirname)
+
+ handle = cache.put_artifact_metadata(self.runtime_artifact, 'log')
+ handle.write('log line 1\nlog line 2\n')
+ handle.close()
+
+ self.assertTrue(cache.has_artifact_metadata(
+ self.runtime_artifact, 'log'))
+
+ handle = cache.get_artifact_metadata(self.runtime_artifact, 'log')
+ stored_metadata = handle.read()
+ handle.close()
+
+ self.assertEqual(stored_metadata, 'log line 1\nlog line 2\n')
+
+ def test_put_check_and_get_source_metadata(self):
+ cache = morphlib.localartifactcache.LocalArtifactCache(
+ self.tempdir.dirname)
+
+ handle = cache.put_source_metadata(self.source, 'mycachekey', 'log')
+ handle.write('source log line 1\nsource log line 2\n')
+ handle.close()
+
+ self.assertTrue(cache.has_source_metadata(
+ self.source, 'mycachekey', 'log'))
+
+ handle = cache.get_source_metadata(self.source, 'mycachekey', 'log')
+ stored_metadata = handle.read()
+ handle.close()
+
+ self.assertEqual(stored_metadata,
+ 'source log line 1\nsource log line 2\n')