1# Copyright 2016 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 re
7
8from pylib import constants
9
10
11_EXCLUSIONS = [
12    re.compile(r'.*OWNERS'),  # Should never be included.
13    re.compile(r'.*\.crx'),  # Chrome extension zip files.
14    re.compile(os.path.join('.*',
15                            r'\.git.*')),  # Any '.git*' directories/files.
16    re.compile(r'.*\.so'),  # Libraries packed into .apk.
17    re.compile(r'.*Mojo.*manifest\.json'),  # Some source_set()s pull these in.
18    re.compile(r'.*\.py'),  # Some test_support targets include python deps.
19    re.compile(r'.*\.apk'),  # Should be installed separately.
20    re.compile(r'.*lib.java/.*'),  # Never need java intermediates.
21
22    # Test filter files:
23    re.compile(r'.*/testing/buildbot/filters/.*'),
24
25    # Chrome external extensions config file.
26    re.compile(r'.*external_extensions\.json'),
27
28    # Exists just to test the compile, not to be run.
29    re.compile(r'.*jni_generator_tests'),
30
31    # v8's blobs and icu data get packaged into APKs.
32    re.compile(r'.*snapshot_blob.*\.bin'),
33    re.compile(r'.*icudtl.bin'),
34
35    # Scripts that are needed by swarming, but not on devices:
36    re.compile(r'.*llvm-symbolizer'),
37    re.compile(r'.*md5sum_bin'),
38    re.compile(os.path.join('.*', 'development', 'scripts', 'stack')),
39
40    # Required for java deobfuscation on the host:
41    re.compile(r'.*build/android/stacktrace/.*'),
42    re.compile(r'.*third_party/jdk/.*'),
43    re.compile(r'.*third_party/proguard/.*'),
44
45    # Build artifacts:
46    re.compile(r'.*\.stamp'),
47    re.compile(r'.*.pak\.info'),
48    re.compile(r'.*\.incremental\.json'),
49]
50
51
52def _FilterDataDeps(abs_host_files):
53  exclusions = _EXCLUSIONS + [
54      re.compile(os.path.join(constants.GetOutDirectory(), 'bin'))
55  ]
56  return [p for p in abs_host_files if not any(r.match(p) for r in exclusions)]
57
58
59def DevicePathComponentsFor(host_path, output_directory):
60  """Returns the device path components for a given host path.
61
62  This returns the device path as a list of joinable path components,
63  with None as the first element to indicate that the path should be
64  rooted at $EXTERNAL_STORAGE.
65
66  e.g., given
67
68    '$RUNTIME_DEPS_ROOT_DIR/foo/bar/baz.txt'
69
70  this would return
71
72    [None, 'foo', 'bar', 'baz.txt']
73
74  This handles a couple classes of paths differently than it otherwise would:
75    - All .pak files get mapped to top-level paks/
76    - All other dependencies get mapped to the top level directory
77        - If a file is not in the output directory then it's relative path to
78          the output directory will start with .. strings, so we remove those
79          and then the path gets mapped to the top-level directory
80        - If a file is in the output directory then the relative path to the
81          output directory gets mapped to the top-level directory
82
83  e.g. given
84
85    '$RUNTIME_DEPS_ROOT_DIR/out/Release/icu_fake_dir/icudtl.dat'
86
87  this would return
88
89    [None, 'icu_fake_dir', 'icudtl.dat']
90
91  Args:
92    host_path: The absolute path to the host file.
93  Returns:
94    A list of device path components.
95  """
96  if (host_path.startswith(output_directory) and
97      os.path.splitext(host_path)[1] == '.pak'):
98    return [None, 'paks', os.path.basename(host_path)]
99
100  rel_host_path = os.path.relpath(host_path, output_directory)
101
102  device_path_components = [None]
103  p = rel_host_path
104  while p:
105    p, d = os.path.split(p)
106    # The relative path from the output directory to a file under the runtime
107    # deps root directory may start with multiple .. strings, so they need to
108    # be skipped.
109    if d and d != os.pardir:
110      device_path_components.insert(1, d)
111  return device_path_components
112
113
114def GetDataDependencies(runtime_deps_path):
115  """Returns a list of device data dependencies.
116
117  Args:
118    runtime_deps_path: A str path to the .runtime_deps file.
119  Returns:
120    A list of (host_path, device_path) tuples.
121  """
122  if not runtime_deps_path:
123    return []
124
125  with open(runtime_deps_path, 'r') as runtime_deps_file:
126    rel_host_files = [l.strip() for l in runtime_deps_file if l]
127
128  output_directory = constants.GetOutDirectory()
129  abs_host_files = [
130      os.path.abspath(os.path.join(output_directory, r))
131      for r in rel_host_files]
132  filtered_abs_host_files = _FilterDataDeps(abs_host_files)
133  # TODO(crbug.com/752610): Filter out host executables, and investigate
134  # whether other files could be filtered as well.
135  return [(f, DevicePathComponentsFor(f, output_directory))
136          for f in filtered_abs_host_files]
137