| OLD | NEW |
| (Empty) |
| 1 # Copyright 2015 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 | |
| 5 import os | |
| 6 | |
| 7 | |
| 8 class DuplicateDependencyFoundException(Exception): | |
| 9 """Two potentially matching files have been found that could satisfy this | |
| 10 dependency, so the right one cannot be selected automatically.""" | |
| 11 pass | |
| 12 | |
| 13 | |
| 14 class DependencyNotFoundException(Exception): | |
| 15 """The dependency hasn't been found on the local filesystem.""" | |
| 16 pass | |
| 17 | |
| 18 | |
| 19 class Dependency(object): | |
| 20 """Dependency represents an import request from one mojom file to another. | |
| 21 """ | |
| 22 def __init__(self, repository, importer, imported): | |
| 23 self._repository = repository | |
| 24 self._importer_filename = os.path.normpath(importer) | |
| 25 self._imported_filename = os.path.normpath(imported) | |
| 26 | |
| 27 def __str__(self): | |
| 28 return str(self.__dict__) | |
| 29 | |
| 30 def __eq__(self, other): | |
| 31 return self.__dict__ == other.__dict__ | |
| 32 | |
| 33 def get_importer(self): | |
| 34 """Returns the name and full path of the file doing the import.""" | |
| 35 return self._importer_filename | |
| 36 | |
| 37 def get_imported(self): | |
| 38 """Returns the imported file (filename and path).""" | |
| 39 return self._imported_filename | |
| 40 | |
| 41 def is_sdk_dep(self): | |
| 42 """Returns whether this dependency is from the mojo SDK.""" | |
| 43 return (self._imported_filename.startswith("mojo/public/") or | |
| 44 self._imported_filename.startswith("//mojo/public/")) | |
| 45 | |
| 46 def _is_in_external(self): | |
| 47 """Returns whether this dependency is under the external directory.""" | |
| 48 common = os.path.commonprefix((self._repository.get_external_directory(), | |
| 49 self._importer_filename)) | |
| 50 return common == self._repository.get_external_directory() | |
| 51 | |
| 52 def maybe_is_a_url(self): | |
| 53 """Returns whether this dependency may be pointing to a downloadable | |
| 54 ressource.""" | |
| 55 if self._is_in_external() and not self.is_sdk_dep(): | |
| 56 # External dependencies may refer to other dependencies by relative path, | |
| 57 # so they can always be URLs. | |
| 58 return True | |
| 59 | |
| 60 base, _ = self._imported_filename.split(os.path.sep, 1) | |
| 61 if not '.' in base: | |
| 62 # There is no dot separator in the first part of the path; it cannot be a | |
| 63 # URL. | |
| 64 return False | |
| 65 return True | |
| 66 | |
| 67 def generate_candidate_urls(self): | |
| 68 """Generates possible paths where to download this dependency. It is | |
| 69 expected that at most one of them should work.""" | |
| 70 candidates = [] | |
| 71 | |
| 72 base, _ = self._imported_filename.split(os.path.sep, 1) | |
| 73 if '.' in base and not base.startswith('.'): | |
| 74 # This import may be an absolute URL path (without scheme). | |
| 75 candidates.append(self._imported_filename) | |
| 76 | |
| 77 # External dependencies may refer to other dependencies by relative path. | |
| 78 if self._is_in_external(): | |
| 79 directory = os.path.relpath(os.path.dirname(self._importer_filename), | |
| 80 self._repository.get_external_directory()) | |
| 81 | |
| 82 # This is to handle the case where external dependencies use | |
| 83 # imports relative to a directory upper in the directory structure. As we | |
| 84 # don't know which directory, we need to go through all of them. | |
| 85 while len(directory) > 0: | |
| 86 candidates.append(os.path.join(directory, self._imported_filename)) | |
| 87 directory = os.path.dirname(directory) | |
| 88 return candidates | |
| 89 | |
| 90 def get_search_path_for_dependency(self): | |
| 91 """Return all possible search paths for this dependency.""" | |
| 92 | |
| 93 # Root directory and external directory are always included. | |
| 94 search_paths = set([self._repository.get_repo_root_directory(), | |
| 95 self._repository.get_external_directory()]) | |
| 96 # Local import paths | |
| 97 search_paths.add(os.path.dirname(self._importer_filename)) | |
| 98 | |
| 99 if self._is_in_external(): | |
| 100 directory = os.path.dirname(self._importer_filename) | |
| 101 | |
| 102 # This is to handle the case where external dependencies use | |
| 103 # imports relative to a directory upper in the directory structure. As we | |
| 104 # don't know which directory, we need to go through all of them. | |
| 105 while self._repository.get_external_directory() in directory: | |
| 106 search_paths.add(directory) | |
| 107 directory = os.path.dirname(directory) | |
| 108 return search_paths | |
| 109 | |
| 110 def is_sdk_dep(self): | |
| 111 """Returns whether this dependency is from the mojo SDK.""" | |
| 112 return self._imported_filename.startswith("mojo/public/") | |
| 113 | |
| 114 def _os_path_exists(self, path): | |
| 115 return os.path.exists(path) | |
| 116 | |
| 117 def get_target_and_import(self, extra_import_dirs): | |
| 118 """Returns a tuple (target, import_directory) for this dependency. | |
| 119 import_directory may be Null. extra_import_dirs lists directories that | |
| 120 should be searched for this dependency in addition to the ones directly | |
| 121 above the importing file. | |
| 122 """ | |
| 123 directory = os.path.dirname(self.get_importer()) | |
| 124 if self.is_sdk_dep(): | |
| 125 return (os.path.dirname(self.get_imported()), None) | |
| 126 | |
| 127 # We need to determine if it is a relative path or not | |
| 128 if self._os_path_exists(os.path.join(directory, self.get_imported())): | |
| 129 # This is a relative import path | |
| 130 dependency_path = os.path.normpath(os.path.join(directory, | |
| 131 self.get_imported())) | |
| 132 return (target_from_path(os.path.relpath(dependency_path, directory)), | |
| 133 None) | |
| 134 | |
| 135 if self._os_path_exists( | |
| 136 os.path.join(self._repository.get_external_directory(), | |
| 137 self.get_imported())): | |
| 138 # This is an "absolute" external dependency, specified by full path | |
| 139 # relative to the external directory. | |
| 140 return (target_from_path( | |
| 141 "//" + os.path.join(self._repository.get_external_suffix(), | |
| 142 self.get_imported())), None) | |
| 143 | |
| 144 # We assume that the dependency is specified relative to a directory | |
| 145 # above this one, so we search all of them for a correspondence. If we | |
| 146 # find one, we return an import directory. | |
| 147 result = None | |
| 148 for import_dir_candidate in (list(self.get_search_path_for_dependency()) | |
| 149 + extra_import_dirs): | |
| 150 dep_mojom_path = os.path.join( | |
| 151 import_dir_candidate, self.get_imported()) | |
| 152 if self._os_path_exists(dep_mojom_path): | |
| 153 if result != None: | |
| 154 raise DuplicateDependencyFoundException(self.get_imported()) | |
| 155 import_dir = os.path.relpath(import_dir_candidate, directory) | |
| 156 result = (target_from_path(os.path.relpath( | |
| 157 dep_mojom_path, directory)), import_dir) | |
| 158 if result == None: | |
| 159 raise DependencyNotFoundException(self.get_imported()) | |
| 160 return result | |
| 161 | |
| 162 | |
| 163 def group_target_name(directory): | |
| 164 """Returns the name of the group target for a given directory.""" | |
| 165 return os.path.basename(directory) | |
| 166 | |
| 167 def _target_dir_from_path(path): | |
| 168 directory, filename = os.path.split(path) | |
| 169 target, _ = os.path.splitext(filename) | |
| 170 if target == group_target_name(directory): | |
| 171 target = target + "_mojom" | |
| 172 return directory, target | |
| 173 | |
| 174 def target_name_from_path(path): | |
| 175 return _target_dir_from_path(path)[1] | |
| 176 | |
| 177 | |
| 178 def target_from_path(path): | |
| 179 return ':'.join(_target_dir_from_path(path)) | |
| 180 | |
| OLD | NEW |