X-Git-Url: https://git.decadent.org.uk/gitweb/?p=dak.git;a=blobdiff_plain;f=daklib%2Ffilewriter.py;h=6f5da4f0d8314c5aeecc0c5a216b7b37f9b6db23;hp=8907fa6d96fa39f7c8e2d7163f3c20e4f361bd2e;hb=17c5cab4eb8d5181ec7a81267a4e2e6b43c0fc65;hpb=e8ef4a21ceff20319cde5002cb562ae05d7622c9 diff --git a/daklib/filewriter.py b/daklib/filewriter.py old mode 100755 new mode 100644 index 8907fa6d..6f5da4f0 --- a/daklib/filewriter.py +++ b/daklib/filewriter.py @@ -27,10 +27,26 @@ Helper code for file writing with optional compression. from daklib.config import Config -from subprocess import check_call +from daklib.daksubprocess import check_call +import errno import os, os.path +class CompressionMethod(object): + def __init__(self, keyword, extension, command): + self.keyword = keyword + self.extension = extension + self.command = command + +_compression_methods = ( + CompressionMethod('bzip2', '.bz2', ['bzip2', '-9']), + CompressionMethod('gzip', '.gz', ['gzip', '-9cn', '--rsyncable']), + CompressionMethod('xz', '.xz', ['xz', '-c']), + # 'none' must be the last compression method as BaseFileWriter + # handling it will remove the input file for other compressions + CompressionMethod('none', '', None), +) + class BaseFileWriter(object): ''' Base class for compressed and uncompressed file writing. @@ -43,12 +59,8 @@ class BaseFileWriter(object): include strings for suite, component, architecture and booleans uncompressed, gzip, bzip2. ''' - self.uncompressed = keywords.get('uncompressed', True) - self.gzip = keywords.get('gzip', False) - self.bzip2 = keywords.get('bzip2', False) - root_dir = Config()['Dir::Root'] - relative_dir = template % keywords - self.path = os.path.join(root_dir, relative_dir) + self.compression = keywords.get('compression', ['none']) + self.path = template % keywords def open(self): ''' @@ -65,23 +77,34 @@ class BaseFileWriter(object): # internal helper function def rename(self, filename): tempfilename = filename + '.new' - os.chmod(tempfilename, 0664) + os.chmod(tempfilename, 0o644) os.rename(tempfilename, filename) + # internal helper function to compress output + def compress(self, cmd, suffix, path): + in_filename = "{0}.new".format(path) + out_filename = "{0}{1}.new".format(path, suffix) + if cmd is not None: + with open(in_filename, 'r') as in_fh, open(out_filename, 'w') as out_fh: + check_call(cmd, stdin=in_fh, stdout=out_fh) + self.rename("{0}{1}".format(path, suffix)) + def close(self): ''' Closes the file object and does the compression and rename work. ''' self.file.close() - if self.gzip: - check_call('gzip --rsyncable <%s.new >%s.gz.new' % (self.path, self.path), - shell = True) - self.rename('%s.gz' % self.path) - if self.bzip2: - check_call('bzip2 <%s.new >%s.bz2.new' % (self.path, self.path), shell = True) - self.rename('%s.bz2' % self.path) - if self.uncompressed: - self.rename(self.path) + for method in _compression_methods: + if method.keyword in self.compression: + self.compress(method.command, method.extension, self.path) + else: + # Try removing the file that would be generated. + # It's not an error if it does not exist. + try: + os.unlink("{0}{1}".format(self.path, method.extension)) + except OSError as e: + if e.errno != errno.ENOENT: + raise else: os.unlink(self.path + '.new') @@ -93,15 +116,13 @@ class BinaryContentsFileWriter(BaseFileWriter): Output files are gzip compressed only. ''' flags = { - 'uncompressed': False, - 'gzip': True, - 'bzip2': False + 'compression': ['gzip'], } flags.update(keywords) if flags['debtype'] == 'deb': - template = "dists/%(suite)s/%(component)s/Contents-%(architecture)s" + template = "%(archive)s/dists/%(suite)s/%(component)s/Contents-%(architecture)s" else: # udeb - template = "dists/%(suite)s/%(component)s/Contents-udeb-%(architecture)s" + template = "%(archive)s/dists/%(suite)s/%(component)s/Contents-udeb-%(architecture)s" BaseFileWriter.__init__(self, template, **flags) class SourceContentsFileWriter(BaseFileWriter): @@ -111,12 +132,10 @@ class SourceContentsFileWriter(BaseFileWriter): Output files are gzip compressed only. ''' flags = { - 'uncompressed': False, - 'gzip': True, - 'bzip2': False + 'compression': ['gzip'], } flags.update(keywords) - template = "dists/%(suite)s/%(component)s/Contents-source" + template = "%(archive)s/dists/%(suite)s/%(component)s/Contents-source" BaseFileWriter.__init__(self, template, **flags) class PackagesFileWriter(BaseFileWriter): @@ -126,15 +145,13 @@ class PackagesFileWriter(BaseFileWriter): are strings. Output files are gzip compressed only. ''' flags = { - 'uncompressed': False, - 'gzip': True, - 'bzip2': True + 'compression': ['gzip', 'xz'], } flags.update(keywords) if flags['debtype'] == 'deb': - template = "dists/%(suite)s/%(component)s/binary-%(architecture)s/Packages" + template = "%(archive)s/dists/%(suite)s/%(component)s/binary-%(architecture)s/Packages" else: # udeb - template = "dists/%(suite)s/%(component)s/debian-installer/binary-%(architecture)s/Packages" + template = "%(archive)s/dists/%(suite)s/%(component)s/debian-installer/binary-%(architecture)s/Packages" BaseFileWriter.__init__(self, template, **flags) class SourcesFileWriter(BaseFileWriter): @@ -144,10 +161,22 @@ class SourcesFileWriter(BaseFileWriter): files are gzip compressed only. ''' flags = { - 'uncompressed': False, - 'gzip': True, - 'bzip2': True + 'compression': ['gzip', 'xz'], } flags.update(keywords) - template = "dists/%(suite)s/%(component)s/source/Sources" + template = "%(archive)s/dists/%(suite)s/%(component)s/source/Sources" BaseFileWriter.__init__(self, template, **flags) + +class TranslationFileWriter(BaseFileWriter): + def __init__(self, **keywords): + ''' + The value of the keywords suite, component and language are strings. + Output files are bzip2 compressed only. + ''' + flags = { + 'compression': ['bzip2'], + 'language': 'en', + } + flags.update(keywords) + template = "%(archive)s/dists/%(suite)s/%(component)s/i18n/Translation-%(language)s" + super(TranslationFileWriter, self).__init__(template, **flags)