1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)import contextlib 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import fnmatch 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import json 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import os 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import pipes 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import shlex 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import shutil 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import subprocess 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import sys 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)import tempfile 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)import zipfile 16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)CHROMIUM_SRC = os.path.join(os.path.dirname(__file__), 18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) os.pardir, os.pardir, os.pardir, os.pardir) 19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)COLORAMA_ROOT = os.path.join(CHROMIUM_SRC, 20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'third_party', 'colorama', 'src') 21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)@contextlib.contextmanager 24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)def TempDir(): 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) dirname = tempfile.mkdtemp() 26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) try: 27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) yield dirname 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) finally: 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) shutil.rmtree(dirname) 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def MakeDirectory(dir_path): 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) try: 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) os.makedirs(dir_path) 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) except OSError: 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pass 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def DeleteDirectory(dir_path): 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if os.path.exists(dir_path): 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) shutil.rmtree(dir_path) 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def Touch(path): 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MakeDirectory(os.path.dirname(path)) 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) with open(path, 'a'): 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) os.utime(path, None) 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)def FindInDirectory(directory, filename_filter): 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) files = [] 5223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) for root, _dirnames, filenames in os.walk(directory): 5323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) matched_files = fnmatch.filter(filenames, filename_filter) 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) files.extend((os.path.join(root, f) for f in matched_files)) 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return files 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)def FindInDirectories(directories, filename_filter): 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) all_files = [] 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for directory in directories: 6123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) all_files.extend(FindInDirectory(directory, filename_filter)) 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return all_files 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def ParseGypList(gyp_string): 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # The ninja generator doesn't support $ in strings, so use ## to 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # represent $. 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # TODO(cjhopman): Remove when 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # https://code.google.com/p/gyp/issues/detail?id=327 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # is addressed. 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gyp_string = gyp_string.replace('##', '$') 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return shlex.split(gyp_string) 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)def CheckOptions(options, parser, required=None): 7623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if not required: 7723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for option_name in required: 79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if getattr(options, option_name) is None: 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) parser.error('--%s is required' % option_name.replace('_', '-')) 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def WriteJson(obj, path, only_if_changed=False): 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) old_dump = None 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if os.path.exists(path): 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) with open(path, 'r') as oldfile: 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) old_dump = oldfile.read() 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) new_dump = json.dumps(obj, sort_keys=True, indent=2, separators=(',', ': ')) 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if not only_if_changed or old_dump != new_dump: 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) with open(path, 'w') as outfile: 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) outfile.write(new_dump) 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def ReadJson(path): 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) with open(path, 'r') as jsonfile: 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return json.load(jsonfile) 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class CalledProcessError(Exception): 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) """This exception is raised when the process run by CheckOutput 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) exits with a non-zero exit code.""" 102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) def __init__(self, cwd, args, output): 10423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) super(CalledProcessError, self).__init__() 105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) self.cwd = cwd 106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) self.args = args 107a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) self.output = output 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) def __str__(self): 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) # A user should be able to simply copy and paste the command that failed 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) # into their shell. 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) copyable_command = '( cd {}; {} )'.format(os.path.abspath(self.cwd), 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ' '.join(map(pipes.quote, self.args))) 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 'Command failed: {}\n{}'.format(copyable_command, self.output) 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)# This can be used in most cases like subprocess.check_output(). The output, 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# particularly when the command fails, better highlights the command's failure. 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)# If the command fails, raises a build_utils.CalledProcessError. 120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)def CheckOutput(args, cwd=None, 121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) print_stdout=False, print_stderr=True, 122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) stdout_filter=None, 123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) stderr_filter=None, 1240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch fail_func=lambda returncode, stderr: returncode != 0): 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if not cwd: 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cwd = os.getcwd() 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) child = subprocess.Popen(args, 129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd) 130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) stdout, stderr = child.communicate() 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if stdout_filter is not None: 133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) stdout = stdout_filter(stdout) 134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if stderr_filter is not None: 136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) stderr = stderr_filter(stderr) 137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if fail_func(child.returncode, stderr): 139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) raise CalledProcessError(cwd, args, stdout + stderr) 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if print_stdout: 142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sys.stdout.write(stdout) 143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if print_stderr: 144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sys.stderr.write(stderr) 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return stdout 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def GetModifiedTime(path): 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # For a symlink, the modified time should be the greater of the link's 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # modified time and the modified time of the target. 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return max(os.lstat(path).st_mtime, os.stat(path).st_mtime) 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def IsTimeStale(output, inputs): 156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if not os.path.exists(output): 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return True 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) output_time = GetModifiedTime(output) 16023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) for i in inputs: 16123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if GetModifiedTime(i) > output_time: 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return True 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return False 164b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 165b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 166b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)def IsDeviceReady(): 167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) device_state = CheckOutput(['adb', 'get-state']) 168b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return device_state.strip() == 'device' 169b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 170b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)def CheckZipPath(name): 172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if os.path.normpath(name) != name: 173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) raise Exception('Non-canonical zip path: %s' % name) 174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if os.path.isabs(name): 175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) raise Exception('Absolute zip path: %s' % name) 176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)def ExtractAll(zip_path, path=None, no_clobber=True): 179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if path is None: 180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) path = os.getcwd() 181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) elif not os.path.exists(path): 182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MakeDirectory(path) 183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) with zipfile.ZipFile(zip_path) as z: 185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for name in z.namelist(): 186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CheckZipPath(name) 187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if no_clobber: 188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) output_path = os.path.join(path, name) 189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if os.path.exists(output_path): 190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) raise Exception( 191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 'Path already exists from zip: %s %s %s' 192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) % (zip_path, name, output_path)) 193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) z.extractall(path=path) 195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)def DoZip(inputs, output, base_dir): 198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) with zipfile.ZipFile(output, 'w') as outfile: 199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) for f in inputs: 200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CheckZipPath(os.path.relpath(f, base_dir)) 201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) outfile.write(f, os.path.relpath(f, base_dir)) 202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 204b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)def PrintWarning(message): 205b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) print 'WARNING: ' + message 206b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 207b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 208b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)def PrintBigWarning(message): 209b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) print '***** ' * 8 210b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) PrintWarning(message) 211b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) print '***** ' * 8 212