changeset 48:757aa3bf9594

* Simplify code for making snapshot archives. * The build slave now unpacks a snapshot after transmission.
author cmlenz
date Fri, 24 Jun 2005 17:13:07 +0000
parents 083e848088ee
children b4c51e32952b
files bitten/master.py bitten/slave.py bitten/util/archive.py
diffstat 3 files changed, 56 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/bitten/master.py
+++ b/bitten/master.py
@@ -65,8 +65,8 @@
                 # already been built
                 builds = Build.select(self.env, config.name, node.rev)
                 if not list(builds):
-                    snapshot = archive.make_archive(self.env, repos, node.path,
-                                                    node.rev, config.name)
+                    snapshot = archive.pack(self.env, repos, node.path,
+                                            node.rev, config.name)
                     logging.info('Created snapshot archive at %s' % snapshot)
                     self.snapshots[(config.name, str(node.rev))] = snapshot
 
--- a/bitten/slave.py
+++ b/bitten/slave.py
@@ -25,7 +25,7 @@
 import time
 
 from bitten import __version__ as VERSION
-from bitten.util import beep, xmlio
+from bitten.util import archive, beep, xmlio
 
 
 class Slave(beep.Initiator):
@@ -70,13 +70,25 @@
             archive_name = msg.get('Content-Disposition', 'snapshot.tar.gz')
             archive_path = os.path.join(workdir, archive_name)
             file(archive_path, 'wb').write(msg.get_payload())
-            logging.info('Received snapshot archive: %s', archive_path)
+            logging.debug('Received snapshot archive: %s', archive_path)
 
-            # TODO: Spawn the build process
+            # Unpack the archive
+            prefix = archive.unpack(archive_path, workdir)
+            path = os.path.join(workdir, prefix)
+            logging.info('Unpacked snapshot to %s' % path)
+
+            # Fix permissions
+            for root, dirs, files in os.walk(workdir, topdown=False):
+                for dirname in dirs:
+                    os.chmod(os.path.join(root, dirname), 0700)
+                for filename in files:
+                    os.chmod(os.path.join(root, filename), 0400)
 
             xml = xmlio.Element('ok')
             self.channel.send_rpy(msgno, beep.MIMEMessage(xml))
 
+            # TODO: Start the build process
+
         else:
             xml = xmlio.Element('error', code=500)['Sorry, what?']
             self.channel.send_err(msgno, beep.MIMEMessage(xml))
--- a/bitten/util/archive.py
+++ b/bitten/util/archive.py
@@ -18,14 +18,16 @@
 #
 # Author: Christopher Lenz <cmlenz@gmx.de>
 
+import logging
 import os.path
+import tarfile
 import time
+import zipfile
 
 _formats = {'gzip': ('.tar.gz', 'gz'), 'bzip2': ('.tar.bz2', 'bz2'),
             'zip': ('.zip', None)}
 
-def make_archive(env, repos=None, path=None, rev=None, prefix=None,
-                format='gzip'):
+def pack(env, repos=None, path=None, rev=None, prefix=None, format='gzip'):
     if repos is None:
         repos = env.get_repository()
     root = repos.get_node(path or '/', rev)
@@ -43,15 +45,9 @@
     filename = os.path.join(filedir, prefix + _formats[format][0])
 
     if format in ('bzip2', 'gzip'):
-        _make_tar_archive(env, root, filename, prefix, format)
+        archive = tarfile.open(filename, 'w:' + _formats[format][1])
     else:
-        _make_zip_archive(env, root, filename, prefix)
-
-    return filename
-
-def _make_tar_archive(env, root, filename, prefix, format):
-    import tarfile
-    tar = tarfile.open(filename, 'w:' + _formats[format][1])
+        archive = zipfile.ZipFile(filename, 'w', zipfile.ZIP_DEFLATED)
 
     def _add_entry(node):
         name = node.path[len(root.path):]
@@ -60,33 +56,46 @@
         if node.isdir:
             for entry in node.get_entries():
                 _add_entry(entry)
-        else:
+        elif format in ('bzip2', 'gzip'):
             info = tarfile.TarInfo(os.path.join(prefix, name))
             info.type = tarfile.REGTYPE
             info.mtime = node.last_modified
             info.size = node.content_length
-            tar.addfile(info, node.get_content())
-    _add_entry(root)
-
-    tar.close()
-
-def _make_zip_archive(env, root, filename, prefix):
-    import zipfile
-    zip = zipfile.ZipFile(filename, 'w', zipfile.ZIP_DEFLATED)
-
-    def _add_entry(node):
-        name = node.path[len(root.path):]
-        if name.startswith('/'):
-            name = name[1:]
-        if node.isdir:
-            for entry in node.get_entries():
-                _add_entry(entry)
-        else:
+            archive.addfile(info, node.get_content())
+        else: # ZIP format
             info = zipfile.ZipInfo(os.path.join(prefix, name))
             info.compress_type = zipfile.ZIP_DEFLATED
             info.date_time = time.gmtime(node.last_modified)[:6]
             info.file_size = node.content_length
-            zip.writestr(info, node.get_content().read())
+            archive.writestr(info, node.get_content().read())
     _add_entry(root)
 
-    zip.close()
+    archive.close()
+
+    return filename
+
+def unpack(filename, dest_path, format=None):
+    if not format:
+        for name, (extension, compression) in _formats.items():
+            if filename.endswith(extension):
+                format = name
+                break
+        if not format:
+            raise Exception, 'Unkown archive extension: %s' \
+                             % os.path.splitext(filename)[1]
+
+    names = []
+    if format in ('bzip2', 'gzip'):
+        tar = tarfile.open(filename)
+        for tarinfo in tar:
+            names.append(tarinfo.name)
+            tar.extract(tarinfo, dest_path)
+    elif format == 'zip':
+        zip = zipfile.ZipFile(filename, 'r')
+        for name in zip.namelist():
+            names.append(name)
+            if name.endswith('/'):
+                os.makedirs(os.path.join(path, name))
+            else:
+                file(os.path.join(path, name), 'wb').write(zip.read(name))
+    return os.path.commonprefix(names)
Copyright (C) 2012-2017 Edgewall Software