OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 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 567 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
578 for s in self.dependencies: | 578 for s in self.dependencies: |
579 work_queue.enqueue(s) | 579 work_queue.enqueue(s) |
580 | 580 |
581 @gclient_utils.lockedmethod | 581 @gclient_utils.lockedmethod |
582 def _run_is_done(self, file_list, parsed_url): | 582 def _run_is_done(self, file_list, parsed_url): |
583 # Both these are kept for hooks that are run as a separate tree traversal. | 583 # Both these are kept for hooks that are run as a separate tree traversal. |
584 self._file_list = file_list | 584 self._file_list = file_list |
585 self._parsed_url = parsed_url | 585 self._parsed_url = parsed_url |
586 self._processed = True | 586 self._processed = True |
587 | 587 |
588 def RunHooksRecursively(self, options): | 588 @staticmethod |
589 """Evaluates all hooks, running actions as needed. run() | 589 def GetHookAction(hook_dict, matching_file_list): |
590 must have been called before to load the DEPS.""" | 590 """Turn a parsed 'hook' dict into an executable command.""" |
591 assert self.hooks_ran == False | 591 logging.debug(hook_dict) |
M-A Ruel
2012/01/31 01:15:25
FTR, you'll have to remove these before committing
szager
2012/01/31 06:47:39
I don't mind removing them (done), but why? These
M-A Ruel
2012/01/31 15:18:33
I'm stupid. You can add these back.
| |
592 logging.debug(matching_file_list) | |
593 command = hook_dict['action'][:] | |
594 if command[0] == 'python': | |
595 # If the hook specified "python" as the first item, the action is a | |
596 # Python script. Run it by starting a new copy of the same | |
597 # interpreter. | |
598 command[0] = sys.executable | |
599 if '$matching_files' in command: | |
600 splice_index = command.index('$matching_files') | |
601 command[splice_index:splice_index + 1] = matching_file_list | |
602 return command | |
603 | |
604 def GetHooks(self, options, result=None): | |
M-A Ruel
2012/01/31 01:15:25
I think it'd be simpler if you simply returned the
szager
2012/01/31 06:47:39
Done.
| |
605 """Evaluate all hooks, and return them in a flat list. | |
606 | |
607 run() must have been called before to load the DEPS. | |
608 """ | |
609 result = [] if result is None else result | |
M-A Ruel
2012/01/31 01:15:25
result = result or []
?
szager
2012/01/31 06:47:39
Obsolete now.
| |
592 if not self.should_process or not self.recursion_limit: | 610 if not self.should_process or not self.recursion_limit: |
593 # Don't run the hook when it is above recursion_limit. | 611 # Don't run the hook when it is above recursion_limit. |
594 return | 612 return |
595 # If "--force" was specified, run all hooks regardless of what files have | 613 # If "--force" was specified, run all hooks regardless of what files have |
596 # changed. | 614 # changed. |
597 if self.deps_hooks: | 615 if self.deps_hooks: |
598 # TODO(maruel): If the user is using git or git-svn, then we don't know | 616 # TODO(maruel): If the user is using git or git-svn, then we don't know |
599 # what files have changed so we always run all hooks. It'd be nice to fix | 617 # what files have changed so we always run all hooks. It'd be nice to fix |
600 # that. | 618 # that. |
601 if (options.force or | 619 if (options.force or |
602 isinstance(self.parsed_url, self.FileImpl) or | 620 isinstance(self.parsed_url, self.FileImpl) or |
603 gclient_scm.GetScmName(self.parsed_url) in ('git', None) or | 621 gclient_scm.GetScmName(self.parsed_url) in ('git', None) or |
604 os.path.isdir(os.path.join(self.root.root_dir, self.name, '.git'))): | 622 os.path.isdir(os.path.join(self.root.root_dir, self.name, '.git'))): |
605 for hook_dict in self.deps_hooks: | 623 for hook_dict in self.deps_hooks: |
606 self._RunHookAction(hook_dict, []) | 624 result.append(self.GetHookAction(hook_dict, [])) |
607 else: | 625 else: |
608 # Run hooks on the basis of whether the files from the gclient operation | 626 # Run hooks on the basis of whether the files from the gclient operation |
609 # match each hook's pattern. | 627 # match each hook's pattern. |
610 for hook_dict in self.deps_hooks: | 628 for hook_dict in self.deps_hooks: |
611 pattern = re.compile(hook_dict['pattern']) | 629 pattern = re.compile(hook_dict['pattern']) |
612 matching_file_list = [ | 630 matching_file_list = [ |
613 f for f in self.file_list_and_children if pattern.search(f) | 631 f for f in self.file_list_and_children if pattern.search(f) |
614 ] | 632 ] |
615 if matching_file_list: | 633 if matching_file_list: |
616 self._RunHookAction(hook_dict, matching_file_list) | 634 result.append(self.GetHookAction(hook_dict, matching_file_list)) |
617 for s in self.dependencies: | 635 for s in self.dependencies: |
618 s.RunHooksRecursively(options) | 636 s.GetHooks(options, result) |
637 return result | |
619 | 638 |
620 def _RunHookAction(self, hook_dict, matching_file_list): | 639 def RunHooksRecursively(self, options): |
621 """Runs the action from a single hook.""" | 640 assert self.hooks_ran == False |
622 # A single DEPS file can specify multiple hooks so this function can be | |
623 # called multiple times on a single Dependency. | |
624 #assert self.hooks_ran == False | |
625 self._hooks_ran = True | 641 self._hooks_ran = True |
626 logging.debug(hook_dict) | 642 for hook in self.GetHooks(options): |
627 logging.debug(matching_file_list) | 643 try: |
628 command = hook_dict['action'][:] | 644 gclient_utils.CheckCallAndFilterAndHeader( |
629 if command[0] == 'python': | 645 hook, cwd=self.root.root_dir, always=True) |
630 # If the hook specified "python" as the first item, the action is a | 646 except (gclient_utils.Error, subprocess2.CalledProcessError), e: |
631 # Python script. Run it by starting a new copy of the same | 647 # Use a discrete exit status code of 2 to indicate that a hook action |
632 # interpreter. | 648 # failed. Users of this script may wish to treat hook action failures |
633 command[0] = sys.executable | 649 # differently from VC failures. |
634 | 650 print >> sys.stderr, 'Error: %s' % str(e) |
635 if '$matching_files' in command: | 651 sys.exit(2) |
636 splice_index = command.index('$matching_files') | |
637 command[splice_index:splice_index + 1] = matching_file_list | |
638 | |
639 try: | |
640 gclient_utils.CheckCallAndFilterAndHeader( | |
641 command, cwd=self.root.root_dir, always=True) | |
642 except (gclient_utils.Error, subprocess2.CalledProcessError), e: | |
643 # Use a discrete exit status code of 2 to indicate that a hook action | |
644 # failed. Users of this script may wish to treat hook action failures | |
645 # differently from VC failures. | |
646 print >> sys.stderr, 'Error: %s' % str(e) | |
647 sys.exit(2) | |
648 | 652 |
649 def subtree(self, include_all): | 653 def subtree(self, include_all): |
650 """Breadth first recursion excluding root node.""" | 654 """Breadth first recursion excluding root node.""" |
651 dependencies = self.dependencies | 655 dependencies = self.dependencies |
652 for d in dependencies: | 656 for d in dependencies: |
653 if d.should_process or include_all: | 657 if d.should_process or include_all: |
654 yield d | 658 yield d |
655 for d in dependencies: | 659 for d in dependencies: |
656 for i in d.subtree(include_all): | 660 for i in d.subtree(include_all): |
657 yield i | 661 yield i |
(...skipping 758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1416 'version of all repositories to reproduce the tree, ' | 1420 'version of all repositories to reproduce the tree, ' |
1417 'implies -a') | 1421 'implies -a') |
1418 (options, args) = parser.parse_args(args) | 1422 (options, args) = parser.parse_args(args) |
1419 client = GClient.LoadCurrentConfig(options) | 1423 client = GClient.LoadCurrentConfig(options) |
1420 if not client: | 1424 if not client: |
1421 raise gclient_utils.Error('client not configured; see \'gclient config\'') | 1425 raise gclient_utils.Error('client not configured; see \'gclient config\'') |
1422 client.PrintRevInfo() | 1426 client.PrintRevInfo() |
1423 return 0 | 1427 return 0 |
1424 | 1428 |
1425 | 1429 |
1430 def CMDhookinfo(parser, args): | |
1431 """Output the hooks that would be run by `gclient runhooks`""" | |
1432 (options, args) = parser.parse_args(args) | |
1433 client = GClient.LoadCurrentConfig(options) | |
1434 if not client: | |
1435 raise gclient_utils.Error('client not configured; see \'gclient config\'') | |
1436 work_queue = gclient_utils.ExecutionQueue(options.jobs, None) | |
1437 for s in client.dependencies: | |
1438 work_queue.enqueue(s) | |
1439 work_queue.flush({}, None, [], options=options) | |
1440 print client.GetHooks(options) | |
M-A Ruel
2012/01/31 01:15:25
for hook in client.GetHooks(options):
print ' '.
szager
2012/01/31 06:47:39
I'd like the output to be parse-able by python, so
| |
1441 return 0 | |
1442 | |
1443 | |
1426 def Command(name): | 1444 def Command(name): |
1427 return getattr(sys.modules[__name__], 'CMD' + name, None) | 1445 return getattr(sys.modules[__name__], 'CMD' + name, None) |
1428 | 1446 |
1429 | 1447 |
1430 def CMDhelp(parser, args): | 1448 def CMDhelp(parser, args): |
1431 """Prints list of commands or help for a specific command.""" | 1449 """Prints list of commands or help for a specific command.""" |
1432 (_, args) = parser.parse_args(args) | 1450 (_, args) = parser.parse_args(args) |
1433 if len(args) == 1: | 1451 if len(args) == 1: |
1434 return Main(args + ['--help']) | 1452 return Main(args + ['--help']) |
1435 parser.print_help() | 1453 parser.print_help() |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1532 except (gclient_utils.Error, subprocess2.CalledProcessError), e: | 1550 except (gclient_utils.Error, subprocess2.CalledProcessError), e: |
1533 print >> sys.stderr, 'Error: %s' % str(e) | 1551 print >> sys.stderr, 'Error: %s' % str(e) |
1534 return 1 | 1552 return 1 |
1535 | 1553 |
1536 | 1554 |
1537 if '__main__' == __name__: | 1555 if '__main__' == __name__: |
1538 fix_encoding.fix_encoding() | 1556 fix_encoding.fix_encoding() |
1539 sys.exit(Main(sys.argv[1:])) | 1557 sys.exit(Main(sys.argv[1:])) |
1540 | 1558 |
1541 # vim: ts=2:sw=2:tw=80:et: | 1559 # vim: ts=2:sw=2:tw=80:et: |
OLD | NEW |