56 lines
		
	
	
	
		
			1.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			56 lines
		
	
	
	
		
			1.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import tarfile
 | |
| 
 | |
| from cStringIO import StringIO
 | |
| 
 | |
| from util.registry.tarlayerformat import TarLayerFormat
 | |
| from util.registry.gzipwrap import GzipWrap
 | |
| 
 | |
| class TarfileAppender(TarLayerFormat):
 | |
|   """ Helper class which allows for appending entries to a gzipped-tarfile and doing so
 | |
|       in a streaming manner.
 | |
|   """
 | |
|   def __init__(self, base_tar_file, entries):
 | |
|     super(TarfileAppender, self).__init__(self._get_tar_iterator)
 | |
|     self.entries = entries
 | |
|     self.base_tar_file = base_tar_file
 | |
|     self.first_info = None
 | |
| 
 | |
|   def get_stream(self):
 | |
|     return GzipWrap(self.get_generator())
 | |
| 
 | |
|   def after_tar_layer(self, current_layer):
 | |
|     pass
 | |
| 
 | |
|   def check_tar_info(self, tar_info):
 | |
|     if not self.first_info:
 | |
|       self.first_info = tar_info
 | |
|     return True
 | |
| 
 | |
|   def _get_tar_iterator(self):
 | |
|     # Yield the contents of the base tar.
 | |
|     yield self.base_tar_file
 | |
| 
 | |
|     # Construct an in-memory tar containing the entries to append, and then yield
 | |
|     # its data.
 | |
|     def add_entry(arch, dir_path, contents=None):
 | |
|       info = tarfile.TarInfo(dir_path)
 | |
|       info.uid = self.first_info.uid
 | |
|       info.gid = self.first_info.gid
 | |
|       info.mode = self.first_info.mode
 | |
|       info.mtime = self.first_info.mtime
 | |
| 
 | |
|       info.type = tarfile.REGTYPE if contents else tarfile.DIRTYPE
 | |
| 
 | |
|       if contents:
 | |
|         info.size = len(contents)
 | |
| 
 | |
|       arch.addfile(info, fileobj=StringIO(contents) if contents else None)
 | |
| 
 | |
|     append_tarball = StringIO()
 | |
|     with tarfile.open(fileobj=append_tarball, mode='w') as updated_archive:
 | |
|       for entry in self.entries:
 | |
|         add_entry(updated_archive, entry, self.entries[entry])
 | |
| 
 | |
|     # To make tarfile happy.
 | |
|     append_tarball.seek(0)
 | |
|     yield append_tarball
 |