summaryrefslogtreecommitdiff
path: root/buildscripts/quickcpplint.py
diff options
context:
space:
mode:
Diffstat (limited to 'buildscripts/quickcpplint.py')
-rwxr-xr-xbuildscripts/quickcpplint.py107
1 files changed, 107 insertions, 0 deletions
diff --git a/buildscripts/quickcpplint.py b/buildscripts/quickcpplint.py
new file mode 100755
index 00000000000..d008475a8a3
--- /dev/null
+++ b/buildscripts/quickcpplint.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python3
+"""Extensible script to run one or more simple C++ Linters across a subset of files in parallel."""
+
+import argparse
+import logging
+import os
+import re
+import sys
+import threading
+from typing import List
+
+# Get relative imports to work when the package is not installed on the PYTHONPATH.
+if __name__ == "__main__" and __package__ is None:
+ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(os.path.realpath(__file__)))))
+
+from buildscripts.linter import git # pylint: disable=wrong-import-position
+from buildscripts.linter import parallel # pylint: disable=wrong-import-position
+from buildscripts.linter import simplecpplint # pylint: disable=wrong-import-position
+
+FILES_RE = re.compile('\\.(h|cpp)$')
+
+
+def is_interesting_file(file_name: str) -> bool:
+ """Return true if this file should be checked."""
+ return (file_name.startswith("jstests")
+ or file_name.startswith("src") and not file_name.startswith("src/third_party/")
+ and not file_name.startswith("src/mongo/gotools/")) and FILES_RE.search(file_name)
+
+
+def _lint_files(file_names: List[str]) -> None:
+ """Lint a list of files with clang-format."""
+ run_lint1 = lambda param1: simplecpplint.lint_file(param1) == 0
+ if not parallel.parallel_process([os.path.abspath(f) for f in file_names], run_lint1):
+ print("ERROR: Code Style does not match coding style")
+ sys.exit(1)
+
+
+def lint_patch(file_name: str) -> None:
+ """Lint patch command entry point."""
+ file_names = git.get_files_to_check_from_patch(file_name, is_interesting_file)
+
+ # Patch may have files that we do not want to check which is fine
+ if file_names:
+ _lint_files(file_names)
+
+
+def lint(file_names: List[str]) -> None:
+ # type: (str, Dict[str, str], List[str]) -> None
+ """Lint files command entry point."""
+ all_file_names = git.get_files_to_check(file_names, is_interesting_file)
+
+ _lint_files(all_file_names)
+
+
+def lint_all(file_names: List[str]) -> None:
+ # pylint: disable=unused-argument
+ """Lint files command entry point based on working tree."""
+ all_file_names = git.get_files_to_check_working_tree(is_interesting_file)
+
+ _lint_files(all_file_names)
+
+
+def lint_my(origin_branch: List[str]) -> None:
+ # pylint: disable=unused-argument
+ """Lint files command based on local changes."""
+ files = git.get_my_files_to_check(is_interesting_file, origin_branch)
+ files = [f for f in files if os.path.exists(f)]
+
+ _lint_files(files)
+
+
+def main() -> None:
+ """Execute Main entry point."""
+
+ parser = argparse.ArgumentParser(description='Quick C++ Lint frontend.')
+
+ parser.add_argument('-v', "--verbose", action='store_true', help="Enable verbose logging")
+
+ sub = parser.add_subparsers(title="Linter subcommands", help="sub-command help")
+
+ parser_lint = sub.add_parser('lint', help='Lint only Git files')
+ parser_lint.add_argument("file_names", nargs="*", help="Globs of files to check")
+ parser_lint.set_defaults(func=lint)
+
+ parser_lint_all = sub.add_parser('lint-all', help='Lint All files')
+ parser_lint_all.add_argument("file_names", nargs="*", help="Globs of files to check")
+ parser_lint_all.set_defaults(func=lint_all)
+
+ parser_lint_patch = sub.add_parser('lint-patch', help='Lint the files in a patch')
+ parser_lint_patch.add_argument("file_names", nargs="*", help="Globs of files to check")
+ parser_lint_patch.set_defaults(func=lint_patch)
+
+ parser_lint_my = sub.add_parser('lint-my', help='Lint my files')
+ parser_lint_my.add_argument("--branch", dest="file_names", default="origin/master",
+ help="Branch to compare against")
+ parser_lint_my.set_defaults(func=lint_my)
+
+ args = parser.parse_args()
+
+ if args.verbose:
+ logging.basicConfig(level=logging.DEBUG)
+
+ args.func(args.file_names)
+
+
+if __name__ == "__main__":
+ main()