[rust] [depot_tools] Minimal `rustfmt` support for `git cl format`.
This CL provides minimal `git cl format` support to enforce correct Rust
formatting in presubmit checks. For now the files are always fully
formatted - there is no support at this point for formatting only the
changed lines.
Manual tests (after temporarily, artificially introducing a formatting
error to one of .rs files under build/rest/tests):
*) git cl presubmit
Result: The src directory requires source formatting.
Please run: git cl format
*) git cl format --dry-run
Result: Pretty/colorful diff printed out.
*) git cl format
Result: Temporary formatting errors are fixed.
Bug: chromium:1231317
Change-Id: I114ece90630476f27871ebcd170162caa92c0871
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/3054980
Commit-Queue: Ćukasz Anforowicz <lukasza@chromium.org>
Reviewed-by: Adrian Taylor <adetaylor@chromium.org>
Reviewed-by: Dirk Pranke <dpranke@google.com>
Reviewed-by: danakj <danakj@chromium.org>
diff --git a/git_cl.py b/git_cl.py
index a87519a..268ff77 100755
--- a/git_cl.py
+++ b/git_cl.py
@@ -46,6 +46,7 @@
import owners_finder
import presubmit_canned_checks
import presubmit_support
+import rustfmt
import scm
import setup_color
import split_cl
@@ -5065,6 +5066,34 @@
return return_value
+def _RunRustFmt(opts, rust_diff_files, top_dir, upstream_commit):
+ """Runs rustfmt. Just like _RunClangFormatDiff returns 2 to indicate that
+ presubmit checks have failed (and returns 0 otherwise)."""
+
+ if not rust_diff_files:
+ return 0
+
+ # Locate the rustfmt binary.
+ try:
+ rustfmt_tool = rustfmt.FindRustfmtToolInChromiumTree()
+ except rustfmt.NotFoundError as e:
+ DieWithError(e)
+
+ # TODO(crbug.com/1231317): Support formatting only the changed lines
+ # if `opts.full or settings.GetFormatFullByDefault()` is False. See also:
+ # https://github.com/emilio/rustfmt-format-diff
+ cmd = [rustfmt_tool]
+ if opts.dry_run:
+ cmd.append('--check')
+ cmd += rust_diff_files
+ rustfmt_exitcode = subprocess2.call(cmd)
+
+ if opts.presubmit and rustfmt_exitcode != 0:
+ return 2
+ else:
+ return 0
+
+
def MatchingFileType(file_name, extensions):
"""Returns True if the file name ends with one of the given extensions."""
return bool([ext for ext in extensions if file_name.lower().endswith(ext)])
@@ -5076,6 +5105,7 @@
"""Runs auto-formatting tools (clang-format etc.) on the diff."""
CLANG_EXTS = ['.cc', '.cpp', '.h', '.m', '.mm', '.proto', '.java']
GN_EXTS = ['.gn', '.gni', '.typemap']
+ RUST_EXTS = ['.rs']
parser.add_option('--full', action='store_true',
help='Reformat the full content of all touched files')
parser.add_option('--upstream', help='Branch to check against')
@@ -5109,6 +5139,18 @@
help='Print diff to stdout rather than modifying files.')
parser.add_option('--presubmit', action='store_true',
help='Used when running the script from a presubmit.')
+
+ parser.add_option('--rust-fmt',
+ dest='use_rust_fmt',
+ action='store_true',
+ default=rustfmt.IsRustfmtSupported(),
+ help='Enables formatting of Rust file types using rustfmt.')
+ parser.add_option(
+ '--no-rust-fmt',
+ dest='use_rust_fmt',
+ action='store_false',
+ help='Disables formatting of Rust file types using rustfmt.')
+
opts, args = parser.parse_args(args)
if opts.python is not None and opts.no_python:
@@ -5158,6 +5200,7 @@
x for x in diff_files if MatchingFileType(x, CLANG_EXTS)
]
python_diff_files = [x for x in diff_files if MatchingFileType(x, ['.py'])]
+ rust_diff_files = [x for x in diff_files if MatchingFileType(x, RUST_EXTS)]
gn_diff_files = [x for x in diff_files if MatchingFileType(x, GN_EXTS)]
top_dir = settings.GetRoot()
@@ -5165,6 +5208,12 @@
return_value = _RunClangFormatDiff(opts, clang_diff_files, top_dir,
upstream_commit)
+ if opts.use_rust_fmt:
+ rust_fmt_return_value = _RunRustFmt(opts, rust_diff_files, top_dir,
+ upstream_commit)
+ if rust_fmt_return_value == 2:
+ return_value = 2
+
# Similar code to above, but using yapf on .py files rather than clang-format
# on C/C++ files
py_explicitly_disabled = opts.python is not None and not opts.python