mirror of https://github.com/mongodb/mongo
135 lines
4.9 KiB
Python
135 lines
4.9 KiB
Python
import argparse
|
|
import json
|
|
import os
|
|
import pathlib
|
|
import platform
|
|
import subprocess
|
|
|
|
from simple_report import put_report, try_combine_reports, make_report
|
|
|
|
mongo_dir = pathlib.Path(__file__).parents[1]
|
|
|
|
|
|
def find_all_failed(bin_path: str) -> list[str]:
|
|
# TODO(SERVER-81039): Remove once third_party libs can be compiled from the root directory.
|
|
ignored_paths = []
|
|
with open(os.path.join(mongo_dir, ".bazelignore"), "r") as file:
|
|
for line in file.readlines():
|
|
contents = line.split("#")[0].strip()
|
|
if contents:
|
|
ignored_paths.append(contents)
|
|
|
|
process = subprocess.run([bin_path, "--format=json", "--mode=check", "-r", "./"], check=True,
|
|
capture_output=True)
|
|
buildifier_results = json.loads(process.stdout)
|
|
if buildifier_results["success"]:
|
|
return []
|
|
|
|
return [
|
|
result["filename"] for result in buildifier_results["files"]
|
|
if (not result["formatted"] and \
|
|
not any(result["filename"].startswith(ignored_path) for ignored_path in ignored_paths))
|
|
]
|
|
|
|
|
|
def lint_all(bin_path: str, generate_report: bool):
|
|
files = find_all_failed(bin_path)
|
|
lint(bin_path, files, generate_report)
|
|
|
|
|
|
def fix_all(bin_path: str):
|
|
files = find_all_failed(bin_path)
|
|
fix(bin_path, files)
|
|
|
|
|
|
def lint(bin_path: str, files: list[str], generate_report: bool):
|
|
for file in files:
|
|
process = subprocess.run([bin_path, "--format=json", "--mode=check", file], check=True,
|
|
capture_output=True)
|
|
result = json.loads(process.stdout)
|
|
if result["success"]:
|
|
continue
|
|
# This purposefully gives a exit code of 4 when there is a diff
|
|
process = subprocess.run([bin_path, "--mode=diff", file], capture_output=True,
|
|
encoding='utf-8')
|
|
if process.returncode not in (0, 4):
|
|
raise RuntimeError()
|
|
diff = process.stdout
|
|
print(f"{file} has linting errors")
|
|
print(diff)
|
|
|
|
if generate_report:
|
|
header = (
|
|
"There are linting errors in this file, fix them with one of the following commands:\n"
|
|
"python3 buildscripts/buildifier.py fix-all\n"
|
|
f"python3 buildscripts/buildifier.py fix {file}\n\n")
|
|
report = make_report(f"{file} warnings", json.dumps(result, indent=2), 1)
|
|
try_combine_reports(report)
|
|
put_report(report)
|
|
report = make_report(f"{file} diff", header + diff, 1)
|
|
try_combine_reports(report)
|
|
put_report(report)
|
|
print("Done linting files")
|
|
|
|
|
|
def fix(bin_path: str, files: list[str]):
|
|
for file in files:
|
|
subprocess.run([bin_path, "--mode=fix", file], check=True)
|
|
print("Done fixing files")
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description='buildifier wrapper')
|
|
parser.add_argument(
|
|
"--binary-dir", "-b", type=str,
|
|
help="Path to the buildifier binary, defaults to looking in the current directory.",
|
|
default="")
|
|
parser.add_argument(
|
|
"--generate-report", action="store_true",
|
|
help="Whether or not a report of the lint errors should be generated for evergreen.",
|
|
default=False)
|
|
parser.set_defaults(subcommand=None)
|
|
|
|
sub = parser.add_subparsers(title="buildifier subcommands", help="sub-command help")
|
|
|
|
lint_all_parser = sub.add_parser("lint-all", help="Lint all files")
|
|
lint_all_parser.set_defaults(subcommand="lint-all")
|
|
|
|
fix_all_parser = sub.add_parser("fix-all", help="Fix all files")
|
|
fix_all_parser.set_defaults(subcommand="fix-all")
|
|
|
|
lint_parser = sub.add_parser("lint", help="Lint specified list of files")
|
|
lint_parser.add_argument("files", nargs="+")
|
|
lint_parser.set_defaults(subcommand="lint")
|
|
|
|
lint_parser = sub.add_parser("fix", help="Fix specified list of files")
|
|
lint_parser.add_argument("files", nargs="+")
|
|
lint_parser.set_defaults(subcommand="fix")
|
|
|
|
args = parser.parse_args()
|
|
assert os.path.abspath(os.curdir) == str(
|
|
mongo_dir.absolute()), "buildifier.py must be run from the root of the mongo repo"
|
|
binary_name = "buildifier.exe" if platform.system() == "Windows" else "buildifier"
|
|
if args.binary_dir:
|
|
binary_path = os.path.join(args.binary_dir, binary_name)
|
|
else:
|
|
binary_path = os.path.join(os.curdir, binary_name)
|
|
|
|
subcommand = args.subcommand
|
|
if subcommand == "lint-all":
|
|
lint_all(binary_path, args.generate_report)
|
|
elif subcommand == "fix-all":
|
|
fix_all(binary_path)
|
|
elif subcommand == "lint":
|
|
lint(binary_path, args.files, args.generate_report)
|
|
elif subcommand == "fix":
|
|
fix(binary_path, args.files)
|
|
else:
|
|
# we purposefully do not use sub.choices.keys() so it does not print as a dict_keys object
|
|
choices = [key for key in sub.choices]
|
|
raise RuntimeError(f"One of the following subcommands must be specified: {choices}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|