1 # Copyright 2013 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
15 def MakeDirectory(dir_path):
22 def DeleteDirectory(dir_path):
23 if os.path.exists(dir_path):
24 shutil.rmtree(dir_path)
28 MakeDirectory(os.path.dirname(path))
33 def FindInDirectory(directory, filename_filter):
35 for root, _dirnames, filenames in os.walk(directory):
36 matched_files = fnmatch.filter(filenames, filename_filter)
37 files.extend((os.path.join(root, f) for f in matched_files))
41 def FindInDirectories(directories, filename_filter):
43 for directory in directories:
44 all_files.extend(FindInDirectory(directory, filename_filter))
48 def ParseGypList(gyp_string):
49 # The ninja generator doesn't support $ in strings, so use ## to
51 # TODO(cjhopman): Remove when
52 # https://code.google.com/p/gyp/issues/detail?id=327
54 gyp_string = gyp_string.replace('##', '$')
55 return shlex.split(gyp_string)
58 def CheckOptions(options, parser, required=None):
61 for option_name in required:
62 if not getattr(options, option_name):
63 parser.error('--%s is required' % option_name.replace('_', '-'))
65 def WriteJson(obj, path, only_if_changed=False):
67 if os.path.exists(path):
68 with open(path, 'r') as oldfile:
69 old_dump = oldfile.read()
71 new_dump = json.dumps(obj)
73 if not only_if_changed or old_dump != new_dump:
74 with open(path, 'w') as outfile:
75 outfile.write(new_dump)
78 with open(path, 'r') as jsonfile:
79 return json.load(jsonfile)
82 class CalledProcessError(Exception):
83 """This exception is raised when the process run by CheckOutput
84 exits with a non-zero exit code."""
86 def __init__(self, cwd, args, output):
87 super(CalledProcessError, self).__init__()
93 # A user should be able to simply copy and paste the command that failed
95 copyable_command = '( cd {}; {} )'.format(os.path.abspath(self.cwd),
96 ' '.join(map(pipes.quote, self.args)))
97 return 'Command failed: {}\n{}'.format(copyable_command, self.output)
100 # This can be used in most cases like subprocess.check_output(). The output,
101 # particularly when the command fails, better highlights the command's failure.
102 # If the command fails, raises a build_utils.CalledProcessError.
103 def CheckOutput(args, cwd=None, print_stdout=False, print_stderr=True,
104 fail_func=lambda returncode, stderr: returncode != 0):
108 child = subprocess.Popen(args,
109 stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd)
110 stdout, stderr = child.communicate()
112 if fail_func(child.returncode, stderr):
113 raise CalledProcessError(cwd, args, stdout + stderr)
116 sys.stdout.write(stdout)
118 sys.stderr.write(stderr)
123 def GetModifiedTime(path):
124 # For a symlink, the modified time should be the greater of the link's
125 # modified time and the modified time of the target.
126 return max(os.lstat(path).st_mtime, os.stat(path).st_mtime)
129 def IsTimeStale(output, inputs):
130 if not os.path.exists(output):
133 output_time = GetModifiedTime(output)
135 if GetModifiedTime(i) > output_time:
141 device_state = CheckOutput(['adb', 'get-state'])
142 return device_state.strip() == 'device'
145 def PrintWarning(message):
146 print 'WARNING: ' + message
149 def PrintBigWarning(message):
151 PrintWarning(message)