aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/tools
diff options
context:
space:
mode:
authorEgor Tensin <egor@tensin.name>2026-10-05 10:34:55 +0500
committerEgor Tensin <egor@tensin.name>2026-10-05 10:53:25 +0500
commitb4f6e1253356370c8d8855ea0b155e844db98b83 (patch)
treef60faafa2ab66e391eec38480e56b2a845cdc539 /tools
parentpyproject.toml: make a guess about the required Python version (diff)
downloadcmake-common-b4f6e1253356370c8d8855ea0b155e844db98b83.tar.gz
cmake-common-b4f6e1253356370c8d8855ea0b155e844db98b83.zip
tools/project-clang-format.py -> project/format.py
Diffstat (limited to 'tools')
-rwxr-xr-xtools/project-clang-format.py236
1 files changed, 0 insertions, 236 deletions
diff --git a/tools/project-clang-format.py b/tools/project-clang-format.py
deleted file mode 100755
index 4b066c3..0000000
--- a/tools/project-clang-format.py
+++ /dev/null
@@ -1,236 +0,0 @@
-#!/usr/bin/env python
-
-# Copyright (c) 2020 Egor Tensin <egor@tensin.name>
-# This file is part of the "cmake-common" project.
-# For details, see https://github.com/egor-tensin/cmake-common
-# Distributed under the MIT License.
-
-"""clang-format all C/C++ files in the project
-
-This script feeds every C/C++ file in the repository to clang-format, either
-printing a unified diff between the original and the formatted versions, or
-formatting the files in-place.
-"""
-
-import argparse
-from contextlib import contextmanager
-import difflib
-import logging
-import os
-import subprocess
-import sys
-
-
-@contextmanager
-def setup_logging():
- level_names = {
- logging.DEBUG: "DBG",
- logging.INFO: "INFO",
- logging.WARNING: "WARN",
- logging.ERROR: "ERR",
- logging.CRITICAL: "CRIT",
- }
- for lvl, name in level_names.items():
- logging.addLevelName(lvl, name)
-
- logging.basicConfig(
- level=logging.INFO,
- datefmt="%Y-%m-%d %H:%M:%S%z",
- format="%(asctime)s | %(levelname)4s | %(message)s",
- )
- try:
- yield
- except Exception as e:
- logging.exception(e)
- sys.exit(1)
-
-
-@contextmanager
-def cd(path):
- cwd = os.getcwd()
- os.chdir(path)
- try:
- yield
- finally:
- os.chdir(cwd)
-
-
-def normalize_path(entry):
- return os.path.abspath(entry)
-
-
-def run(cmd_line):
- logging.debug("Running executable: %s", cmd_line)
- try:
- return subprocess.run(
- cmd_line,
- check=True,
- universal_newlines=True,
- stderr=subprocess.STDOUT,
- stdout=subprocess.PIPE,
- )
- except subprocess.CalledProcessError as e:
- logging.error("Process finished with exit code %d: %s", e.returncode, cmd_line)
- logging.error("Its output was:\n%s", e.output)
- raise
-
-
-def read_file(path):
- with open(path) as file:
- return file.read()
-
-
-class ClangFormat:
- def __init__(self, path, style):
- self.path = path
- self.style = style
-
- def _get_command_line(self, paths, in_place=False):
- cmd_line = [self.path, f"-style={self.style}"]
- if in_place:
- cmd_line.append("-i")
- cmd_line.append("--")
- cmd_line += list(paths)
- return cmd_line
-
- def format_in_place(self, paths):
- run(self._get_command_line(paths, in_place=True))
-
- @staticmethod
- def _show_diff(path, formatted):
- original = read_file(path)
- if original and not formatted:
- # Assuming this file is ignored in .clang-format-ignore.
- return True
-
- original = original.split("\n")
- formatted = formatted.split("\n")
- original_lbl = f"{path} (original)"
- formatted_lbl = f"{path} (formatted)"
-
- diff = difflib.unified_diff(
- original,
- formatted,
- fromfile=original_lbl,
- tofile=formatted_lbl,
- lineterm="",
- )
-
- clean = True
- for line in diff:
- clean = False
- print(line)
- return clean
-
- def show_diff(self, paths):
- clean = True
- for path in paths:
- formatted = run(self._get_command_line([path])).stdout
- clean = self._show_diff(path, formatted) and clean
- return clean
-
-
-def git_root_dir():
- cmd_line = ["git", "rev-parse", "--show-toplevel"]
- root_dir = run(cmd_line).stdout
- if root_dir[-1] != "\n":
- raise RuntimeError("git rev-parse --show-toplevel should append a newline?")
- return root_dir[:-1]
-
-
-def list_git_files():
- cmd_line = ["git", "ls-tree", "-r", "-z", "--name-only", "HEAD"]
- repo_files = run(cmd_line).stdout
- repo_files = repo_files.split("\0")
- return repo_files
-
-
-def list_all_files():
- return (normalize_path(path) for path in list_git_files())
-
-
-def excluded(path, exclude):
- for entry in exclude:
- if entry == os.path.commonpath((path, entry)):
- return True
- return False
-
-
-def filter_files(paths, exclude):
- if not exclude:
- return paths
- return (path for path in paths if not excluded(path, exclude))
-
-
-CPP_FILE_EXTENSIONS = set(
- (".c", ".h", ".cc", ".hh", ".cpp", ".hpp", ".cxx", ".hxx", ".cp", ".c++")
-)
-
-
-def list_cpp_files():
- for path in list_all_files():
- ext = os.path.splitext(path)[1].lower()
- if ext in CPP_FILE_EXTENSIONS:
- yield path
-
-
-DEFAULT_VERSION = "clang-format"
-DEFAULT_STYLE = "file"
-
-
-def process_cpp_files(
- version=DEFAULT_VERSION, style=DEFAULT_STYLE, in_place=False, exclude=None
-):
- clang_format = ClangFormat(version, style)
- with cd(git_root_dir()):
- cpp_files = filter_files(list_cpp_files(), exclude)
- if in_place:
- clang_format.format_in_place(cpp_files)
- else:
- if not clang_format.show_diff(cpp_files):
- sys.exit(1)
-
-
-def parse_args(argv=None):
- if argv is None:
- argv = sys.argv[1:]
-
- parser = argparse.ArgumentParser(
- description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
- )
-
- parser.add_argument(
- "-b",
- "--clang-format",
- dest="version",
- default=DEFAULT_VERSION,
- help="clang-format executable file path",
- )
- parser.add_argument(
- "-s",
- "--style",
- default=DEFAULT_STYLE,
- help="clang-format -style parameter argument",
- )
- parser.add_argument(
- "-i", "--in-place", action="store_true", help="edit the files in-place"
- )
- parser.add_argument(
- "-e",
- "--exclude",
- nargs="*",
- type=normalize_path,
- help="files or directories to exclude",
- )
-
- return parser.parse_args(argv)
-
-
-def main(argv=None):
- args = parse_args(argv)
- with setup_logging():
- process_cpp_files(**vars(args))
-
-
-if __name__ == "__main__":
- main()