From 82739b1c71ff9793f512871968dac663e32f9b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=98yvind=20Eide?= Date: Thu, 30 Nov 2023 09:29:02 +0100 Subject: [PATCH] Add cmake and clang format to pre-commit --- .github/workflows/style.yml | 7 -- .pre-commit-config.yaml | 15 ++++ README.md | 11 +++ script/clang-format | 145 ------------------------------------ script/cmake-format | 102 ------------------------- src/clib/CMakeLists.txt | 10 +-- 6 files changed, 30 insertions(+), 260 deletions(-) delete mode 100755 script/clang-format delete mode 100755 script/cmake-format diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml index eca29099f13..49384719780 100644 --- a/.github/workflows/style.yml +++ b/.github/workflows/style.yml @@ -33,13 +33,6 @@ jobs: run: | pip install ".[style]" - - name: Clang Format - run: ./script/clang-format --check - - - name: CMake Format - if: ${{ always() }} - run: ./script/cmake-format --check - - name: Add matching rule run: echo ::add-matcher::.github/flake8-matcher.json diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3bdc076b62d..0538eaa3d1d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -17,3 +17,18 @@ repos: rev: 23.11.0 hooks: - id: black + +- repo: https://github.com/pre-commit/mirrors-clang-format + rev: v17.0.5 + hooks: + - id: clang-format + args: [ --style=file, --Werror] + exclude: .json + +- repo: https://github.com/cheshirekow/cmake-format-precommit + rev: v0.6.10 + hooks: + - id: cmake-format + - id: cmake-lint + exclude: FindFilesystem + args: [ "--disable:C0301,C0111,C0113" ] diff --git a/README.md b/README.md index c11bb736339..f014506024e 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,17 @@ If you checked out submodules without having git lfs installed, you can force gi git submodule foreach "git lfs pull" ``` + +### Style requirements + +There are a set of style requirements, which are gathered in the `pre-commit` +configuration, to have it automatically run on each commit do: + +``` sh +$ pip install pre-commit +$ pre-commit install +``` + ### Trouble with setup If you encounter problems during install, try deleting the `_skbuild` folder before reinstalling. diff --git a/script/clang-format b/script/clang-format deleted file mode 100755 index d7538552463..00000000000 --- a/script/clang-format +++ /dev/null @@ -1,145 +0,0 @@ -#!/usr/bin/env python3 -import shutil -import sys -from argparse import ArgumentParser -from pathlib import Path -from subprocess import STDOUT, CalledProcessError, check_output -from typing import Iterator, Optional - -DIRECTORIES = ["src/clib"] - - -def find_clang_format_binary(clang_format: Optional[str]) -> Path: - """ - Looks for clang-format binary by searching the PATH environment - variable. Detect if clang-format was installed from PyPI and use the actual - binary rather than the incredibly slow Python wrapper. - """ - if clang_format is None: - clang_format = shutil.which("clang-format") - if clang_format is None: - sys.exit("No viable executable 'clang-format' found in PATH") - - with open(clang_format, "rb") as f: - head = f.read(512) - - if head[:2] != b"#!": - # File does not contain shebang, assuming real clang-format - print(f"Using clang-format: {clang_format}") - return Path(clang_format) - - # Extract everything between '#!' and newline - python_path = head[2:].split(b"\n")[0].decode().strip() - - # Locate the Python 'clang-format' module path - mod_path = ( - check_output( - [python_path, "-c", "import clang_format;print(clang_format.__file__)"] - ) - .decode() - .strip() - ) - - # We assume that the location of the actual binary is always in the same - # location - clang_format_path = Path(mod_path).parent / "data" / "bin" / "clang-format" - - print(f"Using clang-format: {clang_format_path}") - return clang_format_path - - -def source_root() -> Path: - node = Path(__file__).parent.resolve() - while not (node / ".git").is_dir(): - if str(node) == "/": - sys.exit("Could not find the source root (no .git directory)") - node = node.parent - return node - - -def enumerate_sources() -> Iterator[Path]: - root = source_root() - for directory in DIRECTORIES: - for extension in "c", "h", "cpp", "hpp": - pattern = f"{directory}/**/*.{extension}" - for path in root.glob(pattern): - yield path - - -def reformat(clang_format: Path, dry_run: bool, verbose: bool) -> None: - total = 0 - need_reformat = 0 - failed_reformat = 0 - - root = source_root() - for path in enumerate_sources(): - relpath = path.relative_to(root) - total += 1 - if verbose: - print("checking ", path) - - try: - check_output([clang_format, "--dry-run", "-Werror", path], stderr=STDOUT) - continue # This file passed the check, continue - except CalledProcessError: - need_reformat += 1 - if dry_run: - print("would reformat", relpath) - - if dry_run: - continue - try: - check_output([clang_format, "-i", "-Werror", path], stderr=STDOUT) - print("reformatted", relpath) - except CalledProcessError: - failed_reformat += 1 - print("failed to reformat", relpath) - - if dry_run: - print( - f"{need_reformat} files would be reformatted, " - f"{total - need_reformat} files would be left unchanged." - ) - if need_reformat > 0: - sys.exit(1) - else: - successfully_reformatted = need_reformat - failed_reformat - print( - f"{successfully_reformatted} files reformatted, " - f"{total - successfully_reformatted} files left unchanged, " - f"{failed_reformat} files failed to reformat." - ) - if failed_reformat > 0: - sys.exit(1) - - -def main() -> None: - ap = ArgumentParser() - ap.add_argument( - "-c", - "--check", - action="store_true", - default=False, - help="Performs a check without modifying any files", - ) - ap.add_argument( - "--clang-format", - type=str, - help="Name/path of the clang-format binary", - ) - ap.add_argument( - "-v", - "--verbose", - action="store_true", - default=False, - help="Output verbosely", - ) - - args = ap.parse_args() - - clang_format = find_clang_format_binary(args.clang_format) - reformat(clang_format, args.check, args.verbose) - - -if __name__ == "__main__": - main() diff --git a/script/cmake-format b/script/cmake-format deleted file mode 100755 index a49e4ca270f..00000000000 --- a/script/cmake-format +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python3 -import sys -from argparse import ArgumentParser -from pathlib import Path -from subprocess import STDOUT, CalledProcessError, check_output -from typing import Iterator - - -def source_root() -> Path: - node = Path(__file__).parent.resolve() - while not (node / ".git").is_dir(): - if str(node) == "/": - sys.exit("Could not find the source root (no .git directory)") - node = node.parent - return node - - -def enumerate_sources() -> Iterator[Path]: - root = source_root() - for filename in "CMakeLists.txt", "*.cmake": - pattern = f"src/**/{filename}" - for path in root.glob(pattern): - yield path - - -def reformat(cmake_format: str, dry_run: bool, verbose: bool) -> None: - total = 0 - need_reformat = 0 - failed_reformat = 0 - - root = source_root() - for path in enumerate_sources(): - relpath = path.relative_to(root) - total += 1 - if verbose: - print("checking ", path) - - try: - check_output([cmake_format, "--check", path], stderr=STDOUT) - continue # This file passed the check, continue - except CalledProcessError: - need_reformat += 1 - if dry_run: - print("would reformat", relpath) - - if dry_run: - continue - try: - check_output([cmake_format, "-i", path], stderr=STDOUT) - print("reformatted", relpath) - except CalledProcessError: - failed_reformat += 1 - print("failed to reformat", relpath) - - if dry_run: - print( - f"{need_reformat} files would be reformatted, " - f"{total - need_reformat} files would be left unchanged." - ) - if need_reformat > 0: - sys.exit(1) - else: - successfully_reformatted = need_reformat - failed_reformat - print( - f"{successfully_reformatted} files reformatted, " - f"{total - successfully_reformatted} files left unchanged, " - f"{failed_reformat} files failed to reformat." - ) - if failed_reformat > 0: - sys.exit(1) - - -def main() -> None: - ap = ArgumentParser( - description="Format all CMakeFiles and *.cmake in this repository. Requires the PyPI package 'cmake-format'." - ) - ap.add_argument( - "-c", - "--check", - action="store_true", - default=False, - help="Performs a check without modifying any files", - ) - ap.add_argument( - "--cmake-format", - default="cmake-format", - help="Name/path of the cmake-format binary", - ) - ap.add_argument( - "-v", - "--verbose", - action="store_true", - default=False, - help="Output verbosely", - ) - - args = ap.parse_args() - reformat(args.cmake_format, args.check, args.verbose) - - -if __name__ == "__main__": - main() diff --git a/src/clib/CMakeLists.txt b/src/clib/CMakeLists.txt index 09a945e5d25..13801d18a3b 100644 --- a/src/clib/CMakeLists.txt +++ b/src/clib/CMakeLists.txt @@ -66,16 +66,14 @@ list(APPEND CMAKE_PREFIX_PATH "${_tmp_dir}") execute_process( COMMAND "${_python_executable}" -c "import resdata; print(resdata.get_include())" - OUTPUT_VARIABLE ECL_INCLUDE_DIRS - OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ECHO STDOUT COMMAND_ERROR_IS_FATAL - LAST) + OUTPUT_VARIABLE ECL_INCLUDE_DIRS OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND_ECHO STDOUT COMMAND_ERROR_IS_FATAL LAST) execute_process( COMMAND "${_python_executable}" -c "import resdata; print(resdata.ResdataPrototype.lib._name)" - OUTPUT_VARIABLE ECL_LIBRARY - OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ECHO STDOUT COMMAND_ERROR_IS_FATAL - LAST) + OUTPUT_VARIABLE ECL_LIBRARY OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ECHO + STDOUT COMMAND_ERROR_IS_FATAL LAST) add_library(resdata SHARED IMPORTED GLOBAL) set_target_properties(resdata PROPERTIES IMPORTED_LOCATION "${ECL_LIBRARY}"