mirror of
https://github.com/mongodb/mongo.git
synced 2024-11-24 00:17:37 +01:00
855dfadef0
GitOrigin-RevId: e793d662774ccd3ab6c3f356c2287cf1f7ff9805
158 lines
5.3 KiB
Python
158 lines
5.3 KiB
Python
import argparse
|
|
import json
|
|
import os
|
|
import pathlib
|
|
import platform
|
|
import subprocess
|
|
|
|
import download_buildifier
|
|
from simple_report import make_report, put_report, try_combine_reports
|
|
|
|
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)
|
|
|
|
if not os.path.exists(binary_path):
|
|
binary_dir = args.binary_dir if args.binary_dir else os.curdir
|
|
try:
|
|
download_buildifier.download(download_location=binary_dir)
|
|
except Exception as ex:
|
|
raise RuntimeError("Could not download and setup buildifier", ex)
|
|
|
|
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()
|