Skip to content
image.py 42 KiB
Newer Older
Seblu's avatar
Seblu committed
        else:
            self.extract_file(dest, force=force)

    def extract_tar(self, dest, force=False, filelist=None):
        '''
        Extract a payload which is a tarball.
        This is used mainly to extract payload from a directory
        '''
        # check validity of dest
        if os.path.exists(dest):
            if not os.path.isdir(dest):
                raise Exception("Destination %s is not a directory" % dest)
            if not force and len(os.listdir(dest)) > 0:
                raise Exception("Directory %s is not empty (need force)" % dest)
        else:
Seblu's avatar
Seblu committed
            istools.mkdir(dest)
Seblu's avatar
Seblu committed
        # try to open payload file
            fo = PipeFile(self.path, progressbar=True)
        except Exception as e:
Seblu's avatar
Seblu committed
            raise Exception("Unable to open payload file %s" % self.path)
        # check if announced file size is good
        if fo.size is not None and self.size != fo.size:
            raise Exception("Invalid announced size on payload %s" % self.path)
Seblu's avatar
Seblu committed
        # try to open tarball on payload
Seblu's avatar
Seblu committed
            t = Tarball.open(fileobj=fo, mode="r|gz", ignore_zeros=True)
        except Exception as e:
Seblu's avatar
Seblu committed
            raise Exception("Invalid payload tarball: %s" % e)
        # filter on file to extact
Seblu's avatar
Seblu committed
        members = (None if filelist is None
                   else [ t.gettarinfo(name) for name in filelist ])
Seblu's avatar
Seblu committed
            t.extractall(dest, members)
Seblu's avatar
Seblu committed
        except Exception as e:
            raise Exception("Extracting failed: %s" % e)
Seblu's avatar
Seblu committed
        # closing fo
        t.close()
        fo.close()
        # checking download size
        if self.size != fo.read_size:
            raise Exception("Downloading payload %s failed: Invalid size" % self.name)
        if self.md5 != fo.md5:
            raise Exception("Downloading payload %s failed: Invalid MD5" % self.name)
Seblu's avatar
Seblu committed

    def extract_file(self, dest, force=False):
        '''
        Copy a payload directly to a file
        Check md5 on the fly
        '''
        # if dest is a directory try to create file inside
        if os.path.isdir(dest):
            dest = os.path.join(dest, self.name)
Seblu's avatar
Seblu committed
        # try to create leading directories
        elif not os.path.exists(os.path.dirname(dest)):
            istools.mkdir(os.path.dirname(dest))
Seblu's avatar
Seblu committed
        # check validity of dest
        if os.path.exists(dest):
            if os.path.isdir(dest):
                raise Exception("Destination %s is a directory" % dest)
Seblu's avatar
Seblu committed
            if not force:
                raise Exception("File %s already exists" % dest)
        # opening destination (must be local)
Seblu's avatar
Seblu committed
        try:
            f_dst = open(dest, "wb")
Seblu's avatar
Seblu committed
        except Exception as e:
            raise Exception("Unable to open destination file %s" % dest)
        # try to open payload file
        try:
            f_gsrc = PipeFile(self.path, "r", progressbar=True)
            f_src = gzipstream.GzipStream(stream=f_gsrc)
Seblu's avatar
Seblu committed
        except Exception as e:
            raise Exception("Unable to open payload file %s" % self.path)
        # check if announced file size is good
        if f_gsrc.size is not None and self.size != f_gsrc.size:
            raise Exception("Invalid announced size on payload %s" % self.path)
Seblu's avatar
Seblu committed
        # launch copy
        shutil.copyfileobj(f_src, f_dst)
Seblu's avatar
Seblu committed
        # closing fo
        f_dst.close()
        f_gsrc.close()
        f_src.close()
        # checking download size
        if self.size != f_gsrc.read_size:
            raise Exception("Downloading payload %s failed: Invalid size" % self.name)
        if self.md5 != f_gsrc.md5:
            raise Exception("Downloading payload %s failed: Invalid MD5" % self.name)
Seblu's avatar
Seblu committed
        # settings file orginal rights
        istools.chrights(dest, self.uid, self.gid, self.mode, self.mtime)
class Changelog(dict):
    '''
    Object representing a changelog in memory
    '''
    def __init__(self, data):
        self.verbatim = ""
        self.load(data)

    def load(self, data):
        '''
        Load a changelog file
        '''
        version = None
        lines = data.split("\n")
        for line in lines:
            # ignore empty lines
            if len(line.strip()) == 0:
                continue
            # ignore comments
            if line.lstrip().startswith("#"):
                continue
            # try to match a new version
            m = re.match("\[(\d+)\]", line.lstrip())
            if m is not None:
                version = int(m.group(1))
                self[version] = []
                continue
            # if line are out of a version => invalid format
            if version is None:
                raise Exception("Invalid format: Line outside version")
            # add line to version changelog
            self[version] += [line]
        # save original
        self.verbatim = data

    def show(self, version=None, verbose=False):
        '''
        Show changelog for a given version or all
        '''
        out('#light##yellow#Changelog:#reset#')
        # if no version take the hightest
        if version is None:
            version = max(self)
        # display asked version
        if version in self:
            self._show_version(version)
        # display all version in verbose mode
        if verbose:
            for ver in sorted((k for k in self if k < version), reverse=True):
                self._show_version(ver)

    def _show_version(self, version):
        '''
        Display a version content
        '''
        out('  #yellow#Version:#reset# %s' % version)
        for line in self[version]:
            out("    %s" % line)