summaryrefslogtreecommitdiff
path: root/morphlib
diff options
context:
space:
mode:
authorLars Wirzenius <lars.wirzenius@codethink.co.uk>2012-04-16 16:27:14 +0100
committerLars Wirzenius <lars.wirzenius@codethink.co.uk>2012-04-18 18:27:19 +0100
commit3e8797ff2318c8d19828d869f16daba297f423a1 (patch)
tree9846aa4a62190cbc797d1a37ecd3024367862519 /morphlib
parent86e53431fceb8433dd5290a91f6864770de5c0eb (diff)
downloadmorph-3e8797ff2318c8d19828d869f16daba297f423a1.tar.gz
Make StagingArea create build and install directories, run commands
Diffstat (limited to 'morphlib')
-rw-r--r--morphlib/stagingarea.py60
-rw-r--r--morphlib/stagingarea_tests.py32
2 files changed, 90 insertions, 2 deletions
diff --git a/morphlib/stagingarea.py b/morphlib/stagingarea.py
index 126d7d91..848dbc3a 100644
--- a/morphlib/stagingarea.py
+++ b/morphlib/stagingarea.py
@@ -14,9 +14,13 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+import logging
+import os
import shutil
import tarfile
+import morphlib
+
class StagingArea(object):
@@ -35,6 +39,46 @@ class StagingArea(object):
def __init__(self, dirname):
self.dirname = dirname
+ self._chroot = 'chroot' if os.getuid() == 0 else 'echo'
+
+ # Wrapper to be overridden by unit tests.
+ def _mkdir(self, dirname): # pragma: no cover
+ os.mkdir(dirname)
+
+ def _dir_for_source(self, source, suffix):
+ dirname = os.path.join(self.dirname,
+ '%s.%s' % (source.morphology['name'], suffix))
+ self._mkdir(dirname)
+ return dirname
+
+ def builddir(self, source):
+ '''Create a build directory for a given source project.
+
+ Return path to directory.
+
+ '''
+
+ return self._dir_for_source(source, 'build')
+
+ def destdir(self, source):
+ '''Create an installation target directory for a given source project.
+
+ This is meant to be used as $DESTDIR when installing chunks.
+ Return path to directory.
+
+ '''
+
+ return self._dir_for_source(source, 'inst')
+
+ def relative(self, filename):
+ '''Return a filename relative to the staging area.'''
+
+ dirname = self.dirname
+ if not dirname.endswith('/'):
+ dirname += '/'
+
+ assert filename.startswith(dirname)
+ return filename[len(dirname)-1:] # include leading slash
def install_artifact(self, handle):
'''Install a build artifact into the staging area.
@@ -44,7 +88,7 @@ class StagingArea(object):
'''
- tf = tarfile.TarFile(fileobj=handle)
+ tf = tarfile.open(fileobj=handle)
tf.extractall(path=self.dirname)
def remove(self):
@@ -58,3 +102,17 @@ class StagingArea(object):
shutil.rmtree(self.dirname)
+ def runcmd(self, argv, **kwargs): # pragma: no cover
+ '''Run a command in a chroot in the staging area.'''
+ ex = morphlib.execute.Execute('/', logging.debug)
+ cwd = kwargs.get('cwd') or '/'
+ if 'cwd' in kwargs:
+ cwd = kwargs['cwd']
+ del kwargs['cwd']
+ else:
+ cwd = '/'
+ real_argv = [self._chroot, self.dirname,
+ 'sh', '-c', 'cd "$1" && shift && eval "$@"', '--',
+ cwd] + argv
+ return ex.runv(real_argv, **kwargs)
+
diff --git a/morphlib/stagingarea_tests.py b/morphlib/stagingarea_tests.py
index c6b17610..96d00890 100644
--- a/morphlib/stagingarea_tests.py
+++ b/morphlib/stagingarea_tests.py
@@ -23,11 +23,20 @@ import unittest
import morphlib
+class FakeSource(object):
+
+ def __init__(self):
+ self.morphology = {
+ 'name': 'le-name',
+ }
+
+
class StagingAreaTests(unittest.TestCase):
def setUp(self):
self.tempdir = tempfile.mkdtemp()
self.staging = os.path.join(self.tempdir, 'staging')
+ self.created_dirs = []
self.sa = morphlib.stagingarea.StagingArea(self.staging)
def tearDown(self):
@@ -53,13 +62,34 @@ class StagingAreaTests(unittest.TestCase):
files.append(x[len(root):] or '/')
return files
+ def fake_mkdir(self, dirname):
+ self.created_dirs.append(dirname)
+
def test_remembers_specified_directory(self):
self.assertEqual(self.sa.dirname, self.staging)
def test_accepts_root_directory(self):
sa = morphlib.stagingarea.StagingArea('/')
self.assertEqual(sa.dirname, '/')
-
+
+ def test_creates_build_directory(self):
+ source = FakeSource()
+ self.sa._mkdir = self.fake_mkdir
+ dirname = self.sa.builddir(source)
+ self.assertEqual(self.created_dirs, [dirname])
+ self.assertTrue(dirname.startswith(self.staging))
+
+ def test_creates_install_directory(self):
+ source = FakeSource()
+ self.sa._mkdir = self.fake_mkdir
+ dirname = self.sa.destdir(source)
+ self.assertEqual(self.created_dirs, [dirname])
+ self.assertTrue(dirname.startswith(self.staging))
+
+ def test_makes_relative_name(self):
+ filename = os.path.join(self.staging, 'foobar')
+ self.assertEqual(self.sa.relative(filename), '/foobar')
+
def test_installs_artifact(self):
chunk_tar = self.create_chunk()
with open(chunk_tar, 'rb') as f: