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) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import fnmatch 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import json 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import os 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import pipes 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import shlex 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import shutil 11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import subprocess 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import sys 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)import traceback 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def MakeDirectory(dir_path): 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) try: 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) os.makedirs(dir_path) 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) except OSError: 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) pass 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def DeleteDirectory(dir_path): 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if os.path.exists(dir_path): 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) shutil.rmtree(dir_path) 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def Touch(path): 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) MakeDirectory(os.path.dirname(path)) 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) with open(path, 'a'): 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) os.utime(path, None) 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def FindInDirectory(directory, filter): 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) files = [] 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for root, dirnames, filenames in os.walk(directory): 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) matched_files = fnmatch.filter(filenames, filter) 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) files.extend((os.path.join(root, f) for f in matched_files)) 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return files 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def FindInDirectories(directories, filter): 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) all_files = [] 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for directory in directories: 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) all_files.extend(FindInDirectory(directory, filter)) 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return all_files 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def ParseGypList(gyp_string): 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # The ninja generator doesn't support $ in strings, so use ## to 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # represent $. 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # TODO(cjhopman): Remove when 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # https://code.google.com/p/gyp/issues/detail?id=327 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # is addressed. 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gyp_string = gyp_string.replace('##', '$') 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return shlex.split(gyp_string) 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def CheckOptions(options, parser, required=[]): 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for option_name in required: 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if not getattr(options, option_name): 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) parser.error('--%s is required' % option_name.replace('_', '-')) 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def WriteJson(obj, path, only_if_changed=False): 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) old_dump = None 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if os.path.exists(path): 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) with open(path, 'r') as oldfile: 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) old_dump = oldfile.read() 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) new_dump = json.dumps(obj) 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if not only_if_changed or old_dump != new_dump: 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) with open(path, 'w') as outfile: 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) outfile.write(new_dump) 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def ReadJson(path): 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) with open(path, 'r') as jsonfile: 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return json.load(jsonfile) 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class CalledProcessError(Exception): 82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) """This exception is raised when the process run by CheckOutput 83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) exits with a non-zero exit code.""" 84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) def __init__(self, cwd, args, output): 86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) self.cwd = cwd 87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) self.args = args 88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) self.output = output 89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) def __str__(self): 91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) # A user should be able to simply copy and paste the command that failed 92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) # into their shell. 93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) copyable_command = '( cd {}; {} )'.format(os.path.abspath(self.cwd), 94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ' '.join(map(pipes.quote, self.args))) 95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 'Command failed: {}\n{}'.format(copyable_command, self.output) 96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)# This can be used in most cases like subprocess.check_output(). The output, 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)# particularly when the command fails, better highlights the command's failure. 100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)# If the command fails, raises a build_utils.CalledProcessError. 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)def CheckOutput(args, cwd=None, print_stdout=False, print_stderr=True, 102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) fail_if_stderr=False): 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if not cwd: 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) cwd = os.getcwd() 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) child = subprocess.Popen(args, 107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd) 108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) stdout, stderr = child.communicate() 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if child.returncode or (stderr and fail_if_stderr): 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) raise CalledProcessError(cwd, args, stdout + stderr) 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if print_stdout: 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sys.stdout.write(stdout) 115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if print_stderr: 116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sys.stderr.write(stderr) 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return stdout 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def GetModifiedTime(path): 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # For a symlink, the modified time should be the greater of the link's 123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) # modified time and the modified time of the target. 124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return max(os.lstat(path).st_mtime, os.stat(path).st_mtime) 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)def IsTimeStale(output, inputs): 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if not os.path.exists(output): 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return True 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) output_time = GetModifiedTime(output) 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for input in inputs: 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if GetModifiedTime(input) > output_time: 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return True 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return False 136b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 137b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 138b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)def IsDeviceReady(): 139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) device_state = CheckOutput(['adb', 'get-state']) 140b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return device_state.strip() == 'device' 141b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 142b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 143b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)def PrintWarning(message): 144b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) print 'WARNING: ' + message 145b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 146b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 147b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)def PrintBigWarning(message): 148b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) print '***** ' * 8 149b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) PrintWarning(message) 150b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) print '***** ' * 8 151