From 7d5346c241f4376d08e25883b9a85802572f564c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ku=C4=8Dera?= <26327373+vkucera@users.noreply.github.com> Date: Fri, 9 Oct 2026 01:18:14 +0200 Subject: [PATCH] Add more pre-commit hooks --- .pre-commit-config.yaml | 40 ++++++++++++++++-- Scripts/format_includes.awk | 2 +- Scripts/format_includes.py | 84 +++++++++++++++++++++++++++++++++++++ Scripts/o2_linter.py | 0 4 files changed, 121 insertions(+), 5 deletions(-) mode change 100644 => 100755 Scripts/format_includes.awk create mode 100755 Scripts/format_includes.py mode change 100644 => 100755 Scripts/o2_linter.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f837e1ad5a0..cf0e0a1b341 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,15 +2,47 @@ # See https://pre-commit.com/hooks.html for more hooks repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v6.0.0 + rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # frozen: v6.0.0 hooks: - - id: trailing-whitespace + - id: check-added-large-files + - id: check-ast + - id: check-case-conflict + - id: check-executables-have-shebangs + - id: check-merge-conflict + - id: check-symlinks + - id: check-yaml - id: end-of-file-fixer + - id: trailing-whitespace + - repo: https://github.com/shellcheck-py/shellcheck-py + rev: a6564f5d57444e123433a5c9af733e3975c77229 # frozen: v0.11.0.1-1 + hooks: + - id: shellcheck + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: f12be1ebaa5351c1fc76472de98db2c3446c8253 # frozen: v0.16.10 + hooks: + - id: ruff-check # linter + args: ["--fix"] + - id: ruff-format # formatter + - repo: local + hooks: + - id: format-includes + name: format includes + language: python + entry: Scripts/format_includes.py + types: [c++] - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v20.1.3 # clang-format version (keep synced with https://github.com/alisw/ali-bot/blob/master/.github/workflows/c++-code-formatting.yml) + # clang-format version (keep synced with https://github.com/alisw/ali-bot/blob/master/.github/workflows/c++-code-formatting.yml) + rev: 7ec07eeb4135dc6ecf410d24ac4ead986a5d413d # frozen: v20.1.3 hooks: - id: clang-format - repo: https://github.com/cpplint/cpplint - rev: 2.0.2 + rev: 350702a4d39395571bd118c9a3cff0a573488d61 # frozen: 2.0.2 hooks: - id: cpplint + - repo: local + hooks: + - id: O2 linter + name: O2 linter + language: python + entry: Scripts/o2_linter.py + types_or: [c++, cmake, python] diff --git a/Scripts/format_includes.awk b/Scripts/format_includes.awk old mode 100644 new mode 100755 index 42484d62830..b0224f1f747 --- a/Scripts/format_includes.awk +++ b/Scripts/format_includes.awk @@ -15,7 +15,7 @@ else if ( h ~ /^([[:alnum:]_]+\/)+[[:alnum:]_]+\.h/ ) { $2 = "<"h">" } # other third-party else if ( $2 ~ /^".*\./ ) { } # other local-looking file else if ( h ~ /^[[:lower:]_]+\.h/ ) { $2 = "<"h">" } # C system - else if ( h ~ /^[[:lower:]_\/]+/ ) { $2 = "<"h">" } # C++ system + else if ( h ~ /^[[:lower:]_\/]+$/ ) { $2 = "<"h">" } # C++ system } print } diff --git a/Scripts/format_includes.py b/Scripts/format_includes.py new file mode 100755 index 00000000000..c545441d9af --- /dev/null +++ b/Scripts/format_includes.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 + +# Copyright 2019-2020 CERN and copyright holders of ALICE O2. +# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +# All rights not expressly granted are reserved. +# +# This software is distributed under the terms of the GNU General Public +# License v3 (GPL Version 3), copied verbatim in the file "COPYING". +# +# In applying this license CERN does not waive the privileges and immunities +# granted to it by virtue of its status as an Intergovernmental Organization +# or submit itself to any jurisdiction. + +"""! +@brief Fix include style +@author Vít Kučera , Inha University +@date 2026-10-08 + +NB: Run before sorting. + +Usage: format_includes.py FILE [FILE ...] +""" + +import re +import sys + +LOCAL = ('"', '"') +EXTERNAL = ("<", ">") + +INCLUDE = re.compile(r"(\s*#include\s+)(\S+)") + + +def fix_line(line: str) -> str: + m = INCLUDE.match(line) + if not m: + return line + pre, tok = m.groups() + rest = line[m.end() :] + h = tok[1:-1] + + if re.match(r"(PWG[A-Z]{2}|Common|ALICE3|DPG|EventFiltering|PID|Tools|Tutorials)/.*\.h", h): + d = LOCAL # O2Physics + elif re.match( + r"(Algorithm|CCDB|Common[A-Z]|DataFormats|DCAFitter|Detectors|EMCAL|FDD|Field|Framework|FT0|FV0|GlobalTracking|GPU|ITS|MathUtils|MCH|MFT|MID|PHOS|ReconstructionDataFormats|SimulationDataFormat|TOF|TPC|ZDC).*/.*\.h", + h, + ): + d = EXTERNAL # O2 + elif re.match(r"(T[A-Z]|Math/|Roo[A-Z])[A-Za-z0-9/]+\.h", h): + d = EXTERNAL # ROOT + elif re.match(r"KF[A-Z][A-Za-z0-9]+\.h", h): + d = EXTERNAL # KFParticle + elif re.match(r"(fastjet/|onnxruntime)", h): + d = EXTERNAL # FastJet, ONNX + elif re.match(r".*DataModel/", h): + d = LOCAL # incomplete path to DataModel + elif re.match(r"([A-Za-z0-9_]+/)+[A-Za-z0-9_]+\.h", h): + d = EXTERNAL # other third-party + elif re.match(r'".*\.', tok): + return line # other local-looking file + elif re.match(r"[a-z_]+\.h", h): + d = EXTERNAL # C system + elif re.match(r"[a-z_/]+$", h): + d = EXTERNAL # C++ system (whole string) + else: + return line + + return pre + d[0] + h + d[1] + rest + + +def process(path: str): + # newline='' keeps the original line endings untouched. + with open(path, newline="") as f: + lines = f.readlines() + new_lines = [fix_line(line) for line in lines] + if new_lines != lines: + with open(path, "w", newline="") as f: + f.writelines(new_lines) + + +if __name__ == "__main__": + if len(sys.argv) < 2: + sys.exit(__doc__) + for p in sys.argv[1:]: + process(p) diff --git a/Scripts/o2_linter.py b/Scripts/o2_linter.py old mode 100644 new mode 100755