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 """Front end tool to manage .isolate files and corresponding tests. | 6 """Front end tool to manage .isolate files and corresponding tests. |
7 | 7 |
8 Run ./isolate.py --help for more detailed information. | 8 Run ./isolate.py --help for more detailed information. |
9 | 9 |
10 See more information at | 10 See more information at |
(...skipping 647 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
658 complete_state.root_dir, | 658 complete_state.root_dir, |
659 complete_state.saved_state.variables, | 659 complete_state.saved_state.variables, |
660 complete_state.result.relative_cwd) | 660 complete_state.result.relative_cwd) |
661 return value | 661 return value |
662 except trace_inputs.TracingFailure, e: | 662 except trace_inputs.TracingFailure, e: |
663 raise ExecutionError( | 663 raise ExecutionError( |
664 'Reading traces failed for: %s\n%s' % | 664 'Reading traces failed for: %s\n%s' % |
665 (' '.join(complete_state.result.command), str(e))) | 665 (' '.join(complete_state.result.command), str(e))) |
666 | 666 |
667 | 667 |
668 def merge(complete_state): | |
669 """Reads a trace and merges it back into the source .isolate file.""" | |
670 value = read(complete_state) | |
csharp
2012/09/06 12:59:37
Nit: what exactly does value contain? Is it a dict
M-A Ruel
2012/09/06 19:26:50
A dict, as the read() docstring says.
| |
671 | |
672 # Now take that data and union it into the original .isolate file. | |
673 with open(complete_state.saved_state.isolate_file, 'r') as f: | |
674 prev_content = f.read() | |
675 prev_config = merge_isolate.load_gyp( | |
676 merge_isolate.eval_content(prev_content), | |
677 merge_isolate.extract_comment(prev_content), | |
678 merge_isolate.DEFAULT_OSES) | |
679 new_config = merge_isolate.load_gyp( | |
680 value, | |
681 '', | |
682 merge_isolate.DEFAULT_OSES) | |
683 config = merge_isolate.union(prev_config, new_config) | |
684 # pylint: disable=E1103 | |
685 data = merge_isolate.convert_map_to_gyp( | |
686 *merge_isolate.reduce_inputs(*merge_isolate.invert_map(config.flatten()))) | |
687 print 'Updating %s' % complete_state.saved_state.isolate_file | |
688 with open(complete_state.saved_state.isolate_file, 'wb') as f: | |
689 merge_isolate.print_all(config.file_comment, data, f) | |
690 | |
691 | |
668 def CMDcheck(args): | 692 def CMDcheck(args): |
669 """Checks that all the inputs are present and update .result.""" | 693 """Checks that all the inputs are present and update .result.""" |
670 parser = OptionParserIsolate(command='check') | 694 parser = OptionParserIsolate(command='check') |
671 options, _ = parser.parse_args(args) | 695 options, _ = parser.parse_args(args) |
672 complete_state = load_complete_state(options, NO_INFO) | 696 complete_state = load_complete_state(options, NO_INFO) |
673 | 697 |
674 # Nothing is done specifically. Just store the result and state. | 698 # Nothing is done specifically. Just store the result and state. |
675 complete_state.save_files() | 699 complete_state.save_files() |
676 return 0 | 700 return 0 |
677 | 701 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
741 | 765 |
742 | 766 |
743 def CMDmerge(args): | 767 def CMDmerge(args): |
744 """Reads and merges the data from the trace back into the original .isolate. | 768 """Reads and merges the data from the trace back into the original .isolate. |
745 | 769 |
746 Ignores --outdir. | 770 Ignores --outdir. |
747 """ | 771 """ |
748 parser = OptionParserIsolate(command='merge', require_result=False) | 772 parser = OptionParserIsolate(command='merge', require_result=False) |
749 options, _ = parser.parse_args(args) | 773 options, _ = parser.parse_args(args) |
750 complete_state = load_complete_state(options, NO_INFO) | 774 complete_state = load_complete_state(options, NO_INFO) |
751 value = read(complete_state) | 775 merge(complete_state) |
752 | |
753 # Now take that data and union it into the original .isolate file. | |
754 with open(complete_state.saved_state.isolate_file, 'r') as f: | |
755 prev_content = f.read() | |
756 prev_config = merge_isolate.load_gyp( | |
757 merge_isolate.eval_content(prev_content), | |
758 merge_isolate.extract_comment(prev_content), | |
759 merge_isolate.DEFAULT_OSES) | |
760 new_config = merge_isolate.load_gyp( | |
761 value, | |
762 '', | |
763 merge_isolate.DEFAULT_OSES) | |
764 config = merge_isolate.union(prev_config, new_config) | |
765 # pylint: disable=E1103 | |
766 data = merge_isolate.convert_map_to_gyp( | |
767 *merge_isolate.reduce_inputs(*merge_isolate.invert_map(config.flatten()))) | |
768 print 'Updating %s' % complete_state.saved_state.isolate_file | |
769 with open(complete_state.saved_state.isolate_file, 'wb') as f: | |
770 merge_isolate.print_all(config.file_comment, data, f) | |
771 | |
772 return 0 | 776 return 0 |
773 | 777 |
774 | 778 |
775 def CMDread(args): | 779 def CMDread(args): |
776 """Reads the trace file generated with command 'trace'. | 780 """Reads the trace file generated with command 'trace'. |
777 | 781 |
778 Ignores --outdir. | 782 Ignores --outdir. |
779 """ | 783 """ |
780 parser = OptionParserIsolate(command='read', require_result=False) | 784 parser = OptionParserIsolate(command='read', require_result=False) |
781 options, _ = parser.parse_args(args) | 785 options, _ = parser.parse_args(args) |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
876 It runs the executable without remapping it, and traces all the files it and | 880 It runs the executable without remapping it, and traces all the files it and |
877 its child processes access. Then the 'read' command can be used to generate an | 881 its child processes access. Then the 'read' command can be used to generate an |
878 updated .isolate file out of it. | 882 updated .isolate file out of it. |
879 | 883 |
880 Argument processing stops at the first non-recognized argument and these | 884 Argument processing stops at the first non-recognized argument and these |
881 arguments are appended to the command line of the target to run. For example, | 885 arguments are appended to the command line of the target to run. For example, |
882 use: isolate.py -r foo.results -- --gtest_filter=Foo.Bar | 886 use: isolate.py -r foo.results -- --gtest_filter=Foo.Bar |
883 """ | 887 """ |
884 parser = OptionParserIsolate(command='trace') | 888 parser = OptionParserIsolate(command='trace') |
885 parser.enable_interspersed_args() | 889 parser.enable_interspersed_args() |
890 parser.add_option( | |
891 '-m', '--merge', action='store_true', | |
892 help='After tracing, merge the results back in the .isolate file') | |
886 options, args = parser.parse_args(args) | 893 options, args = parser.parse_args(args) |
887 complete_state = load_complete_state(options, STATS_ONLY) | 894 complete_state = load_complete_state(options, STATS_ONLY) |
888 cmd = complete_state.result.command + args | 895 cmd = complete_state.result.command + args |
889 if not cmd: | 896 if not cmd: |
890 raise ExecutionError('No command to run') | 897 raise ExecutionError('No command to run') |
891 cmd = trace_inputs.fix_python_path(cmd) | 898 cmd = trace_inputs.fix_python_path(cmd) |
892 cwd = os.path.normpath(os.path.join( | 899 cwd = os.path.normpath(os.path.join( |
893 complete_state.root_dir, complete_state.result.relative_cwd)) | 900 complete_state.root_dir, complete_state.result.relative_cwd)) |
894 logging.info('Running %s, cwd=%s' % (cmd, cwd)) | 901 logging.info('Running %s, cwd=%s' % (cmd, cwd)) |
895 api = trace_inputs.get_api() | 902 api = trace_inputs.get_api() |
896 logfile = complete_state.result_file + '.log' | 903 logfile = complete_state.result_file + '.log' |
897 api.clean_trace(logfile) | 904 api.clean_trace(logfile) |
898 try: | 905 try: |
899 with api.get_tracer(logfile) as tracer: | 906 with api.get_tracer(logfile) as tracer: |
900 result, _ = tracer.trace( | 907 result, _ = tracer.trace( |
901 cmd, | 908 cmd, |
902 cwd, | 909 cwd, |
903 'default', | 910 'default', |
904 True) | 911 True) |
905 except trace_inputs.TracingFailure, e: | 912 except trace_inputs.TracingFailure, e: |
906 raise ExecutionError('Tracing failed for: %s\n%s' % (' '.join(cmd), str(e))) | 913 raise ExecutionError('Tracing failed for: %s\n%s' % (' '.join(cmd), str(e))) |
907 | 914 |
908 complete_state.save_files() | 915 complete_state.save_files() |
916 | |
917 if options.merge: | |
918 merge(complete_state) | |
919 | |
909 return result | 920 return result |
910 | 921 |
911 | 922 |
912 class OptionParserWithNiceDescription(optparse.OptionParser): | 923 class OptionParserWithNiceDescription(optparse.OptionParser): |
913 """Generates the description with the command's docstring.""" | 924 """Generates the description with the command's docstring.""" |
914 def __init__(self, *args, **kwargs): | 925 def __init__(self, *args, **kwargs): |
915 """Sets 'description' and 'usage' if not already specified.""" | 926 """Sets 'description' and 'usage' if not already specified.""" |
916 command = kwargs.pop('command', None) | 927 command = kwargs.pop('command', None) |
917 if not 'description' in kwargs: | 928 if not 'description' in kwargs: |
918 kwargs['description'] = re.sub( | 929 kwargs['description'] = re.sub( |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1066 return command(argv[1:]) | 1077 return command(argv[1:]) |
1067 except (ExecutionError, run_test_from_archive.MappingError), e: | 1078 except (ExecutionError, run_test_from_archive.MappingError), e: |
1068 sys.stderr.write('\nError: ') | 1079 sys.stderr.write('\nError: ') |
1069 sys.stderr.write(str(e)) | 1080 sys.stderr.write(str(e)) |
1070 sys.stderr.write('\n') | 1081 sys.stderr.write('\n') |
1071 return 1 | 1082 return 1 |
1072 | 1083 |
1073 | 1084 |
1074 if __name__ == '__main__': | 1085 if __name__ == '__main__': |
1075 sys.exit(main(sys.argv[1:])) | 1086 sys.exit(main(sys.argv[1:])) |
OLD | NEW |