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 |