| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Meta checkout manager supporting both Subversion and GIT. | 6 """Meta checkout manager supporting both Subversion and GIT. |
| 7 | 7 |
| 8 Files | 8 Files |
| 9 .gclient : Current client configuration, written by 'config' command. | 9 .gclient : Current client configuration, written by 'config' command. |
| 10 Format is a Python script defining 'solutions', a list whose | 10 Format is a Python script defining 'solutions', a list whose |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 | 138 |
| 139 class Dependency(GClientKeywords, gclient_utils.WorkItem): | 139 class Dependency(GClientKeywords, gclient_utils.WorkItem): |
| 140 """Object that represents a dependency checkout.""" | 140 """Object that represents a dependency checkout.""" |
| 141 | 141 |
| 142 def __init__(self, parent, name, url, safesync_url, custom_deps, | 142 def __init__(self, parent, name, url, safesync_url, custom_deps, |
| 143 custom_vars, deps_file, should_process): | 143 custom_vars, deps_file, should_process): |
| 144 # Warning: this function can be called from any thread. Both | 144 # Warning: this function can be called from any thread. Both |
| 145 # self.dependencies and self.requirements are read and modified from | 145 # self.dependencies and self.requirements are read and modified from |
| 146 # multiple threads at the same time. Sad. | 146 # multiple threads at the same time. Sad. |
| 147 GClientKeywords.__init__(self) | 147 GClientKeywords.__init__(self) |
| 148 gclient_utils.WorkItem.__init__(self) | 148 gclient_utils.WorkItem.__init__(self, name) |
| 149 self.parent = parent | 149 self.parent = parent |
| 150 self.name = name | |
| 151 self.url = url | 150 self.url = url |
| 152 self.parsed_url = None | 151 self.parsed_url = None |
| 153 # These 2 are only set in .gclient and not in DEPS files. | 152 # These 2 are only set in .gclient and not in DEPS files. |
| 154 self.safesync_url = safesync_url | 153 self.safesync_url = safesync_url |
| 155 self.custom_vars = custom_vars or {} | 154 self.custom_vars = custom_vars or {} |
| 156 self.custom_deps = custom_deps or {} | 155 self.custom_deps = custom_deps or {} |
| 157 self.deps_hooks = [] | 156 self.deps_hooks = [] |
| 158 self.dependencies = [] | 157 self.dependencies = [] |
| 159 self.deps_file = deps_file | 158 self.deps_file = deps_file |
| 160 # A cache of the files affected by the current operation, necessary for | 159 # A cache of the files affected by the current operation, necessary for |
| 161 # hooks. | 160 # hooks. |
| 162 self._file_list = [] | 161 self._file_list = [] |
| 163 # If it is not set to True, the dependency wasn't processed for its child | 162 # If it is not set to True, the dependency wasn't processed for its child |
| 164 # dependency, i.e. its DEPS wasn't read. | 163 # dependency, i.e. its DEPS wasn't read. |
| 165 self.deps_parsed = False | 164 self.deps_parsed = False |
| 166 # This dependency should be processed, i.e. checked out | 165 # This dependency should be processed, i.e. checked out |
| 167 self.should_process = should_process | 166 self.should_process = should_process |
| 168 # This dependency has been processed, i.e. checked out | 167 # This dependency has been processed, i.e. checked out |
| 169 self.processed = False | 168 self.processed = False |
| 170 # This dependency had its hook run | 169 # This dependency had its hook run |
| 171 self.hooks_ran = False | 170 self.hooks_ran = False |
| 172 # Required dependencies to run before running this one: | |
| 173 self.requirements = set() | |
| 174 | 171 |
| 175 # Post process the url to remove trailing slashes. | 172 # Post process the url to remove trailing slashes. |
| 176 if isinstance(self.url, basestring): | 173 if isinstance(self.url, basestring): |
| 177 # urls are sometime incorrectly written as proto://host/path/@rev. Replace | 174 # urls are sometime incorrectly written as proto://host/path/@rev. Replace |
| 178 # it to proto://host/path@rev. | 175 # it to proto://host/path@rev. |
| 179 if self.url.count('@') > 1: | 176 if self.url.count('@') > 1: |
| 180 raise gclient_utils.Error('Invalid url "%s"' % self.url) | 177 raise gclient_utils.Error('Invalid url "%s"' % self.url) |
| 181 self.url = self.url.replace('/@', '@') | 178 self.url = self.url.replace('/@', '@') |
| 182 | 179 |
| 183 self._FindDependencies() | 180 self._FindDependencies() |
| (...skipping 10 matching lines...) Expand all Loading... |
| 194 raise gclient_utils.Error('deps_file name must not be a path, just a ' | 191 raise gclient_utils.Error('deps_file name must not be a path, just a ' |
| 195 'filename. %s' % self.deps_file) | 192 'filename. %s' % self.deps_file) |
| 196 | 193 |
| 197 def _FindDependencies(self): | 194 def _FindDependencies(self): |
| 198 """Setup self.requirements and find any other dependency who would have self | 195 """Setup self.requirements and find any other dependency who would have self |
| 199 as a requirement. | 196 as a requirement. |
| 200 """ | 197 """ |
| 201 # self.parent is implicitly a requirement. This will be recursive by | 198 # self.parent is implicitly a requirement. This will be recursive by |
| 202 # definition. | 199 # definition. |
| 203 if self.parent and self.parent.name: | 200 if self.parent and self.parent.name: |
| 204 self.requirements.add(self.parent.name) | 201 self._requirements.add(self.parent.name) |
| 205 | 202 |
| 206 # For a tree with at least 2 levels*, the leaf node needs to depend | 203 # For a tree with at least 2 levels*, the leaf node needs to depend |
| 207 # on the level higher up in an orderly way. | 204 # on the level higher up in an orderly way. |
| 208 # This becomes messy for >2 depth as the DEPS file format is a dictionary, | 205 # This becomes messy for >2 depth as the DEPS file format is a dictionary, |
| 209 # thus unsorted, while the .gclient format is a list thus sorted. | 206 # thus unsorted, while the .gclient format is a list thus sorted. |
| 210 # | 207 # |
| 211 # * _recursion_limit is hard coded 2 and there is no hope to change this | 208 # * _recursion_limit is hard coded 2 and there is no hope to change this |
| 212 # value. | 209 # value. |
| 213 # | 210 # |
| 214 # Interestingly enough, the following condition only works in the case we | 211 # Interestingly enough, the following condition only works in the case we |
| 215 # want: self is a 2nd level node. 3nd level node wouldn't need this since | 212 # want: self is a 2nd level node. 3nd level node wouldn't need this since |
| 216 # they already have their parent as a requirement. | 213 # they already have their parent as a requirement. |
| 217 if self.parent in self.root_parent().dependencies: | 214 if self.parent in self.root_parent().dependencies: |
| 218 root_deps = self.root_parent().dependencies | 215 root_deps = self.root_parent().dependencies |
| 219 for i in range(0, root_deps.index(self.parent)): | 216 for i in range(0, root_deps.index(self.parent)): |
| 220 value = root_deps[i] | 217 value = root_deps[i] |
| 221 if value.name: | 218 if value.name: |
| 222 self.requirements.add(value.name) | 219 self._requirements.add(value.name) |
| 223 | 220 |
| 224 if isinstance(self.url, self.FromImpl): | 221 if isinstance(self.url, self.FromImpl): |
| 225 self.requirements.add(self.url.module_name) | 222 self._requirements.add(self.url.module_name) |
| 226 | 223 |
| 227 if self.name and self.should_process: | 224 if self.name and self.should_process: |
| 228 def yield_full_tree(root): | 225 def yield_full_tree(root): |
| 229 """Depth-first recursion.""" | 226 """Depth-first recursion.""" |
| 230 yield root | 227 yield root |
| 231 for i in root.dependencies: | 228 for i in root.dependencies: |
| 232 for j in yield_full_tree(i): | 229 for j in yield_full_tree(i): |
| 233 if j.should_process: | 230 if j.should_process: |
| 234 yield j | 231 yield j |
| 235 | 232 |
| 236 for obj in yield_full_tree(self.root_parent()): | 233 for obj in yield_full_tree(self.root_parent()): |
| 237 if obj is self or not obj.name: | 234 if obj is self or not obj.name: |
| 238 continue | 235 continue |
| 239 # Step 1: Find any requirements self may need. | 236 # Step 1: Find any requirements self may need. |
| 240 if self.name.startswith(posixpath.join(obj.name, '')): | 237 if self.name.startswith(posixpath.join(obj.name, '')): |
| 241 self.requirements.add(obj.name) | 238 self._requirements.add(obj.name) |
| 242 # Step 2: Find any requirements self may impose. | 239 # Step 2: Find any requirements self may impose. |
| 243 if obj.name.startswith(posixpath.join(self.name, '')): | 240 if obj.name.startswith(posixpath.join(self.name, '')): |
| 244 obj.requirements.add(self.name) | 241 try: |
| 242 # Access to a protected member _requirements of a client class |
| 243 # pylint: disable=W0212 |
| 244 obj.lock.acquire() |
| 245 obj._requirements.add(self.name) |
| 246 finally: |
| 247 obj.lock.release() |
| 245 | 248 |
| 246 def LateOverride(self, url): | 249 def LateOverride(self, url): |
| 247 """Resolves the parsed url from url. | 250 """Resolves the parsed url from url. |
| 248 | 251 |
| 249 Manages From() keyword accordingly. Do not touch self.parsed_url nor | 252 Manages From() keyword accordingly. Do not touch self.parsed_url nor |
| 250 self.url because it may called with other urls due to From().""" | 253 self.url because it may called with other urls due to From().""" |
| 251 assert self.parsed_url == None or not self.should_process, self.parsed_url | 254 assert self.parsed_url == None or not self.should_process, self.parsed_url |
| 252 overriden_url = self.get_custom_deps(self.name, url) | 255 overriden_url = self.get_custom_deps(self.name, url) |
| 253 if overriden_url != url: | 256 if overriden_url != url: |
| 254 logging.info('%s, %s was overriden to %s' % (self.name, url, | 257 logging.info('%s, %s was overriden to %s' % (self.name, url, |
| (...skipping 1107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1362 except (gclient_utils.Error, subprocess2.CalledProcessError), e: | 1365 except (gclient_utils.Error, subprocess2.CalledProcessError), e: |
| 1363 print >> sys.stderr, 'Error: %s' % str(e) | 1366 print >> sys.stderr, 'Error: %s' % str(e) |
| 1364 return 1 | 1367 return 1 |
| 1365 | 1368 |
| 1366 | 1369 |
| 1367 if '__main__' == __name__: | 1370 if '__main__' == __name__: |
| 1368 fix_encoding.fix_encoding() | 1371 fix_encoding.fix_encoding() |
| 1369 sys.exit(Main(sys.argv[1:])) | 1372 sys.exit(Main(sys.argv[1:])) |
| 1370 | 1373 |
| 1371 # vim: ts=2:sw=2:tw=80:et: | 1374 # vim: ts=2:sw=2:tw=80:et: |
| OLD | NEW |