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 |