forked from platformio/platformio-core
		
	
		
			
	
	
		
			88 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			88 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| 
								 | 
							
								# Copyright (C) Ivan Kravets <me@ikravets.com>
							 | 
						||
| 
								 | 
							
								# See LICENSE for details.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								from os import chmod
							 | 
						||
| 
								 | 
							
								from os.path import join, splitext
							 | 
						||
| 
								 | 
							
								from tarfile import open as tarfile_open
							 | 
						||
| 
								 | 
							
								from time import mktime
							 | 
						||
| 
								 | 
							
								from zipfile import ZipFile
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								from click import progressbar
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								from platformio.exception import UnsupportedArchiveType
							 | 
						||
| 
								 | 
							
								from platformio.util import change_filemtime
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ArchiveBase(object):
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __init__(self, arhfileobj):
							 | 
						||
| 
								 | 
							
								        self._afo = arhfileobj
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def get_items(self):
							 | 
						||
| 
								 | 
							
								        raise NotImplementedError()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def extract_item(self, item, dest_dir):
							 | 
						||
| 
								 | 
							
								        self._afo.extract(item, dest_dir)
							 | 
						||
| 
								 | 
							
								        self.after_extract(item, dest_dir)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def after_extract(self, item, dest_dir):
							 | 
						||
| 
								 | 
							
								        pass
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class TARArchive(ArchiveBase):
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __init__(self, archpath):
							 | 
						||
| 
								 | 
							
								        ArchiveBase.__init__(self, tarfile_open(archpath))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def get_items(self):
							 | 
						||
| 
								 | 
							
								        return self._afo.getmembers()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class ZIPArchive(ArchiveBase):
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __init__(self, archpath):
							 | 
						||
| 
								 | 
							
								        ArchiveBase.__init__(self, ZipFile(archpath))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @staticmethod
							 | 
						||
| 
								 | 
							
								    def preserve_permissions(item, dest_dir):
							 | 
						||
| 
								 | 
							
								        attrs = item.external_attr >> 16L
							 | 
						||
| 
								 | 
							
								        if attrs:
							 | 
						||
| 
								 | 
							
								            chmod(join(dest_dir, item.filename), attrs)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    @staticmethod
							 | 
						||
| 
								 | 
							
								    def preserve_mtime(item, dest_dir):
							 | 
						||
| 
								 | 
							
								        change_filemtime(
							 | 
						||
| 
								 | 
							
								            join(dest_dir, item.filename),
							 | 
						||
| 
								 | 
							
								            mktime(list(item.date_time) + [0]*3)
							 | 
						||
| 
								 | 
							
								        )
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def get_items(self):
							 | 
						||
| 
								 | 
							
								        return self._afo.infolist()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def after_extract(self, item, dest_dir):
							 | 
						||
| 
								 | 
							
								        self.preserve_permissions(item, dest_dir)
							 | 
						||
| 
								 | 
							
								        self.preserve_mtime(item, dest_dir)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class FileUnpacker(object):
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def __init__(self, archpath, dest_dir="."):
							 | 
						||
| 
								 | 
							
								        self._archpath = archpath
							 | 
						||
| 
								 | 
							
								        self._dest_dir = dest_dir
							 | 
						||
| 
								 | 
							
								        self._unpacker = None
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        _, archext = splitext(archpath.lower())
							 | 
						||
| 
								 | 
							
								        if archext in (".gz", ".bz2"):
							 | 
						||
| 
								 | 
							
								            self._unpacker = TARArchive(archpath)
							 | 
						||
| 
								 | 
							
								        elif archext == ".zip":
							 | 
						||
| 
								 | 
							
								            self._unpacker = ZIPArchive(archpath)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if not self._unpacker:
							 | 
						||
| 
								 | 
							
								            raise UnsupportedArchiveType(archpath)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    def start(self):
							 | 
						||
| 
								 | 
							
								        with progressbar(self._unpacker.get_items(), label="Unpacking") as pb:
							 | 
						||
| 
								 | 
							
								            for item in pb:
							 | 
						||
| 
								 | 
							
								                self._unpacker.extract_item(item, self._dest_dir)
							 | 
						||
| 
								 | 
							
								        return True
							 |