| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright (c) 2010 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2010 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 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 130 return self._custom_vars[var_name] | 130 return self._custom_vars[var_name] |
| 131 elif var_name in self._local_scope.get("vars", {}): | 131 elif var_name in self._local_scope.get("vars", {}): |
| 132 return self._local_scope["vars"][var_name] | 132 return self._local_scope["vars"][var_name] |
| 133 raise gclient_utils.Error("Var is not defined: %s" % var_name) | 133 raise gclient_utils.Error("Var is not defined: %s" % var_name) |
| 134 | 134 |
| 135 | 135 |
| 136 class Dependency(GClientKeywords): | 136 class Dependency(GClientKeywords): |
| 137 """Object that represents a dependency checkout.""" | 137 """Object that represents a dependency checkout.""" |
| 138 DEPS_FILE = 'DEPS' | 138 DEPS_FILE = 'DEPS' |
| 139 | 139 |
| 140 def __init__(self, parent, name, url, safesync_url=None, custom_deps=None, | 140 def __init__(self, parent, name, url, safesync_url, custom_deps, |
| 141 custom_vars=None, deps_file=None): | 141 custom_vars, deps_file): |
| 142 GClientKeywords.__init__(self) | 142 GClientKeywords.__init__(self) |
| 143 self.parent = parent | 143 self.parent = parent |
| 144 self.name = name | 144 self.name = name |
| 145 self.url = url | 145 self.url = url |
| 146 self.parsed_url = None | 146 self.parsed_url = None |
| 147 # These 2 are only set in .gclient and not in DEPS files. | 147 # These 2 are only set in .gclient and not in DEPS files. |
| 148 self.safesync_url = safesync_url | 148 self.safesync_url = safesync_url |
| 149 self.custom_vars = custom_vars or {} | 149 self.custom_vars = custom_vars or {} |
| 150 self.custom_deps = custom_deps or {} | 150 self.custom_deps = custom_deps or {} |
| 151 self.deps_hooks = [] | 151 self.deps_hooks = [] |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 290 for d, url in deps.items(): | 290 for d, url in deps.items(): |
| 291 # normpath is required to allow DEPS to use .. in their | 291 # normpath is required to allow DEPS to use .. in their |
| 292 # dependency local path. | 292 # dependency local path. |
| 293 rel_deps[os.path.normpath(os.path.join(self.name, d))] = url | 293 rel_deps[os.path.normpath(os.path.join(self.name, d))] = url |
| 294 deps = rel_deps | 294 deps = rel_deps |
| 295 | 295 |
| 296 # Convert the deps into real Dependency. | 296 # Convert the deps into real Dependency. |
| 297 for name, url in deps.iteritems(): | 297 for name, url in deps.iteritems(): |
| 298 if name in [s.name for s in self.dependencies]: | 298 if name in [s.name for s in self.dependencies]: |
| 299 raise | 299 raise |
| 300 self.dependencies.append(Dependency(self, name, url)) | 300 self.dependencies.append(Dependency(self, name, url, None, None, None, |
| 301 None)) |
| 301 # Sort by name. | 302 # Sort by name. |
| 302 self.dependencies.sort(key=lambda x: x.name) | 303 self.dependencies.sort(key=lambda x: x.name) |
| 303 logging.info('Loaded: %s' % str(self)) | 304 logging.info('Loaded: %s' % str(self)) |
| 304 | 305 |
| 305 def RunCommandRecursively(self, options, revision_overrides, | 306 def RunCommandRecursively(self, options, revision_overrides, |
| 306 command, args, pm): | 307 command, args, pm): |
| 307 """Runs 'command' before parsing the DEPS in case it's a initial checkout | 308 """Runs 'command' before parsing the DEPS in case it's a initial checkout |
| 308 or a revert.""" | 309 or a revert.""" |
| 309 assert self._file_list == [] | 310 assert self._file_list == [] |
| 310 # When running runhooks, there's no need to consult the SCM. | 311 # When running runhooks, there's no need to consult the SCM. |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 | 416 |
| 416 def root_dir(self): | 417 def root_dir(self): |
| 417 return self.parent.root_dir() | 418 return self.parent.root_dir() |
| 418 | 419 |
| 419 def enforced_os(self): | 420 def enforced_os(self): |
| 420 return self.parent.enforced_os() | 421 return self.parent.enforced_os() |
| 421 | 422 |
| 422 def recursion_limit(self): | 423 def recursion_limit(self): |
| 423 return self.parent.recursion_limit() - 1 | 424 return self.parent.recursion_limit() - 1 |
| 424 | 425 |
| 425 def tree(self, force_all): | 426 def tree(self, include_all): |
| 426 return self.parent.tree(force_all) | 427 return self.parent.tree(include_all) |
| 427 | 428 |
| 428 def subtree(self, force_all): | 429 def subtree(self, include_all): |
| 429 result = [] | 430 result = [] |
| 430 # Add breadth-first. | 431 # Add breadth-first. |
| 431 if self.direct_reference or force_all: | 432 if self.direct_reference or include_all: |
| 432 for d in self.dependencies: | 433 for d in self.dependencies: |
| 433 result.append(d) | 434 result.append(d) |
| 434 for d in self.dependencies: | 435 for d in self.dependencies: |
| 435 result.extend(d.subtree(force_all)) | 436 result.extend(d.subtree(include_all)) |
| 436 return result | 437 return result |
| 437 | 438 |
| 438 def get_custom_deps(self, name, url): | 439 def get_custom_deps(self, name, url): |
| 439 """Returns a custom deps if applicable.""" | 440 """Returns a custom deps if applicable.""" |
| 440 if self.parent: | 441 if self.parent: |
| 441 url = self.parent.get_custom_deps(name, url) | 442 url = self.parent.get_custom_deps(name, url) |
| 442 # None is a valid return value to disable a dependency. | 443 # None is a valid return value to disable a dependency. |
| 443 return self.custom_deps.get(name, url) | 444 return self.custom_deps.get(name, url) |
| 444 | 445 |
| 445 def file_list(self): | 446 def file_list(self): |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 509 }, | 510 }, |
| 510 """) | 511 """) |
| 511 | 512 |
| 512 DEFAULT_SNAPSHOT_FILE_TEXT = ("""\ | 513 DEFAULT_SNAPSHOT_FILE_TEXT = ("""\ |
| 513 # Snapshot generated with gclient revinfo --snapshot | 514 # Snapshot generated with gclient revinfo --snapshot |
| 514 solutions = [ | 515 solutions = [ |
| 515 %(solution_list)s] | 516 %(solution_list)s] |
| 516 """) | 517 """) |
| 517 | 518 |
| 518 def __init__(self, root_dir, options): | 519 def __init__(self, root_dir, options): |
| 519 Dependency.__init__(self, None, None, None) | 520 # Do not change previous behavior. Only solution level and immediate DEPS |
| 521 # are processed. |
| 522 self._recursion_limit = 2 |
| 523 Dependency.__init__(self, None, None, None, None, None, None, None) |
| 520 self._options = options | 524 self._options = options |
| 521 if options.deps_os: | 525 if options.deps_os: |
| 522 enforced_os = options.deps_os.split(',') | 526 enforced_os = options.deps_os.split(',') |
| 523 else: | 527 else: |
| 524 enforced_os = [self.DEPS_OS_CHOICES.get(sys.platform, 'unix')] | 528 enforced_os = [self.DEPS_OS_CHOICES.get(sys.platform, 'unix')] |
| 525 if 'all' in enforced_os: | 529 if 'all' in enforced_os: |
| 526 enforced_os = self.DEPS_OS_CHOICES.itervalues() | 530 enforced_os = self.DEPS_OS_CHOICES.itervalues() |
| 527 self._enforced_os = list(set(enforced_os)) | 531 self._enforced_os = list(set(enforced_os)) |
| 528 self._root_dir = root_dir | 532 self._root_dir = root_dir |
| 529 self.config_content = None | 533 self.config_content = None |
| 530 # Do not change previous behavior. Only solution level and immediate DEPS | |
| 531 # are processed. | |
| 532 self._recursion_limit = 2 | |
| 533 | 534 |
| 534 def SetConfig(self, content): | 535 def SetConfig(self, content): |
| 535 assert self.dependencies == [] | 536 assert self.dependencies == [] |
| 536 config_dict = {} | 537 config_dict = {} |
| 537 self.config_content = content | 538 self.config_content = content |
| 538 try: | 539 try: |
| 539 exec(content, config_dict) | 540 exec(content, config_dict) |
| 540 except SyntaxError, e: | 541 except SyntaxError, e: |
| 541 gclient_utils.SyntaxErrorToError('.gclient', e) | 542 gclient_utils.SyntaxErrorToError('.gclient', e) |
| 542 for s in config_dict.get('solutions', []): | 543 for s in config_dict.get('solutions', []): |
| 543 try: | 544 try: |
| 544 self.dependencies.append(Dependency( | 545 self.dependencies.append(Dependency( |
| 545 self, s['name'], s['url'], | 546 self, s['name'], s['url'], |
| 546 s.get('safesync_url', None), | 547 s.get('safesync_url', None), |
| 547 s.get('custom_deps', {}), | 548 s.get('custom_deps', {}), |
| 548 s.get('custom_vars', {}))) | 549 s.get('custom_vars', {}), |
| 550 None)) |
| 549 except KeyError: | 551 except KeyError: |
| 550 raise gclient_utils.Error('Invalid .gclient file. Solution is ' | 552 raise gclient_utils.Error('Invalid .gclient file. Solution is ' |
| 551 'incomplete: %s' % s) | 553 'incomplete: %s' % s) |
| 552 # .gclient can have hooks. | 554 # .gclient can have hooks. |
| 553 self.deps_hooks = config_dict.get('hooks', []) | 555 self.deps_hooks = config_dict.get('hooks', []) |
| 554 | 556 |
| 555 def SaveConfig(self): | 557 def SaveConfig(self): |
| 556 gclient_utils.FileWrite(os.path.join(self.root_dir(), | 558 gclient_utils.FileWrite(os.path.join(self.root_dir(), |
| 557 self._options.config_filename), | 559 self._options.config_filename), |
| 558 self.config_content) | 560 self.config_content) |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 769 return self._root_dir | 771 return self._root_dir |
| 770 | 772 |
| 771 def enforced_os(self): | 773 def enforced_os(self): |
| 772 """What deps_os entries that are to be parsed.""" | 774 """What deps_os entries that are to be parsed.""" |
| 773 return self._enforced_os | 775 return self._enforced_os |
| 774 | 776 |
| 775 def recursion_limit(self): | 777 def recursion_limit(self): |
| 776 """How recursive can each dependencies in DEPS file can load DEPS file.""" | 778 """How recursive can each dependencies in DEPS file can load DEPS file.""" |
| 777 return self._recursion_limit | 779 return self._recursion_limit |
| 778 | 780 |
| 779 def tree(self, force_all): | 781 def tree(self, include_all): |
| 780 """Returns a flat list of all the dependencies.""" | 782 """Returns a flat list of all the dependencies.""" |
| 781 return self.subtree(force_all) | 783 return self.subtree(include_all) |
| 782 | 784 |
| 783 | 785 |
| 784 #### gclient commands. | 786 #### gclient commands. |
| 785 | 787 |
| 786 | 788 |
| 787 def CMDcleanup(parser, args): | 789 def CMDcleanup(parser, args): |
| 788 """Cleans up all working copies. | 790 """Cleans up all working copies. |
| 789 | 791 |
| 790 Mostly svn-specific. Simply runs 'svn cleanup' for each module. | 792 Mostly svn-specific. Simply runs 'svn cleanup' for each module. |
| 791 """ | 793 """ |
| (...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1160 return CMDhelp(parser, argv) | 1162 return CMDhelp(parser, argv) |
| 1161 except gclient_utils.Error, e: | 1163 except gclient_utils.Error, e: |
| 1162 print >> sys.stderr, 'Error: %s' % str(e) | 1164 print >> sys.stderr, 'Error: %s' % str(e) |
| 1163 return 1 | 1165 return 1 |
| 1164 | 1166 |
| 1165 | 1167 |
| 1166 if '__main__' == __name__: | 1168 if '__main__' == __name__: |
| 1167 sys.exit(Main(sys.argv[1:])) | 1169 sys.exit(Main(sys.argv[1:])) |
| 1168 | 1170 |
| 1169 # vim: ts=2:sw=2:tw=80:et: | 1171 # vim: ts=2:sw=2:tw=80:et: |
| OLD | NEW |