# HG changeset patch # User cmlenz # Date 1119633187 0 # Node ID 757aa3bf9594d5c204ed36f71fedbaa5abc9466b # Parent 083e848088ee1dfb0f4b14f54b7bf7d93a4f8776 * Simplify code for making snapshot archives. * The build slave now unpacks a snapshot after transmission. diff --git a/bitten/master.py b/bitten/master.py --- 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 diff --git a/bitten/slave.py b/bitten/slave.py --- 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)) diff --git a/bitten/util/archive.py b/bitten/util/archive.py --- a/bitten/util/archive.py +++ b/bitten/util/archive.py @@ -18,14 +18,16 @@ # # Author: Christopher Lenz +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)