1# Copyright 2014 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.
4
5import os
6import stat
7
8from telemetry import decorators
9from telemetry.util import cloud_storage
10from telemetry.util import path
11
12
13def _GetBinPath(binary_name, platform_name):
14  # TODO(tonyg): Add another nesting level for architecture_name.
15  return os.path.join(path.GetTelemetryDir(), 'bin', platform_name, binary_name)
16
17
18def _IsInCloudStorage(binary_name, platform_name):
19  return os.path.exists(_GetBinPath(binary_name, platform_name) + '.sha1')
20
21
22@decorators.Cache
23def FindLocallyBuiltPath(binary_name):
24  """Finds the most recently built |binary_name|."""
25  command = None
26  command_mtime = 0
27  chrome_root = path.GetChromiumSrcDir()
28  required_mode = os.X_OK
29  if binary_name.endswith('.apk'):
30    required_mode = os.R_OK
31  for build_dir, build_type in path.GetBuildDirectories():
32    candidate = os.path.join(chrome_root, build_dir, build_type, binary_name)
33    if os.path.isfile(candidate) and os.access(candidate, required_mode):
34      candidate_mtime = os.stat(candidate).st_mtime
35      if candidate_mtime > command_mtime:
36        command = candidate
37        command_mtime = candidate_mtime
38  return command
39
40
41@decorators.Cache
42def FindPath(binary_name, platform_name):
43  """Returns the path to the given binary name, pulling from the cloud if
44  necessary."""
45  if platform_name == 'win':
46    binary_name += '.exe'
47  command = FindLocallyBuiltPath(binary_name)
48  if not command and _IsInCloudStorage(binary_name, platform_name):
49    cloud_storage.GetIfChanged(_GetBinPath(binary_name, platform_name))
50    command = _GetBinPath(binary_name, platform_name)
51
52    # Ensure the downloaded file is actually executable.
53    if command and os.path.exists(command):
54      os.chmod(command,
55               stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP)
56
57  # Return an absolute path consistently.
58  if command:
59    command = os.path.abspath(command)
60  return command
61