Package daklib :: Module filewriter
[hide private]
[frames] | no frames]

Source Code for Module daklib.filewriter

  1  """ 
  2  Helper code for file writing with optional compression. 
  3   
  4  @contact: Debian FTPMaster <ftpmaster@debian.org> 
  5  @copyright: 2011 Torsten Werner <twerner@debian.org> 
  6  @license: GNU General Public License version 2 or later 
  7  """ 
  8   
  9  ################################################################################ 
 10   
 11  # This program is free software; you can redistribute it and/or modify 
 12  # it under the terms of the GNU General Public License as published by 
 13  # the Free Software Foundation; either version 2 of the License, or 
 14  # (at your option) any later version. 
 15   
 16  # This program is distributed in the hope that it will be useful, 
 17  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 18  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 19  # GNU General Public License for more details. 
 20   
 21  # You should have received a copy of the GNU General Public License 
 22  # along with this program; if not, write to the Free Software 
 23  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 24   
 25  ################################################################################ 
 26   
 27  import errno 
 28  import os 
 29  import os.path 
 30  import subprocess 
 31   
 32   
33 -class CompressionMethod:
34 - def __init__(self, keyword, extension, command):
35 self.keyword = keyword 36 self.extension = extension 37 self.command = command
38 39 40 _compression_methods = ( 41 CompressionMethod('bzip2', '.bz2', ['bzip2', '-9']), 42 CompressionMethod('gzip', '.gz', ['gzip', '-9cn', '--rsyncable', '--no-name']), 43 CompressionMethod('xz', '.xz', ['xz', '-c']), 44 CompressionMethod('zstd', '.zst', ['zstd', '--compress']), 45 # 'none' must be the last compression method as BaseFileWriter 46 # handling it will remove the input file for other compressions 47 CompressionMethod('none', '', None), 48 ) 49 50
51 -class BaseFileWriter:
52 ''' 53 Base class for compressed and uncompressed file writing. 54 ''' 55
56 - def __init__(self, template, **keywords):
57 ''' 58 The template argument is a string template like 59 "dists/%(suite)s/%(component)s/Contents-%(architecture)s.gz" that 60 should be relative to the archive's root directory. The keywords 61 include strings for suite, component, architecture and booleans 62 uncompressed, gzip, bzip2. 63 ''' 64 self.compression = keywords.get('compression', ['none']) 65 self.path = template % keywords
66
67 - def open(self):
68 ''' 69 Returns a file object for writing. 70 ''' 71 # create missing directories 72 try: 73 os.makedirs(os.path.dirname(self.path)) 74 except: 75 pass 76 self.file = open(self.path + '.new', 'w') 77 return self.file
78 79 # internal helper function
80 - def rename(self, filename):
81 tempfilename = filename + '.new' 82 os.chmod(tempfilename, 0o644) 83 os.rename(tempfilename, filename)
84 85 # internal helper function to compress output
86 - def compress(self, cmd, suffix, path):
87 in_filename = "{0}.new".format(path) 88 out_filename = "{0}{1}.new".format(path, suffix) 89 if cmd is not None: 90 with open(in_filename, 'r') as in_fh, open(out_filename, 'w') as out_fh: 91 subprocess.check_call(cmd, stdin=in_fh, stdout=out_fh, close_fds=True) 92 self.rename("{0}{1}".format(path, suffix))
93
94 - def close(self):
95 ''' 96 Closes the file object and does the compression and rename work. 97 ''' 98 self.file.close() 99 for method in _compression_methods: 100 if method.keyword in self.compression: 101 self.compress(method.command, method.extension, self.path) 102 else: 103 # Try removing the file that would be generated. 104 # It's not an error if it does not exist. 105 try: 106 os.unlink("{0}{1}".format(self.path, method.extension)) 107 except OSError as e: 108 if e.errno != errno.ENOENT: 109 raise 110 else: 111 os.unlink(self.path + '.new')
112 113
114 -class BinaryContentsFileWriter(BaseFileWriter):
115 - def __init__(self, **keywords):
116 ''' 117 The value of the keywords suite, component, and architecture are 118 strings. The value of component may be omitted if not applicable. 119 Output files are gzip compressed only. 120 ''' 121 flags = { 122 'compression': ['gzip'], 123 } 124 flags.update(keywords) 125 if flags['debtype'] == 'deb': 126 template = "%(archive)s/dists/%(suite)s/%(component)s/Contents-%(architecture)s" 127 else: # udeb 128 template = "%(archive)s/dists/%(suite)s/%(component)s/Contents-udeb-%(architecture)s" 129 BaseFileWriter.__init__(self, template, **flags)
130 131
132 -class SourceContentsFileWriter(BaseFileWriter):
133 - def __init__(self, **keywords):
134 ''' 135 The value of the keywords suite and component are strings. 136 Output files are gzip compressed only. 137 ''' 138 flags = { 139 'compression': ['gzip'], 140 } 141 flags.update(keywords) 142 template = "%(archive)s/dists/%(suite)s/%(component)s/Contents-source" 143 BaseFileWriter.__init__(self, template, **flags)
144 145
146 -class PackagesFileWriter(BaseFileWriter):
147 - def __init__(self, **keywords):
148 ''' 149 The value of the keywords suite, component, debtype and architecture 150 are strings. Output files are gzip compressed only. 151 ''' 152 flags = { 153 'compression': ['gzip', 'xz'], 154 } 155 flags.update(keywords) 156 if flags['debtype'] == 'deb': 157 template = "%(archive)s/dists/%(suite)s/%(component)s/binary-%(architecture)s/Packages" 158 else: # udeb 159 template = "%(archive)s/dists/%(suite)s/%(component)s/debian-installer/binary-%(architecture)s/Packages" 160 BaseFileWriter.__init__(self, template, **flags)
161 162
163 -class SourcesFileWriter(BaseFileWriter):
164 - def __init__(self, **keywords):
165 ''' 166 The value of the keywords suite and component are strings. Output 167 files are gzip compressed only. 168 ''' 169 flags = { 170 'compression': ['gzip', 'xz'], 171 } 172 flags.update(keywords) 173 template = "%(archive)s/dists/%(suite)s/%(component)s/source/Sources" 174 BaseFileWriter.__init__(self, template, **flags)
175 176
177 -class TranslationFileWriter(BaseFileWriter):
178 - def __init__(self, **keywords):
179 ''' 180 The value of the keywords suite, component and language are strings. 181 Output files are bzip2 compressed only. 182 ''' 183 flags = { 184 'compression': ['bzip2'], 185 'language': 'en', 186 } 187 flags.update(keywords) 188 template = "%(archive)s/dists/%(suite)s/%(component)s/i18n/Translation-%(language)s" 189 super(TranslationFileWriter, self).__init__(template, **flags)
190