| 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 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 129 | 129 |
| 130 def Lookup(self, var_name): | 130 def Lookup(self, var_name): |
| 131 """Implements the Var syntax.""" | 131 """Implements the Var syntax.""" |
| 132 if var_name in self._custom_vars: | 132 if var_name in self._custom_vars: |
| 133 return self._custom_vars[var_name] | 133 return self._custom_vars[var_name] |
| 134 elif var_name in self._local_scope.get("vars", {}): | 134 elif var_name in self._local_scope.get("vars", {}): |
| 135 return self._local_scope["vars"][var_name] | 135 return self._local_scope["vars"][var_name] |
| 136 raise gclient_utils.Error("Var is not defined: %s" % var_name) | 136 raise gclient_utils.Error("Var is not defined: %s" % var_name) |
| 137 | 137 |
| 138 | 138 |
| 139 class Dependency(GClientKeywords, gclient_utils.WorkItem): | 139 class DependencySettings(object): |
| 140 """Immutable configuration settings.""" |
| 141 def __init__( |
| 142 self, parent, safesync_url, managed, custom_deps, custom_vars, |
| 143 deps_file, should_process): |
| 144 # These are not mutable: |
| 145 self._parent = parent |
| 146 self._safesync_url = safesync_url |
| 147 self._deps_file = deps_file |
| 148 # 'managed' determines whether or not this dependency is synced/updated by |
| 149 # gclient after gclient checks it out initially. The difference between |
| 150 # 'managed' and 'should_process' is that the user specifies 'managed' via |
| 151 # the --unmanaged command-line flag or a .gclient config, where |
| 152 # 'should_process' is dynamically set by gclient if it goes over its |
| 153 # recursion limit and controls gclient's behavior so it does not misbehave. |
| 154 self._managed = managed |
| 155 self._should_process = should_process |
| 156 |
| 157 # These are only set in .gclient and not in DEPS files. |
| 158 self._custom_vars = custom_vars or {} |
| 159 self._custom_deps = custom_deps or {} |
| 160 |
| 161 if '/' in self._deps_file or '\\' in self._deps_file: |
| 162 raise gclient_utils.Error('deps_file name must not be a path, just a ' |
| 163 'filename. %s' % self._deps_file) |
| 164 |
| 165 @property |
| 166 def deps_file(self): |
| 167 """Immutable so no need to lock.""" |
| 168 return self._deps_file |
| 169 |
| 170 @property |
| 171 def managed(self): |
| 172 """Immutable so no need to lock.""" |
| 173 return self._managed |
| 174 |
| 175 @property |
| 176 def parent(self): |
| 177 """Immutable so no need to lock.""" |
| 178 return self._parent |
| 179 |
| 180 @property |
| 181 def safesync_url(self): |
| 182 """Immutable so no need to lock.""" |
| 183 return self._safesync_url |
| 184 |
| 185 @property |
| 186 def should_process(self): |
| 187 """True if this dependency should be processed, i.e. checked out.""" |
| 188 return self._should_process |
| 189 |
| 190 @property |
| 191 def custom_vars(self): |
| 192 """Immutable so no need to lock.""" |
| 193 return self._custom_vars.copy() |
| 194 |
| 195 @property |
| 196 def custom_deps(self): |
| 197 """Immutable so no need to lock.""" |
| 198 return self._custom_deps.copy() |
| 199 |
| 200 |
| 201 class Dependency(GClientKeywords, gclient_utils.WorkItem, DependencySettings): |
| 140 """Object that represents a dependency checkout.""" | 202 """Object that represents a dependency checkout.""" |
| 141 | 203 |
| 142 def __init__(self, parent, name, url, safesync_url, managed, custom_deps, | 204 def __init__(self, parent, name, url, safesync_url, managed, custom_deps, |
| 143 custom_vars, deps_file, should_process): | 205 custom_vars, deps_file, should_process): |
| 144 # Warning: this function can be called from any thread. Both | 206 # Warning: this function can be called from any thread. Both |
| 145 # self.dependencies and self.requirements are read and modified from | 207 # self.dependencies and self.requirements are read and modified from |
| 146 # multiple threads at the same time. Sad. | 208 # multiple threads at the same time. Sad. |
| 147 GClientKeywords.__init__(self) | 209 GClientKeywords.__init__(self) |
| 148 gclient_utils.WorkItem.__init__(self, name) | 210 gclient_utils.WorkItem.__init__(self, name) |
| 149 | 211 DependencySettings.__init__( |
| 150 # These are not mutable: | 212 self, parent, safesync_url, managed, custom_deps, custom_vars, |
| 151 self._parent = parent | 213 deps_file, should_process) |
| 152 self._safesync_url = safesync_url | |
| 153 self._deps_file = deps_file | |
| 154 self._should_process = should_process | |
| 155 | 214 |
| 156 # This is in both .gclient and DEPS files: | 215 # This is in both .gclient and DEPS files: |
| 157 self.url = url | 216 self.url = url |
| 158 | 217 |
| 159 # These are only set in .gclient and not in DEPS files. | |
| 160 # 'managed' determines whether or not this dependency is synced/updated by | |
| 161 # gclient after gclient checks it out initially. The difference between | |
| 162 # 'managed' and 'should_process' (defined below) is that the user specifies | |
| 163 # 'managed' via the --unmanaged command-line flag or a .gclient config, | |
| 164 # where 'should_process' is dynamically set by gclient if it goes over its | |
| 165 # recursion limit and controls gclient's behavior so it does not misbehave. | |
| 166 self._managed = managed | |
| 167 self._custom_vars = custom_vars or {} | |
| 168 self._custom_deps = custom_deps or {} | |
| 169 self.deps_hooks = [] | 218 self.deps_hooks = [] |
| 170 | 219 |
| 171 # Calculates properties: | 220 # Calculates properties: |
| 172 self.parsed_url = None | 221 self.parsed_url = None |
| 173 self.dependencies = [] | 222 self.dependencies = [] |
| 174 # A cache of the files affected by the current operation, necessary for | 223 # A cache of the files affected by the current operation, necessary for |
| 175 # hooks. | 224 # hooks. |
| 176 self._file_list = [] | 225 self._file_list = [] |
| 177 # If it is not set to True, the dependency wasn't processed for its child | 226 # If it is not set to True, the dependency wasn't processed for its child |
| 178 # dependency, i.e. its DEPS wasn't read. | 227 # dependency, i.e. its DEPS wasn't read. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 193 self._FindDependencies() | 242 self._FindDependencies() |
| 194 | 243 |
| 195 # Sanity checks | 244 # Sanity checks |
| 196 if not self.name and self.parent: | 245 if not self.name and self.parent: |
| 197 raise gclient_utils.Error('Dependency without name') | 246 raise gclient_utils.Error('Dependency without name') |
| 198 if not isinstance(self.url, | 247 if not isinstance(self.url, |
| 199 (basestring, self.FromImpl, self.FileImpl, None.__class__)): | 248 (basestring, self.FromImpl, self.FileImpl, None.__class__)): |
| 200 raise gclient_utils.Error('dependency url must be either a string, None, ' | 249 raise gclient_utils.Error('dependency url must be either a string, None, ' |
| 201 'File() or From() instead of %s' % | 250 'File() or From() instead of %s' % |
| 202 self.url.__class__.__name__) | 251 self.url.__class__.__name__) |
| 203 if '/' in self.deps_file or '\\' in self.deps_file: | |
| 204 raise gclient_utils.Error('deps_file name must not be a path, just a ' | |
| 205 'filename. %s' % self.deps_file) | |
| 206 | 252 |
| 207 def _FindDependencies(self): | 253 def _FindDependencies(self): |
| 208 """Setup self.requirements and find any other dependency who would have self | 254 """Setup self.requirements and find any other dependency who would have self |
| 209 as a requirement. | 255 as a requirement. |
| 210 """ | 256 """ |
| 211 # self.parent is implicitly a requirement. This will be recursive by | 257 # self.parent is implicitly a requirement. This will be recursive by |
| 212 # definition. | 258 # definition. |
| 213 if self.parent and self.parent.name: | 259 if self.parent and self.parent.name: |
| 214 self._requirements.add(self.parent.name) | 260 self._requirements.add(self.parent.name) |
| 215 | 261 |
| (...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 """Returns a custom deps if applicable.""" | 626 """Returns a custom deps if applicable.""" |
| 581 if self.parent: | 627 if self.parent: |
| 582 url = self.parent.get_custom_deps(name, url) | 628 url = self.parent.get_custom_deps(name, url) |
| 583 # None is a valid return value to disable a dependency. | 629 # None is a valid return value to disable a dependency. |
| 584 return self.custom_deps.get(name, url) | 630 return self.custom_deps.get(name, url) |
| 585 | 631 |
| 586 @property | 632 @property |
| 587 def recursion_limit(self): | 633 def recursion_limit(self): |
| 588 """Returns > 0 if this dependency is not too recursed to be processed. | 634 """Returns > 0 if this dependency is not too recursed to be processed. |
| 589 | 635 |
| 590 Immutable so no need to lock.""" | 636 Immutable so no need to lock. |
| 637 """ |
| 591 return max(self.parent.recursion_limit - 1, 0) | 638 return max(self.parent.recursion_limit - 1, 0) |
| 592 | 639 |
| 593 @property | 640 @property |
| 594 def deps_file(self): | |
| 595 """Immutable so no need to lock.""" | |
| 596 return self._deps_file | |
| 597 | |
| 598 @property | |
| 599 def managed(self): | |
| 600 """Immutable so no need to lock.""" | |
| 601 return self._managed | |
| 602 | |
| 603 @property | |
| 604 def safesync_url(self): | |
| 605 """Immutable so no need to lock.""" | |
| 606 return self._safesync_url | |
| 607 | |
| 608 @property | |
| 609 def should_process(self): | |
| 610 """True if this dependency should be processed, i.e. checked out.""" | |
| 611 return self._should_process | |
| 612 | |
| 613 @property | |
| 614 def parent(self): | |
| 615 """Immutable so no need to lock.""" | |
| 616 return self._parent | |
| 617 | |
| 618 @property | |
| 619 def custom_vars(self): | |
| 620 """Immutable so no need to lock.""" | |
| 621 return self._custom_vars.copy() | |
| 622 | |
| 623 @property | |
| 624 def custom_deps(self): | |
| 625 """Immutable so no need to lock.""" | |
| 626 return self._custom_deps.copy() | |
| 627 | |
| 628 @property | |
| 629 @gclient_utils.lockedmethod | 641 @gclient_utils.lockedmethod |
| 630 def file_list(self): | 642 def file_list(self): |
| 631 result = self._file_list[:] | 643 result = self._file_list[:] |
| 632 for d in self.dependencies: | 644 for d in self.dependencies: |
| 633 result.extend(d.file_list) | 645 result.extend(d.file_list) |
| 634 return tuple(result) | 646 return tuple(result) |
| 635 | 647 |
| 636 def __str__(self): | 648 def __str__(self): |
| 637 out = [] | 649 out = [] |
| 638 for i in ('name', 'url', 'parsed_url', 'safesync_url', 'custom_deps', | 650 for i in ('name', 'url', 'parsed_url', 'safesync_url', 'custom_deps', |
| (...skipping 786 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1425 except (gclient_utils.Error, subprocess2.CalledProcessError), e: | 1437 except (gclient_utils.Error, subprocess2.CalledProcessError), e: |
| 1426 print >> sys.stderr, 'Error: %s' % str(e) | 1438 print >> sys.stderr, 'Error: %s' % str(e) |
| 1427 return 1 | 1439 return 1 |
| 1428 | 1440 |
| 1429 | 1441 |
| 1430 if '__main__' == __name__: | 1442 if '__main__' == __name__: |
| 1431 fix_encoding.fix_encoding() | 1443 fix_encoding.fix_encoding() |
| 1432 sys.exit(Main(sys.argv[1:])) | 1444 sys.exit(Main(sys.argv[1:])) |
| 1433 | 1445 |
| 1434 # vim: ts=2:sw=2:tw=80:et: | 1446 # vim: ts=2:sw=2:tw=80:et: |
| OLD | NEW |