src/tools/shellutil.py
changeset 0 ca70ae20a155
equal deleted inserted replaced
-1:000000000000 0:ca70ae20a155
       
     1 # Copyright (c) 2005-2009 Nokia Corporation
       
     2 #
       
     3 # Licensed under the Apache License, Version 2.0 (the "License");
       
     4 # you may not use this file except in compliance with the License.
       
     5 # You may obtain a copy of the License at
       
     6 #
       
     7 #     http://www.apache.org/licenses/LICENSE-2.0
       
     8 #
       
     9 # Unless required by applicable law or agreed to in writing, software
       
    10 # distributed under the License is distributed on an "AS IS" BASIS,
       
    11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    12 # See the License for the specific language governing permissions and
       
    13 # limitations under the License.
       
    14 
       
    15 import sys
       
    16 import stat
       
    17 import re
       
    18 import shutil
       
    19 import thread
       
    20 import os.path
       
    21 from os.path import normpath
       
    22 from subprocess import *
       
    23 from threading import Thread
       
    24 import zipfile
       
    25 import tarfile
       
    26 
       
    27 
       
    28 class CommandFailedException(Exception):
       
    29     pass
       
    30 
       
    31 
       
    32 class BuildFailedException(Exception):
       
    33     pass
       
    34 
       
    35 
       
    36 class ConfigureError(Exception):
       
    37     pass
       
    38 
       
    39 
       
    40 def log(str):
       
    41     """Prints the log in PyS60 format.
       
    42     This must be used in place of "print" to get uniformity in logs
       
    43     """
       
    44     print "PyS60: " + str
       
    45 
       
    46 
       
    47 def run_shell_command(cmd, stdin='', mixed_stderr=0, verbose=0,
       
    48                       exception_on_error=1):
       
    49     """Internal method to execute shell commands"""
       
    50     stdout_buf = []
       
    51     if mixed_stderr:
       
    52         stderr_buf = stdout_buf
       
    53     else:
       
    54         stderr_buf = []
       
    55     if verbose:
       
    56         print '- ', cmd
       
    57     p = Popen(cmd,
       
    58               stdin=PIPE,
       
    59               stdout=PIPE,
       
    60               stderr=PIPE,
       
    61               shell=True)
       
    62     p.stdin.write(stdin)
       
    63     p.stdin.close()
       
    64 
       
    65     def handle_stderr():
       
    66         while 1:
       
    67             line = p.stderr.readline()
       
    68             if len(line) == 0:
       
    69                 break
       
    70             if verbose:
       
    71                 print " ** " + line
       
    72             stderr_buf.append(line)
       
    73     stderr_thread = Thread(target=handle_stderr)
       
    74     stderr_thread.start()
       
    75     while 1:
       
    76         line = p.stdout.readline()
       
    77         if len(line) == 0:
       
    78             break
       
    79         if verbose:
       
    80             print " -- " + line,
       
    81         stdout_buf.append(line)
       
    82     retcode = p.wait()
       
    83     stderr_thread.join()
       
    84     if retcode != 0 and exception_on_error:
       
    85         raise CommandFailedException('Command "%s" failed with code "%s"'
       
    86                                        % (cmd, retcode))
       
    87     if mixed_stderr:
       
    88         return {'stdout': ''.join(stdout_buf),
       
    89                 'return_code': retcode}
       
    90     else:
       
    91         return {'stdout': ''.join(stdout_buf),
       
    92                 'stderr': ''.join(stderr_buf),
       
    93                 'return_code': retcode}
       
    94 
       
    95 
       
    96 def run_cmd(cmd, verbose=1, exception_on_error=1):
       
    97     """Method to execute shell commands.
       
    98     Set verbose to 0 to stop logging messages.
       
    99     """
       
   100     log('Executing command :<%s>' % cmd)
       
   101     run_shell_command(cmd, mixed_stderr=1, verbose=verbose,
       
   102                       exception_on_error=exception_on_error)
       
   103 
       
   104 
       
   105 def rename_file(fromfile, tofile):
       
   106     if not os.path.exists(fromfile):
       
   107         log("shellutil.py: Error: %s File does not exists" % (fromfile))
       
   108         return
       
   109     fromfile = normpath(fromfile)
       
   110     tofile = normpath(tofile)
       
   111     delete_file(tofile)
       
   112     log("shellutil.py: Renaming: %s -> %s" % (fromfile, tofile))
       
   113     os.rename(fromfile, tofile)
       
   114 
       
   115 
       
   116 def copy_file(fromfile, tofile):
       
   117     """Method to copy files"""
       
   118     fromfile = normpath(fromfile)
       
   119     tofile = normpath(tofile)
       
   120     if fromfile == tofile:
       
   121         log("shellutil.py: No need to copy, source and target are the same:" +
       
   122              "%s -> %s" % (fromfile, tofile))
       
   123     else:
       
   124         log("shellutil.py: Copying: %s -> %s" % (fromfile, tofile))
       
   125         targetdir = os.path.dirname(os.path.abspath(tofile))
       
   126         if not os.path.exists(targetdir):
       
   127             os.makedirs(targetdir)
       
   128         content = open(fromfile, 'rb').read()
       
   129         open(tofile, 'wb').write(content)
       
   130 
       
   131 
       
   132 def delete_file(filename):
       
   133     """Method to delete a particular file if that exists
       
   134     If access is denied will give an error.
       
   135     """
       
   136     if os.path.exists(filename):
       
   137         log("Deleting: %s" % filename)
       
   138         os.remove(filename)
       
   139 
       
   140 
       
   141 def deltree_if_exists(dirname):
       
   142     """Delete an entire directory."""
       
   143     if os.path.exists(dirname):
       
   144         shutil.rmtree(dirname)
       
   145 
       
   146 
       
   147 def files_matching_regex(topdir, regex):
       
   148     """Find the matching files in a directory
       
   149     Return an empty list if file not found
       
   150     """
       
   151     files = []
       
   152     compiled_regex = re.compile(regex, re.I)
       
   153     for path, dirnames, filenames in os.walk(topdir):
       
   154         for x in filenames:
       
   155             pathname = os.path.join(path, x)
       
   156             if compiled_regex.match(pathname):
       
   157                 files.append(pathname)
       
   158     return files
       
   159 
       
   160 
       
   161 def setcapas(output, capas, compression_type='', verbose=0):
       
   162     """Method to apply new capability set & compression type on dlls or exes
       
   163     This is used as post linker
       
   164     """
       
   165     compression_opt = ''
       
   166     if compression_type != '':
       
   167         compression_opt = '-compressionmethod ' + compression_type
       
   168     run_cmd('elftran -capability "%s" %s %s' \
       
   169                                            % (capas, compression_opt, output))
       
   170     if verbose:
       
   171         run_cmd('elftran -dump s %s' % output, exception_on_error=0)
       
   172 
       
   173 
       
   174 def create_archive_from_directory(archive_name, topdir, archive_dir='',
       
   175                                   archive_type='zip'):
       
   176     """Creates a compressed archive from the contents of the given directory.
       
   177        The archive types supported are tar.gz and zip.
       
   178     """
       
   179     archive_name = os.path.normpath(archive_name)
       
   180     topdir = os.path.normpath(topdir)
       
   181     print "Creating archive %s from directory %s..." % (archive_name, topdir)
       
   182 
       
   183     if archive_type == 'tar.gz':
       
   184         archive = tarfile.open(archive_name, 'w:gz')
       
   185     else:
       
   186         archive = zipfile.ZipFile(archive_name, 'w')
       
   187     abs_topdir = os.path.abspath(topdir)
       
   188     for root, dirs, files in os.walk(topdir):
       
   189         if '.svn' in dirs:
       
   190             dirs.remove('.svn')
       
   191         abs_root = os.path.abspath(root)
       
   192         # Remove the common part from the directory name,
       
   193         # leaving just the relative part
       
   194         relative_path = abs_root[len(abs_topdir) + 1:]
       
   195         for name in files:
       
   196             absolute_filename = os.path.join(abs_root, name)
       
   197             archive_filename = os.path.join(relative_path, name)
       
   198             archive_filename = os.path.join(archive_dir, archive_filename)
       
   199             print "Adding %s as %s" % (absolute_filename, archive_filename)
       
   200             if archive_type == 'tar.gz':
       
   201                 archive.add(absolute_filename, archive_filename)
       
   202             else:
       
   203                 archive.write(absolute_filename, archive_filename,
       
   204                                                           zipfile.ZIP_DEFLATED)
       
   205     archive.close()
       
   206     print "Created: ", archive_name
       
   207 
       
   208 
       
   209 class tee(object):
       
   210     """Class that implements stdout redirection to both file and screen"""
       
   211 
       
   212     def __init__(self, name, mode):
       
   213         self.file = open(name, mode)
       
   214         self.stdout = sys.stdout
       
   215         sys.stdout = self
       
   216 
       
   217     def close(self):
       
   218         if self.stdout is not None:
       
   219             sys.stdout = self.stdout
       
   220             self.stdout = None
       
   221         if self.file is not None:
       
   222             self.file.close()
       
   223             self.file = None
       
   224 
       
   225     def write(self, data):
       
   226         data = data.replace("\r", "")
       
   227         self.file.write(data)
       
   228         self.stdout.write(data)
       
   229 
       
   230     def flush(self):
       
   231         self.file.flush()
       
   232         self.stdout.flush()
       
   233 
       
   234     def __del__(self):
       
   235         self.close()