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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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, name) | 148 gclient_utils.WorkItem.__init__(self, name) |
149 self.parent = parent | 149 |
| 150 # These are not mutable: |
| 151 self._parent = parent |
| 152 self._safesync_url = safesync_url |
| 153 self._deps_file = deps_file |
| 154 self._should_process = should_process |
| 155 |
| 156 # This is in both .gclient and DEPS files: |
150 self.url = url | 157 self.url = url |
151 self.parsed_url = None | 158 |
152 # These 2 are only set in .gclient and not in DEPS files. | 159 # These are only set in .gclient and not in DEPS files. |
153 self.safesync_url = safesync_url | |
154 self.custom_vars = custom_vars or {} | 160 self.custom_vars = custom_vars or {} |
155 self.custom_deps = custom_deps or {} | 161 self.custom_deps = custom_deps or {} |
156 self.deps_hooks = [] | 162 self.deps_hooks = [] |
| 163 |
| 164 # Calculates properties: |
| 165 self.parsed_url = None |
157 self.dependencies = [] | 166 self.dependencies = [] |
158 self.deps_file = deps_file | |
159 # A cache of the files affected by the current operation, necessary for | 167 # A cache of the files affected by the current operation, necessary for |
160 # hooks. | 168 # hooks. |
161 self._file_list = [] | 169 self._file_list = [] |
162 # If it is not set to True, the dependency wasn't processed for its child | 170 # If it is not set to True, the dependency wasn't processed for its child |
163 # dependency, i.e. its DEPS wasn't read. | 171 # dependency, i.e. its DEPS wasn't read. |
164 self.deps_parsed = False | 172 self.deps_parsed = False |
165 # This dependency should be processed, i.e. checked out | |
166 self.should_process = should_process | |
167 # This dependency has been processed, i.e. checked out | 173 # This dependency has been processed, i.e. checked out |
168 self.processed = False | 174 self.processed = False |
169 # This dependency had its hook run | 175 # This dependency had its hook run |
170 self.hooks_ran = False | 176 self.hooks_ran = False |
171 | 177 |
172 # Post process the url to remove trailing slashes. | 178 # Post process the url to remove trailing slashes. |
173 if isinstance(self.url, basestring): | 179 if isinstance(self.url, basestring): |
174 # urls are sometime incorrectly written as proto://host/path/@rev. Replace | 180 # urls are sometime incorrectly written as proto://host/path/@rev. Replace |
175 # it to proto://host/path@rev. | 181 # it to proto://host/path@rev. |
176 if self.url.count('@') > 1: | 182 if self.url.count('@') > 1: |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
251 | 257 |
252 Manages From() keyword accordingly. Do not touch self.parsed_url nor | 258 Manages From() keyword accordingly. Do not touch self.parsed_url nor |
253 self.url because it may called with other urls due to From().""" | 259 self.url because it may called with other urls due to From().""" |
254 assert self.parsed_url == None or not self.should_process, self.parsed_url | 260 assert self.parsed_url == None or not self.should_process, self.parsed_url |
255 overriden_url = self.get_custom_deps(self.name, url) | 261 overriden_url = self.get_custom_deps(self.name, url) |
256 if overriden_url != url: | 262 if overriden_url != url: |
257 logging.info('%s, %s was overriden to %s' % (self.name, url, | 263 logging.info('%s, %s was overriden to %s' % (self.name, url, |
258 overriden_url)) | 264 overriden_url)) |
259 return overriden_url | 265 return overriden_url |
260 elif isinstance(url, self.FromImpl): | 266 elif isinstance(url, self.FromImpl): |
261 ref = [dep for dep in self.tree(True) if url.module_name == dep.name] | 267 ref = [ |
| 268 dep for dep in self.root.subtree(True) if url.module_name == dep.name |
| 269 ] |
262 if not ref: | 270 if not ref: |
263 raise gclient_utils.Error('Failed to find one reference to %s. %s' % ( | 271 raise gclient_utils.Error('Failed to find one reference to %s. %s' % ( |
264 url.module_name, ref)) | 272 url.module_name, ref)) |
265 # It may happen that len(ref) > 1 but it's no big deal. | 273 # It may happen that len(ref) > 1 but it's no big deal. |
266 ref = ref[0] | 274 ref = ref[0] |
267 sub_target = url.sub_target_name or self.name | 275 sub_target = url.sub_target_name or self.name |
268 # Make sure the referenced dependency DEPS file is loaded and file the | 276 # Make sure the referenced dependency DEPS file is loaded and file the |
269 # inner referenced dependency. | 277 # inner referenced dependency. |
270 ref.ParseDepsFile() | 278 ref.ParseDepsFile() |
271 found_dep = None | 279 found_dep = None |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
372 # dependency local path. | 380 # dependency local path. |
373 rel_deps[os.path.normpath(os.path.join(self.name, d))] = url | 381 rel_deps[os.path.normpath(os.path.join(self.name, d))] = url |
374 deps = rel_deps | 382 deps = rel_deps |
375 | 383 |
376 # Convert the deps into real Dependency. | 384 # Convert the deps into real Dependency. |
377 for name, url in deps.iteritems(): | 385 for name, url in deps.iteritems(): |
378 if name in [s.name for s in self.dependencies]: | 386 if name in [s.name for s in self.dependencies]: |
379 raise gclient_utils.Error( | 387 raise gclient_utils.Error( |
380 'The same name "%s" appears multiple times in the deps section' % | 388 'The same name "%s" appears multiple times in the deps section' % |
381 name) | 389 name) |
382 should_process = self.recursion_limit() > 0 and self.should_process | 390 should_process = self.recursion_limit and self.should_process |
383 if should_process: | 391 if should_process: |
384 tree = dict((d.name, d) for d in self.tree(False)) | 392 tree = dict((d.name, d) for d in self.root.subtree(False)) |
385 if name in tree: | 393 if name in tree: |
386 if url == tree[name].url: | 394 if url == tree[name].url: |
387 logging.info('Won\'t process duplicate dependency %s' % tree[name]) | 395 logging.info('Won\'t process duplicate dependency %s' % tree[name]) |
388 # In theory we could keep it as a shadow of the other one. In | 396 # In theory we could keep it as a shadow of the other one. In |
389 # practice, simply ignore it. | 397 # practice, simply ignore it. |
390 #should_process = False | 398 #should_process = False |
391 continue | 399 continue |
392 else: | 400 else: |
393 raise gclient_utils.Error( | 401 raise gclient_utils.Error( |
394 'Dependency %s specified more than once:\n %s\nvs\n %s' % | 402 'Dependency %s specified more than once:\n %s\nvs\n %s' % |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 # Create a shallow copy to mutate revision. | 467 # Create a shallow copy to mutate revision. |
460 options = copy.copy(options) | 468 options = copy.copy(options) |
461 options.revision = revision_overrides.get(self.name) | 469 options.revision = revision_overrides.get(self.name) |
462 maybeGetParentRevision(options) | 470 maybeGetParentRevision(options) |
463 scm = gclient_scm.CreateSCM( | 471 scm = gclient_scm.CreateSCM( |
464 self.parsed_url, self.root.root_dir, self.name) | 472 self.parsed_url, self.root.root_dir, self.name) |
465 scm.RunCommand(command, options, args, self._file_list) | 473 scm.RunCommand(command, options, args, self._file_list) |
466 maybeConvertToDateRevision(options) | 474 maybeConvertToDateRevision(options) |
467 self._file_list = [os.path.join(self.name, f.strip()) | 475 self._file_list = [os.path.join(self.name, f.strip()) |
468 for f in self._file_list] | 476 for f in self._file_list] |
| 477 |
| 478 # TODO(phajdan.jr): We should know exactly when the paths are absolute. |
| 479 # Convert all absolute paths to relative. |
| 480 for i in range(len(self._file_list)): |
| 481 # It depends on the command being executed (like runhooks vs sync). |
| 482 if not os.path.isabs(self._file_list[i]): |
| 483 continue |
| 484 prefix = os.path.commonprefix( |
| 485 [self.root.root_dir.lower(), self._file_list[i].lower()]) |
| 486 self._file_list[i] = self._file_list[i][len(prefix):] |
| 487 # Strip any leading path separators. |
| 488 while (self._file_list[i].startswith('\\') or |
| 489 self._file_list[i].startswith('/')): |
| 490 self._file_list[i] = self._file_list[i][1:] |
469 self.processed = True | 491 self.processed = True |
470 if self.recursion_limit() > 0: | 492 if self.recursion_limit: |
471 # Then we can parse the DEPS file. | 493 # Then we can parse the DEPS file. |
472 self.ParseDepsFile() | 494 self.ParseDepsFile() |
473 | 495 |
474 # Parse the dependencies of this dependency. | 496 # Parse the dependencies of this dependency. |
475 for s in self.dependencies: | 497 for s in self.dependencies: |
476 work_queue.enqueue(s) | 498 work_queue.enqueue(s) |
477 | 499 |
478 def RunHooksRecursively(self, options): | 500 def RunHooksRecursively(self, options): |
479 """Evaluates all hooks, running actions as needed. run() | 501 """Evaluates all hooks, running actions as needed. run() |
480 must have been called before to load the DEPS.""" | 502 must have been called before to load the DEPS.""" |
481 assert self.hooks_ran == False | 503 assert self.hooks_ran == False |
482 if not self.should_process or self.recursion_limit() <= 0: | 504 if not self.should_process or not self.recursion_limit: |
483 # Don't run the hook when it is above recursion_limit. | 505 # Don't run the hook when it is above recursion_limit. |
484 return | 506 return |
485 # If "--force" was specified, run all hooks regardless of what files have | 507 # If "--force" was specified, run all hooks regardless of what files have |
486 # changed. | 508 # changed. |
487 if self.deps_hooks: | 509 if self.deps_hooks: |
488 # TODO(maruel): If the user is using git or git-svn, then we don't know | 510 # TODO(maruel): If the user is using git or git-svn, then we don't know |
489 # what files have changed so we always run all hooks. It'd be nice to fix | 511 # what files have changed so we always run all hooks. It'd be nice to fix |
490 # that. | 512 # that. |
491 if (options.force or | 513 if (options.force or |
492 isinstance(self.parsed_url, self.FileImpl) or | 514 isinstance(self.parsed_url, self.FileImpl) or |
493 gclient_scm.GetScmName(self.parsed_url) in ('git', None) or | 515 gclient_scm.GetScmName(self.parsed_url) in ('git', None) or |
494 os.path.isdir(os.path.join(self.root.root_dir, self.name, '.git'))): | 516 os.path.isdir(os.path.join(self.root.root_dir, self.name, '.git'))): |
495 for hook_dict in self.deps_hooks: | 517 for hook_dict in self.deps_hooks: |
496 self._RunHookAction(hook_dict, []) | 518 self._RunHookAction(hook_dict, []) |
497 else: | 519 else: |
498 # TODO(phajdan.jr): We should know exactly when the paths are absolute. | |
499 # Convert all absolute paths to relative. | |
500 file_list = self.file_list() | |
501 for i in range(len(file_list)): | |
502 # It depends on the command being executed (like runhooks vs sync). | |
503 if not os.path.isabs(file_list[i]): | |
504 continue | |
505 | |
506 prefix = os.path.commonprefix([self.root.root_dir.lower(), | |
507 file_list[i].lower()]) | |
508 file_list[i] = file_list[i][len(prefix):] | |
509 | |
510 # Strip any leading path separators. | |
511 while (file_list[i].startswith('\\') or | |
512 file_list[i].startswith('/')): | |
513 file_list[i] = file_list[i][1:] | |
514 | |
515 # Run hooks on the basis of whether the files from the gclient operation | 520 # Run hooks on the basis of whether the files from the gclient operation |
516 # match each hook's pattern. | 521 # match each hook's pattern. |
517 for hook_dict in self.deps_hooks: | 522 for hook_dict in self.deps_hooks: |
518 pattern = re.compile(hook_dict['pattern']) | 523 pattern = re.compile(hook_dict['pattern']) |
519 matching_file_list = [f for f in file_list if pattern.search(f)] | 524 matching_file_list = [f for f in self.file_list if pattern.search(f)] |
520 if matching_file_list: | 525 if matching_file_list: |
521 self._RunHookAction(hook_dict, matching_file_list) | 526 self._RunHookAction(hook_dict, matching_file_list) |
522 for s in self.dependencies: | 527 for s in self.dependencies: |
523 s.RunHooksRecursively(options) | 528 s.RunHooksRecursively(options) |
524 | 529 |
525 def _RunHookAction(self, hook_dict, matching_file_list): | 530 def _RunHookAction(self, hook_dict, matching_file_list): |
526 """Runs the action from a single hook.""" | 531 """Runs the action from a single hook.""" |
527 # A single DEPS file can specify multiple hooks so this function can be | 532 # A single DEPS file can specify multiple hooks so this function can be |
528 # called multiple times on a single Dependency. | 533 # called multiple times on a single Dependency. |
529 #assert self.hooks_ran == False | 534 #assert self.hooks_ran == False |
(...skipping 14 matching lines...) Expand all Loading... |
544 try: | 549 try: |
545 gclient_utils.CheckCallAndFilterAndHeader( | 550 gclient_utils.CheckCallAndFilterAndHeader( |
546 command, cwd=self.root.root_dir, always=True) | 551 command, cwd=self.root.root_dir, always=True) |
547 except (gclient_utils.Error, subprocess2.CalledProcessError), e: | 552 except (gclient_utils.Error, subprocess2.CalledProcessError), e: |
548 # Use a discrete exit status code of 2 to indicate that a hook action | 553 # Use a discrete exit status code of 2 to indicate that a hook action |
549 # failed. Users of this script may wish to treat hook action failures | 554 # failed. Users of this script may wish to treat hook action failures |
550 # differently from VC failures. | 555 # differently from VC failures. |
551 print >> sys.stderr, 'Error: %s' % str(e) | 556 print >> sys.stderr, 'Error: %s' % str(e) |
552 sys.exit(2) | 557 sys.exit(2) |
553 | 558 |
554 def recursion_limit(self): | |
555 return self.parent.recursion_limit() - 1 | |
556 | |
557 def tree(self, include_all): | |
558 return self.parent.tree(include_all) | |
559 | |
560 def subtree(self, include_all): | 559 def subtree(self, include_all): |
561 """Breadth first""" | 560 """Breadth first""" |
562 result = [] | 561 result = [] |
563 for d in self.dependencies: | 562 for d in self.dependencies: |
564 if d.should_process or include_all: | 563 if d.should_process or include_all: |
565 result.append(d) | 564 result.append(d) |
566 for d in self.dependencies: | 565 for d in self.dependencies: |
567 result.extend(d.subtree(include_all)) | 566 result.extend(d.subtree(include_all)) |
568 return result | 567 return result |
569 | 568 |
570 def get_custom_deps(self, name, url): | 569 def get_custom_deps(self, name, url): |
571 """Returns a custom deps if applicable.""" | 570 """Returns a custom deps if applicable.""" |
572 if self.parent: | 571 if self.parent: |
573 url = self.parent.get_custom_deps(name, url) | 572 url = self.parent.get_custom_deps(name, url) |
574 # None is a valid return value to disable a dependency. | 573 # None is a valid return value to disable a dependency. |
575 return self.custom_deps.get(name, url) | 574 return self.custom_deps.get(name, url) |
576 | 575 |
| 576 @property |
| 577 def recursion_limit(self): |
| 578 """Returns > 0 if this dependency is not too recursed to be processed.""" |
| 579 return max(self.parent.recursion_limit - 1, 0) |
| 580 |
| 581 @property |
| 582 def deps_file(self): |
| 583 return self._deps_file |
| 584 |
| 585 @property |
| 586 def safesync_url(self): |
| 587 return self._safesync_url |
| 588 |
| 589 @property |
| 590 def should_process(self): |
| 591 """True if this dependency should be processed, i.e. checked out.""" |
| 592 return self._should_process |
| 593 |
| 594 @property |
| 595 def parent(self): |
| 596 return self._parent |
| 597 |
| 598 @property |
577 def file_list(self): | 599 def file_list(self): |
578 result = self._file_list[:] | 600 result = self._file_list[:] |
579 for d in self.dependencies: | 601 for d in self.dependencies: |
580 result.extend(d.file_list()) | 602 result.extend(d.file_list) |
581 return result | 603 return tuple(result) |
582 | 604 |
583 def __str__(self): | 605 def __str__(self): |
584 out = [] | 606 out = [] |
585 for i in ('name', 'url', 'parsed_url', 'safesync_url', 'custom_deps', | 607 for i in ('name', 'url', 'parsed_url', 'safesync_url', 'custom_deps', |
586 'custom_vars', 'deps_hooks', 'file_list', 'should_process', | 608 'custom_vars', 'deps_hooks', 'file_list', 'should_process', |
587 'processed', 'hooks_ran', 'deps_parsed', 'requirements'): | 609 'processed', 'hooks_ran', 'deps_parsed', 'requirements'): |
588 # First try the native property if it exists. | 610 # First try the native property if it exists. |
589 if hasattr(self, '_' + i): | 611 if hasattr(self, '_' + i): |
590 value = getattr(self, '_' + i, False) | 612 value = getattr(self, '_' + i, False) |
591 else: | 613 else: |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
683 def SetConfig(self, content): | 705 def SetConfig(self, content): |
684 assert self.dependencies == [] | 706 assert self.dependencies == [] |
685 config_dict = {} | 707 config_dict = {} |
686 self.config_content = content | 708 self.config_content = content |
687 try: | 709 try: |
688 exec(content, config_dict) | 710 exec(content, config_dict) |
689 except SyntaxError, e: | 711 except SyntaxError, e: |
690 gclient_utils.SyntaxErrorToError('.gclient', e) | 712 gclient_utils.SyntaxErrorToError('.gclient', e) |
691 for s in config_dict.get('solutions', []): | 713 for s in config_dict.get('solutions', []): |
692 try: | 714 try: |
693 tree = dict((d.name, d) for d in self.tree(False)) | 715 tree = dict((d.name, d) for d in self.root.subtree(False)) |
694 if s['name'] in tree: | 716 if s['name'] in tree: |
695 raise gclient_utils.Error( | 717 raise gclient_utils.Error( |
696 'Dependency %s specified more than once in .gclient' % s['name']) | 718 'Dependency %s specified more than once in .gclient' % s['name']) |
697 self.dependencies.append(Dependency( | 719 self.dependencies.append(Dependency( |
698 self, s['name'], s['url'], | 720 self, s['name'], s['url'], |
699 s.get('safesync_url', None), | 721 s.get('safesync_url', None), |
700 s.get('custom_deps', {}), | 722 s.get('custom_deps', {}), |
701 s.get('custom_vars', {}), | 723 s.get('custom_vars', {}), |
702 s.get('deps_file', 'DEPS'), | 724 s.get('deps_file', 'DEPS'), |
703 True)) | 725 True)) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
735 }) | 757 }) |
736 | 758 |
737 def _SaveEntries(self): | 759 def _SaveEntries(self): |
738 """Creates a .gclient_entries file to record the list of unique checkouts. | 760 """Creates a .gclient_entries file to record the list of unique checkouts. |
739 | 761 |
740 The .gclient_entries file lives in the same directory as .gclient. | 762 The .gclient_entries file lives in the same directory as .gclient. |
741 """ | 763 """ |
742 # Sometimes pprint.pformat will use {', sometimes it'll use { ' ... It | 764 # Sometimes pprint.pformat will use {', sometimes it'll use { ' ... It |
743 # makes testing a bit too fun. | 765 # makes testing a bit too fun. |
744 result = 'entries = {\n' | 766 result = 'entries = {\n' |
745 for entry in self.tree(False): | 767 for entry in self.root.subtree(False): |
746 # Skip over File() dependencies as we can't version them. | 768 # Skip over File() dependencies as we can't version them. |
747 if not isinstance(entry.parsed_url, self.FileImpl): | 769 if not isinstance(entry.parsed_url, self.FileImpl): |
748 result += ' %s: %s,\n' % (pprint.pformat(entry.name), | 770 result += ' %s: %s,\n' % (pprint.pformat(entry.name), |
749 pprint.pformat(entry.parsed_url)) | 771 pprint.pformat(entry.parsed_url)) |
750 result += '}\n' | 772 result += '}\n' |
751 file_path = os.path.join(self.root_dir, self._options.entries_filename) | 773 file_path = os.path.join(self.root_dir, self._options.entries_filename) |
752 logging.info(result) | 774 logging.info(result) |
753 gclient_utils.FileWrite(file_path, result) | 775 gclient_utils.FileWrite(file_path, result) |
754 | 776 |
755 def _ReadEntries(self): | 777 def _ReadEntries(self): |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
824 | 846 |
825 # Once all the dependencies have been processed, it's now safe to run the | 847 # Once all the dependencies have been processed, it's now safe to run the |
826 # hooks. | 848 # hooks. |
827 if not self._options.nohooks: | 849 if not self._options.nohooks: |
828 self.RunHooksRecursively(self._options) | 850 self.RunHooksRecursively(self._options) |
829 | 851 |
830 if command == 'update': | 852 if command == 'update': |
831 # Notify the user if there is an orphaned entry in their working copy. | 853 # Notify the user if there is an orphaned entry in their working copy. |
832 # Only delete the directory if there are no changes in it, and | 854 # Only delete the directory if there are no changes in it, and |
833 # delete_unversioned_trees is set to true. | 855 # delete_unversioned_trees is set to true. |
834 entries = [i.name for i in self.tree(False) if i.url] | 856 entries = [i.name for i in self.root.subtree(False) if i.url] |
835 for entry, prev_url in self._ReadEntries().iteritems(): | 857 for entry, prev_url in self._ReadEntries().iteritems(): |
836 if not prev_url: | 858 if not prev_url: |
837 # entry must have been overridden via .gclient custom_deps | 859 # entry must have been overridden via .gclient custom_deps |
838 continue | 860 continue |
839 # Fix path separator on Windows. | 861 # Fix path separator on Windows. |
840 entry_fixed = entry.replace('/', os.path.sep) | 862 entry_fixed = entry.replace('/', os.path.sep) |
841 e_dir = os.path.join(self.root_dir, entry_fixed) | 863 e_dir = os.path.join(self.root_dir, entry_fixed) |
842 # Use entry and not entry_fixed there. | 864 # Use entry and not entry_fixed there. |
843 if entry not in entries and os.path.exists(e_dir): | 865 if entry not in entries and os.path.exists(e_dir): |
844 file_list = [] | 866 file_list = [] |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
906 'solution_name': d.name, | 928 'solution_name': d.name, |
907 'solution_url': d.url, | 929 'solution_url': d.url, |
908 'deps_file': d.deps_file, | 930 'deps_file': d.deps_file, |
909 'safesync_url' : d.safesync_url or '', | 931 'safesync_url' : d.safesync_url or '', |
910 'solution_deps': ''.join(custom_deps), | 932 'solution_deps': ''.join(custom_deps), |
911 } | 933 } |
912 # Print the snapshot configuration file | 934 # Print the snapshot configuration file |
913 print(self.DEFAULT_SNAPSHOT_FILE_TEXT % {'solution_list': new_gclient}) | 935 print(self.DEFAULT_SNAPSHOT_FILE_TEXT % {'solution_list': new_gclient}) |
914 else: | 936 else: |
915 entries = {} | 937 entries = {} |
916 for d in self.tree(False): | 938 for d in self.root.subtree(False): |
917 if self._options.actual: | 939 if self._options.actual: |
918 entries[d.name] = GetURLAndRev(d) | 940 entries[d.name] = GetURLAndRev(d) |
919 else: | 941 else: |
920 entries[d.name] = d.parsed_url | 942 entries[d.name] = d.parsed_url |
921 keys = sorted(entries.keys()) | 943 keys = sorted(entries.keys()) |
922 for x in keys: | 944 for x in keys: |
923 print('%s: %s' % (x, entries[x])) | 945 print('%s: %s' % (x, entries[x])) |
924 logging.info(str(self)) | 946 logging.info(str(self)) |
925 | 947 |
926 def ParseDepsFile(self): | 948 def ParseDepsFile(self): |
927 """No DEPS to parse for a .gclient file.""" | 949 """No DEPS to parse for a .gclient file.""" |
928 raise gclient_utils.Error('Internal error') | 950 raise gclient_utils.Error('Internal error') |
929 | 951 |
930 @property | 952 @property |
931 def root_dir(self): | 953 def root_dir(self): |
932 """Root directory of gclient checkout.""" | 954 """Root directory of gclient checkout.""" |
933 return self._root_dir | 955 return self._root_dir |
934 | 956 |
935 @property | 957 @property |
936 def enforced_os(self): | 958 def enforced_os(self): |
937 """What deps_os entries that are to be parsed.""" | 959 """What deps_os entries that are to be parsed.""" |
938 return self._enforced_os | 960 return self._enforced_os |
939 | 961 |
| 962 @property |
940 def recursion_limit(self): | 963 def recursion_limit(self): |
941 """How recursive can each dependencies in DEPS file can load DEPS file.""" | 964 """How recursive can each dependencies in DEPS file can load DEPS file.""" |
942 return self._recursion_limit | 965 return self._recursion_limit |
943 | 966 |
944 def tree(self, include_all): | |
945 """Returns a flat list of all the dependencies.""" | |
946 return self.subtree(include_all) | |
947 | |
948 | 967 |
949 #### gclient commands. | 968 #### gclient commands. |
950 | 969 |
951 | 970 |
952 def CMDcleanup(parser, args): | 971 def CMDcleanup(parser, args): |
953 """Cleans up all working copies. | 972 """Cleans up all working copies. |
954 | 973 |
955 Mostly svn-specific. Simply runs 'svn cleanup' for each module. | 974 Mostly svn-specific. Simply runs 'svn cleanup' for each module. |
956 """ | 975 """ |
957 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST', | 976 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST', |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1363 except (gclient_utils.Error, subprocess2.CalledProcessError), e: | 1382 except (gclient_utils.Error, subprocess2.CalledProcessError), e: |
1364 print >> sys.stderr, 'Error: %s' % str(e) | 1383 print >> sys.stderr, 'Error: %s' % str(e) |
1365 return 1 | 1384 return 1 |
1366 | 1385 |
1367 | 1386 |
1368 if '__main__' == __name__: | 1387 if '__main__' == __name__: |
1369 fix_encoding.fix_encoding() | 1388 fix_encoding.fix_encoding() |
1370 sys.exit(Main(sys.argv[1:])) | 1389 sys.exit(Main(sys.argv[1:])) |
1371 | 1390 |
1372 # vim: ts=2:sw=2:tw=80:et: | 1391 # vim: ts=2:sw=2:tw=80:et: |
OLD | NEW |