summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2011-10-17 20:19:41 +0100
committerLars Wirzenius <liw@liw.fi>2011-10-17 20:19:41 +0100
commite55fece2655675ff4b151134fe5e0f222f4c8d70 (patch)
treedb08e3057188c59db340e2a1600bc0c77c462c52
parent6961416a28270d3483d7ffd73539294cdb874403 (diff)
downloadmorph-e55fece2655675ff4b151134fe5e0f222f4c8d70.tar.gz
Add functions for creating and unpacking binary chunks.
-rw-r--r--morphlib/__init__.py1
-rw-r--r--morphlib/bins.py49
-rw-r--r--morphlib/bins_tests.py78
3 files changed, 128 insertions, 0 deletions
diff --git a/morphlib/__init__.py b/morphlib/__init__.py
index 51651a9f..f4869eb1 100644
--- a/morphlib/__init__.py
+++ b/morphlib/__init__.py
@@ -20,6 +20,7 @@
__version__ = '0.0'
+import bins
import builder
import cachedir
import execute
diff --git a/morphlib/bins.py b/morphlib/bins.py
new file mode 100644
index 00000000..de946020
--- /dev/null
+++ b/morphlib/bins.py
@@ -0,0 +1,49 @@
+# Copyright (C) 2011 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.
+
+
+'''Functions for dealing with Baserock binaries.
+
+Binaries are chunks, strata, and system images.
+
+'''
+
+
+import logging
+import tarfile
+
+import morphlib
+
+
+def create_chunk(rootdir, chunk_filename):
+ '''Create a chunk from the contents of a directory.'''
+ logging.debug('Creating chunk file %s from %s' % (chunk_filename, rootdir))
+ tar = tarfile.open(name=chunk_filename, mode='w:gz')
+ tar.add(rootdir, arcname='.')
+ tar.close()
+
+
+def unpack_chunk(chunk_filename, dirname):
+ '''Unpack a chunk into a directory.
+
+ The directory must exist already.
+
+ '''
+
+ logging.debug('Unpacking chunk %s into %s' % (chunk_filename, dirname))
+ tar = tarfile.open(name=chunk_filename)
+ tar.extractall(path=dirname)
+ tar.close()
+
diff --git a/morphlib/bins_tests.py b/morphlib/bins_tests.py
new file mode 100644
index 00000000..b3c13a64
--- /dev/null
+++ b/morphlib/bins_tests.py
@@ -0,0 +1,78 @@
+# Copyright (C) 2011 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 shutil
+import tempfile
+import unittest
+
+import morphlib
+
+
+def recursive_lstat(root):
+ '''Return a list of (pathname, stat result) pairs for everything in root.
+
+ Pathnames are relative to root. Directories are recursed into.
+ The stat result is selective, not all fields are used.
+
+ '''
+
+ def remove_root(pathname):
+ assert pathname.startswith(root)
+ if pathname == root:
+ return '.'
+ else:
+ return pathname[len(root):]
+
+ def lstat(filename):
+ st = os.lstat(filename)
+ return (st.st_mode, st.st_size, int(st.st_mtime))
+
+ result = []
+
+ for dirname, subdirs, basenames in os.walk(root):
+ result.append((remove_root(dirname), lstat(dirname)))
+ for basename in sorted(basenames):
+ filename = os.path.join(dirname, basename)
+ result.append((remove_root(filename), lstat(filename)))
+ subdirs.sort()
+
+ return result
+
+
+class ChunkTests(unittest.TestCase):
+
+ def setUp(self):
+ self.tempdir = tempfile.mkdtemp()
+ self.instdir = os.path.join(self.tempdir, 'inst')
+ self.chunk_file = os.path.join(self.tempdir, 'chunk')
+ self.unpacked = os.path.join(self.tempdir, 'unpacked')
+
+ def tearDown(self):
+ shutil.rmtree(self.tempdir)
+
+ def populate_instdir(self):
+ os.mkdir(self.instdir)
+ os.mkdir(os.path.join(self.instdir, 'bin'))
+
+ def test_creates_and_unpacks_chunk_exactly(self):
+ self.populate_instdir()
+ morphlib.bins.create_chunk(self.instdir, self.chunk_file)
+ os.mkdir(self.unpacked)
+ morphlib.bins.unpack_chunk(self.chunk_file, self.unpacked)
+ self.assertEqual(recursive_lstat(self.instdir),
+ recursive_lstat(self.unpacked))
+