add rewritten moudle archive to handle archiving and compressing
authorGui Chen <gui.chen@intel.com>
Wed, 23 Apr 2014 08:33:06 +0000 (04:33 -0400)
committeradmin <yuhuan.yang@samsung.com>
Wed, 3 Feb 2016 16:24:14 +0000 (00:24 +0800)
Change-Id: I9fd94ca3b3d3460ecb2af618baa329f04a6a3bfb
Signed-off-by: Gui Chen <gui.chen@intel.com>
mic/archive.py [new file with mode: 0644]

diff --git a/mic/archive.py b/mic/archive.py
new file mode 100644 (file)
index 0000000..c92aaa6
--- /dev/null
@@ -0,0 +1,331 @@
+#
+# Copyright (c) 2013 Intel Inc.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; version 2 of the License
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc., 59
+# Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# Following messages should be disabled in pylint
+#  * Used * or ** magic (W0142)
+#  * Unused variable (W0612)
+#  * Used builtin function (W0141)
+#  * Invalid name for type (C0103)
+#  * Popen has no '%s' member (E1101)
+# pylint: disable=W0142, W0612, W0141, C0103, E1101
+
+""" Compression and Archiving
+
+Utility functions for creating archive files (tarballs, zip files, etc)
+and compressing files (gzip, bzip2, lzop, etc)
+"""
+
+import os
+import shutil
+import tempfile
+import subprocess
+
+__all__ = [
+            "get_compress_formats",
+            "compress",
+            "decompress",
+            "get_archive_formats",
+            "get_archive_suffixes",
+            "make_archive",
+            "extract_archive",
+            "compressing",
+            "packing",
+          ]
+
+def which(binary, path=None):
+    """ Find 'binary' in the directories listed in 'path'
+
+    @binary: the executable file to find
+    @path: the suposed path to search for, use $PATH if None
+    @retval: the absolute path if found, otherwise None
+    """
+    if path is None:
+        path = os.environ["PATH"]
+    for apath in path.split(os.pathsep):
+        fpath = os.path.join(apath, binary)
+        if os.path.isfile(fpath) and os.access(fpath, os.X_OK):
+            return fpath
+    return None
+
+def _call_external(cmdln_or_args):
+    """ Wapper for subprocess calls.
+
+    @cmdln_or_args: command line to be joined before execution.
+    @retval: a tuple (returncode, outdata, errdata).
+    """
+    if isinstance(cmdln_or_args, list):
+        shell = False
+    else:
+        shell = True
+
+    proc = subprocess.Popen(cmdln_or_args, shell=shell,
+                            stdout=subprocess.PIPE,
+                            stderr=subprocess.STDOUT)
+    (outdata, errdata) = proc.communicate()
+
+    return (proc.returncode, outdata, errdata)
+
+def _do_gzip(input_name, compression=True):
+    """ Compress/decompress the file with 'gzip' utility.
+
+    @input_name: the file name to compress/decompress
+    @compress: True for compressing, False for decompressing
+    @retval: the path of the compressed/decompressed file
+    """
+    if which("pigz") is not None:
+        compressor = "pigz"
+    else:
+        compressor = "gzip"
+
+    if compression:
+        cmdln = [compressor, "-f", input_name]
+    else:
+        cmdln = [compressor, "-d", "-f", input_name]
+
+    _call_external(cmdln)
+
+    if compression:
+        output_name = input_name + ".gz"
+    else:
+        # suppose that file name is suffixed with ".gz"
+        output_name = os.path.splitext(input_name)[0]
+
+    return output_name
+
+def _do_bzip2(input_name, compression=True):
+    """ Compress/decompress the file with 'bzip2' utility.
+
+    @input_name: the file name to compress/decompress
+    @compress: True for compressing, False for decompressing
+    @retval: the path of the compressed/decompressed file
+    """
+    if which("pbzip2") is not None:
+        compressor = "pbzip2"
+    else:
+        compressor = "bzip2"
+
+    if compression:
+        cmdln = [compressor, "-f", input_name]
+    else:
+        cmdln = [compressor, "-d", "-f", input_name]
+
+    _call_external(cmdln)
+
+    if compression:
+        output_name = input_name + ".bz2"
+    else:
+        # suppose that file name is suffixed with ".bz2"
+        output_name = os.path.splitext(input_name)[0]
+
+    return output_name
+
+def _do_lzop(input_name, compression=True):
+    """ Compress/decompress the file with 'lzop' utility.
+
+    @input_name: the file name to compress/decompress
+    @compress: True for compressing, False for decompressing
+    @retval: the path of the compressed/decompressed file
+    """
+    compressor = "lzop"
+
+    if compression:
+        cmdln = [compressor, "-f", "-U", input_name]
+    else:
+        cmdln = [compressor, "-d", "-f", "-U", input_name]
+
+    _call_external(cmdln)
+
+    if compression:
+        output_name = input_name + ".lzo"
+    else:
+        # suppose that file name is suffixed with ".lzo"
+        output_name = os.path.splitext(input_name)[0]
+
+    return output_name
+
+_COMPRESS_FORMATS = {
+    "gz" :  _do_gzip,
+    "bz2":  _do_bzip2,
+    "lzo":  _do_lzop,
+}
+
+def get_compress_formats():
+    """ Get the list of the supported compression formats
+
+    """
+    pass
+
+def compress(file_path, compress_format):
+    """ Compress a given file
+
+    @file_path: the path of the file to compress
+    @compress_format: the compression format
+    @retval: the path of the compressed file
+    """
+    try:
+        func = _COMPRESS_FORMATS[compress_format]
+    except KeyError:
+        raise ValueError, "unknown compress format '%s'" % compress_format
+    return func(file_path, True)
+
+def decompress(file_path, decompress_format=None):
+    """ Decompess a give file
+
+    @file_path: the path of the file to decompress
+    @decompress_format: the format for decompression, None for auto detection
+    @retval: the path of the decompressed file
+    """
+    try:
+        func = _COMPRESS_FORMATS[decompress_format]
+    except KeyError:
+        raise ValueError, "unknown decompress format '%s'" % decompress_format
+    return func(file_path, False)
+
+
+def _make_tarball(archive_name, target_name, compressor=None):
+    """ Create a tarball from all the files under 'target_name' or itself.
+
+    @archive_name: the name of the archived file
+    @target_name: the directory or the file name to archive
+    @compressor: callback function to compress the tarball
+    @retval: indicate the compressing result
+    """
+    archive_dir = os.path.dirname(archive_name)
+
+    if not os.path.exists(archive_dir):
+        os.makedirs(archive_dir)
+
+    import tarfile
+
+    tarball_name = tempfile.mktemp(suffix=".tar", dir=archive_dir)
+    tar = tarfile.open(tarball_name, 'w')
+
+    if os.path.isdir(target_name):
+        for child in os.listdir(target_name):
+            tar.add(os.path.join(target_name, child), child)
+    else:
+        tar.add(target_name, os.path.basename(target_name))
+
+    tar.close()
+
+    if compressor:
+        tarball_name = compressor(tarball_name, True)
+
+    shutil.move(tarball_name, archive_name)
+
+    return os.path.exists(archive_name)
+
+def _make_zipfile(archive_name, target_name):
+    """ Create a zip file from all the files under 'target_name' or itself.
+
+    @archive_name: the name of the archived file
+    @target_name: the directory or the file name to archive
+    @retval: indicate the archiving result
+    """
+    archive_dir = os.path.dirname(archive_name)
+
+    if not os.path.exists(archive_dir):
+        os.makedirs(archive_dir)
+
+    import zipfile
+
+    arv = zipfile.ZipFile(archive_name, 'w', compression=zipfile.ZIP_DEFLATED)
+
+    if os.path.isdir(target_name):
+        for dirpath, dirname, filenames in os.walk(target_name):
+            for filename in filenames:
+                filepath = os.path.normpath(os.path.join(dirpath, filename))
+                arcname = os.path.relpath(filepath, target_name)
+                if os.path.isfile(filepath):
+                    arv.write(filepath, arcname)
+    else:
+        arv.write(target_name, os.path.basename(target_name))
+
+    arv.close()
+
+    return os.path.exists(archive_name)
+
+_ARCHIVE_SUFFIXES = {
+    "zip"   : [".zip"],
+    "tar"   : [".tar"],
+    "lzotar": [".tzo", ".tar.lzo"],
+    "gztar" : [".tgz", ".taz", ".tar.gz"],
+    "bztar" : [".tbz", ".tbz2", ".tar.bz", ".tar.bz2"],
+}
+
+_ARCHIVE_FORMATS = {
+    "zip"   : ( _make_zipfile, {} ),
+    "tar"   : ( _make_tarball, {"compressor" : None} ),
+    "lzotar": ( _make_tarball, {"compressor" : _do_lzop} ),
+    "gztar" : ( _make_tarball, {"compressor" : _do_gzip} ),
+    "bztar" : ( _make_tarball, {"compressor" : _do_bzip2} ),
+}
+
+def get_archive_formats():
+    """ Get the list of the supported formats for archiving
+
+    @retval: a list contained tuples represented as (name, suffix)
+    """
+    formats = []
+
+    for name in _ARCHIVE_FORMATS.keys():
+        suffix = _ARCHIVE_SUFFIXES.get(name, None)
+        if (suffix):
+            formats.append((name, suffix))
+
+    return formats
+
+def get_archive_suffixes():
+    """ Get the list of the support suffixes
+
+    @retval: a list contained all suffixes
+    """
+    suffixes = []
+    for name in _ARCHIVE_FORMATS.keys():
+        suffix = _ARCHIVE_SUFFIXES.get(name, None)
+        if (suffix):
+            suffixes.extend(suffix)
+
+    return suffixes
+
+def make_archive(archive_name, target_name):
+    """ Create an archive file (eg. tar or zip).
+
+    @archive_name: the name of the archived file
+    @target_name: the directory or the file to archive
+    """
+    for aformat, suffixs in _ARCHIVE_SUFFIXES.iteritems():
+        if filter(archive_name.endswith, suffixs):
+            archive_format = aformat
+            break
+    else:
+        raise ValueError, "unknown archive suffix '%s'" % archive_name
+
+    try:
+        func, kwargs = _ARCHIVE_FORMATS[archive_format]
+    except KeyError:
+        raise ValueError, "unknown archive format '%s'" % archive_format
+
+    return func(archive_name, target_name, **kwargs)
+
+def extract_archive():
+    """ Extract the given file
+    """
+    pass
+
+packing = make_archive
+compressing = compress
+