|
#!/usr/bin/env python |
|
# Copyright 2016 The Fuchsia Authors. All rights reserved. |
|
# Use of this source code is governed by a BSD-style license that can be |
|
# found in the LICENSE file. |
|
"""Runs source formatters on modified files. |
|
|
|
In order to find the files to be formatted, this uses `git diff-index` against |
|
the newest parent commit in the upstream branch (or against HEAD if there is no |
|
upstream branch). In result, files that are locally modified, staged or touched |
|
by any commits introduced on the local branch are formatted. |
|
""" |
|
|
|
import argparse |
|
import os |
|
import platform |
|
import subprocess |
|
import sys |
|
import git_utils |
|
import paths |
|
|
|
clang_platform = "%s-%s" % ( |
|
platform.system().lower().replace("darwin", "mac"), |
|
{ |
|
"x86_64": "x64", |
|
"aarch64": "arm64", |
|
}[platform.machine()], |
|
) |
|
CLANG_TOOL = os.path.join(paths.BUILDTOOLS_ROOT, clang_platform, "clang", "bin", |
|
"clang-format") |
|
DART_TOOL = os.path.join(paths.DART_ROOT, "bin", "dartfmt") |
|
GN_TOOL = os.path.join(paths.BUILDTOOLS_ROOT, "gn") |
|
gotoolos = "linux64" |
|
if platform.platform().startswith("Darwin"): |
|
gotoolos = "mac" |
|
GO_TOOL = os.path.join(paths.BUILDTOOLS_ROOT, gotoolos, "go", "bin", "gofmt") |
|
CHECK_HEADER_GUARDS_TOOL = os.path.join(paths.FUCHSIA_ROOT, "scripts", "style", |
|
"check-header-guards.py") |
|
|
|
C_CMD = [ |
|
CLANG_TOOL, "-style=file", "-fallback-style=Chromium", "-sort-includes", |
|
"-i" |
|
] |
|
DART_CMD = [DART_TOOL, "-w"] |
|
GN_CMD = [GN_TOOL, "format"] |
|
GO_CMD = [GO_TOOL, "-w"] |
|
FIX_HEADER_GUARDS_COMMAND = [CHECK_HEADER_GUARDS_TOOL, "--fix"] |
|
|
|
EXT_TO_COMMANDS = { |
|
".cc": [C_CMD], |
|
".cpp": [C_CMD], |
|
".dart": [DART_CMD], |
|
".gn": [GN_CMD], |
|
".gni": [GN_CMD], |
|
".go": [GO_CMD], |
|
".h": [FIX_HEADER_GUARDS_COMMAND, C_CMD], |
|
".hh": [C_CMD], |
|
".hpp": [C_CMD], |
|
} |
|
|
|
|
|
def main(): |
|
parser = argparse.ArgumentParser(description="Format modified files.") |
|
parser.add_argument( |
|
"--dry-run", |
|
dest="dry_run", |
|
action="store_true", |
|
default=False, |
|
help="just pretend to run stuff") |
|
parser.add_argument( |
|
"--verbose", |
|
dest="verbose", |
|
action="store_true", |
|
default=False, |
|
help="tell me what you're doing") |
|
parser.add_argument( |
|
"--all", |
|
dest="all", |
|
action="store_true", |
|
default=False, |
|
help="format all files in the repo, not just the modified ones") |
|
args = parser.parse_args() |
|
|
|
# Find the files to be formatted. |
|
if args.all: |
|
files = git_utils.get_all_files() |
|
else: |
|
files = git_utils.get_diff_files() |
|
|
|
if args.verbose: |
|
print |
|
print "Files to be formatted:" |
|
if not files: |
|
print " (no files)" |
|
return |
|
|
|
for file in files: |
|
print " - " + file |
|
|
|
# Run the formatters. |
|
if args.dry_run: |
|
print |
|
print "Would run the following formatters (dry run):" |
|
elif args.verbose: |
|
print "Running the following formatters:" |
|
|
|
count = 0 |
|
|
|
for file in files: |
|
# Skip deleted files. |
|
if not os.path.isfile(file): |
|
continue |
|
|
|
_, extension = os.path.splitext(file) |
|
if extension not in EXT_TO_COMMANDS: |
|
continue |
|
|
|
count += 1 |
|
cmds = EXT_TO_COMMANDS[extension] |
|
for cmd in cmds: |
|
cmd = cmd + [file] |
|
if args.dry_run or args.verbose: |
|
print cmd |
|
|
|
if args.dry_run: |
|
continue |
|
|
|
try: |
|
subprocess.check_call(cmd) |
|
except Exception as e: |
|
print " ".join(cmd) + " failed" |
|
raise e |
|
|
|
if (args.dry_run or args.verbose) and not count: |
|
print " (none)" |
|
return 0 |
|
|
|
|
|
if __name__ == "__main__": |
|
sys.exit(main()) |