OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <sstream> | 5 #include <sstream> |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
9 #include "base/strings/string_split.h" | 9 #include "base/strings/string_split.h" |
10 #include "tools/gn/commands.h" | 10 #include "tools/gn/commands.h" |
11 #include "tools/gn/filesystem_utils.h" | 11 #include "tools/gn/filesystem_utils.h" |
12 #include "tools/gn/input_file.h" | 12 #include "tools/gn/input_file.h" |
13 #include "tools/gn/parser.h" | 13 #include "tools/gn/parser.h" |
14 #include "tools/gn/scheduler.h" | 14 #include "tools/gn/scheduler.h" |
15 #include "tools/gn/setup.h" | 15 #include "tools/gn/setup.h" |
16 #include "tools/gn/source_file.h" | 16 #include "tools/gn/source_file.h" |
17 #include "tools/gn/tokenizer.h" | 17 #include "tools/gn/tokenizer.h" |
18 | 18 |
19 namespace commands { | 19 namespace commands { |
20 | 20 |
| 21 const char kSwitchDryRun[] = "dry-run"; |
21 const char kSwitchDumpTree[] = "dump-tree"; | 22 const char kSwitchDumpTree[] = "dump-tree"; |
22 const char kSwitchInPlace[] = "in-place"; | 23 const char kSwitchInPlace[] = "in-place"; |
23 const char kSwitchStdin[] = "stdin"; | 24 const char kSwitchStdin[] = "stdin"; |
24 | 25 |
25 const char kFormat[] = "format"; | 26 const char kFormat[] = "format"; |
26 const char kFormat_HelpShort[] = | 27 const char kFormat_HelpShort[] = |
27 "format: Format .gn file."; | 28 "format: Format .gn file."; |
28 const char kFormat_Help[] = | 29 const char kFormat_Help[] = |
29 "gn format [--dump-tree] [--in-place] [--stdin] BUILD.gn\n" | 30 "gn format [--dump-tree] [--in-place] [--stdin] BUILD.gn\n" |
30 "\n" | 31 "\n" |
31 " Formats .gn file to a standard format.\n" | 32 " Formats .gn file to a standard format.\n" |
32 "\n" | 33 "\n" |
33 "Arguments\n" | 34 "Arguments\n" |
| 35 " --dry-run\n" |
| 36 " Does not change or output anything, but sets the process exit code\n" |
| 37 " based on whether output would be different than what's on disk.\n" |
| 38 " This is useful for presubmit/lint-type checks.\n" |
| 39 " - Exit code 0: successful format, matches on disk.\n" |
| 40 " - Exit code 1: general failure (parse error, etc.)\n" |
| 41 " - Exit code 2: successful format, but differs from on disk.\n" |
| 42 "\n" |
34 " --dump-tree\n" | 43 " --dump-tree\n" |
35 " For debugging only, dumps the parse tree.\n" | 44 " For debugging only, dumps the parse tree.\n" |
36 "\n" | 45 "\n" |
37 " --in-place\n" | 46 " --in-place\n" |
38 " Instead of writing the formatted file to stdout, replace the input\n" | 47 " Instead of writing the formatted file to stdout, replace the input\n" |
39 " file with the formatted output. If no reformatting is required,\n" | 48 " file with the formatted output. If no reformatting is required,\n" |
40 " the input file will not be touched, and nothing printed.\n" | 49 " the input file will not be touched, and nothing printed.\n" |
41 "\n" | 50 "\n" |
42 " --stdin\n" | 51 " --stdin\n" |
43 " Read input from stdin (and write to stdout). Not compatible with\n" | 52 " Read input from stdin (and write to stdout). Not compatible with\n" |
(...skipping 893 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
937 if (err.has_error()) { | 946 if (err.has_error()) { |
938 err.PrintToStdout(); | 947 err.PrintToStdout(); |
939 return false; | 948 return false; |
940 } | 949 } |
941 | 950 |
942 DoFormat(parse_node.get(), dump_tree, output); | 951 DoFormat(parse_node.get(), dump_tree, output); |
943 return true; | 952 return true; |
944 } | 953 } |
945 | 954 |
946 int RunFormat(const std::vector<std::string>& args) { | 955 int RunFormat(const std::vector<std::string>& args) { |
| 956 bool dry_run = |
| 957 base::CommandLine::ForCurrentProcess()->HasSwitch(kSwitchDryRun); |
947 bool dump_tree = | 958 bool dump_tree = |
948 base::CommandLine::ForCurrentProcess()->HasSwitch(kSwitchDumpTree); | 959 base::CommandLine::ForCurrentProcess()->HasSwitch(kSwitchDumpTree); |
949 | |
950 bool from_stdin = | 960 bool from_stdin = |
951 base::CommandLine::ForCurrentProcess()->HasSwitch(kSwitchStdin); | 961 base::CommandLine::ForCurrentProcess()->HasSwitch(kSwitchStdin); |
| 962 bool in_place = |
| 963 base::CommandLine::ForCurrentProcess()->HasSwitch(kSwitchInPlace); |
| 964 |
| 965 if (dry_run) { |
| 966 // --dry-run only works with an actual file to compare to. |
| 967 from_stdin = false; |
| 968 in_place = true; |
| 969 } |
952 | 970 |
953 if (from_stdin) { | 971 if (from_stdin) { |
954 if (args.size() != 0) { | 972 if (args.size() != 0) { |
955 Err(Location(), "Expecting no arguments when reading from stdin.\n") | 973 Err(Location(), "Expecting no arguments when reading from stdin.\n") |
956 .PrintToStdout(); | 974 .PrintToStdout(); |
957 return 1; | 975 return 1; |
958 } | 976 } |
959 std::string input = ReadStdin(); | 977 std::string input = ReadStdin(); |
960 std::string output; | 978 std::string output; |
961 if (!FormatStringToString(input, dump_tree, &output)) | 979 if (!FormatStringToString(input, dump_tree, &output)) |
(...skipping 10 matching lines...) Expand all Loading... |
972 return 1; | 990 return 1; |
973 } | 991 } |
974 | 992 |
975 Setup setup; | 993 Setup setup; |
976 SourceDir source_dir = | 994 SourceDir source_dir = |
977 SourceDirForCurrentDirectory(setup.build_settings().root_path()); | 995 SourceDirForCurrentDirectory(setup.build_settings().root_path()); |
978 SourceFile file = source_dir.ResolveRelativeFile(args[0]); | 996 SourceFile file = source_dir.ResolveRelativeFile(args[0]); |
979 | 997 |
980 std::string output_string; | 998 std::string output_string; |
981 if (FormatFileToString(&setup, file, dump_tree, &output_string)) { | 999 if (FormatFileToString(&setup, file, dump_tree, &output_string)) { |
982 bool in_place = | |
983 base::CommandLine::ForCurrentProcess()->HasSwitch(kSwitchInPlace); | |
984 if (in_place) { | 1000 if (in_place) { |
985 base::FilePath to_write = setup.build_settings().GetFullPath(file); | 1001 base::FilePath to_write = setup.build_settings().GetFullPath(file); |
986 std::string original_contents; | 1002 std::string original_contents; |
987 if (!base::ReadFileToString(to_write, &original_contents)) { | 1003 if (!base::ReadFileToString(to_write, &original_contents)) { |
988 Err(Location(), std::string("Couldn't read \"") + | 1004 Err(Location(), std::string("Couldn't read \"") + |
989 to_write.AsUTF8Unsafe() + | 1005 to_write.AsUTF8Unsafe() + |
990 std::string("\" for comparison.")).PrintToStdout(); | 1006 std::string("\" for comparison.")).PrintToStdout(); |
991 return 1; | 1007 return 1; |
992 } | 1008 } |
| 1009 if (dry_run) |
| 1010 return original_contents == output_string ? 0 : 2; |
993 if (original_contents != output_string) { | 1011 if (original_contents != output_string) { |
994 if (base::WriteFile(to_write, | 1012 if (base::WriteFile(to_write, |
995 output_string.data(), | 1013 output_string.data(), |
996 static_cast<int>(output_string.size())) == -1) { | 1014 static_cast<int>(output_string.size())) == -1) { |
997 Err(Location(), | 1015 Err(Location(), |
998 std::string("Failed to write formatted output back to \"") + | 1016 std::string("Failed to write formatted output back to \"") + |
999 to_write.AsUTF8Unsafe() + std::string("\".")).PrintToStdout(); | 1017 to_write.AsUTF8Unsafe() + std::string("\".")).PrintToStdout(); |
1000 return 1; | 1018 return 1; |
1001 } | 1019 } |
1002 printf("Wrote formatted to '%s'.\n", to_write.AsUTF8Unsafe().c_str()); | 1020 printf("Wrote formatted to '%s'.\n", to_write.AsUTF8Unsafe().c_str()); |
1003 } | 1021 } |
1004 } else { | 1022 } else { |
1005 printf("%s", output_string.c_str()); | 1023 printf("%s", output_string.c_str()); |
1006 } | 1024 } |
1007 } | 1025 } |
1008 | 1026 |
1009 return 0; | 1027 return 0; |
1010 } | 1028 } |
1011 | 1029 |
1012 } // namespace commands | 1030 } // namespace commands |
OLD | NEW |