feat(linter): implement Phase 1 linter automation and docs
- Add .clang-tidy (analyzer + selected bugprone) and .clang-format (LLVM, 4-space, 100 cols) - Enhance scripts/run-linter.sh to use compile_commands.json when available - Add scripts/setup-hooks.sh pre-commit (format enforcement; advisory tidy) - Update azure-pipelines.yml to export compile_commands and run clang-tidy -p build - Fill docs/linter-setup.md and docs/coding-standards.md for Phase 1 - Add minimal tests in tests/test_main.cpp to ensure CI executes - Rewrite README with Phase 1 workflow
This commit is contained in:
11
.clang-format
Normal file
11
.clang-format
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
BasedOnStyle: LLVM
|
||||||
|
IndentWidth: 4
|
||||||
|
TabWidth: 4
|
||||||
|
UseTab: Never
|
||||||
|
ColumnLimit: 100
|
||||||
|
AllowShortFunctionsOnASingleLine: Empty
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
SortIncludes: CaseSensitive
|
||||||
|
SpacesInAngles: Never
|
||||||
|
PointerAlignment: Right
|
||||||
|
DerivePointerAlignment: false
|
31
.clang-tidy
Normal file
31
.clang-tidy
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
Checks: >
|
||||||
|
-*,
|
||||||
|
clang-analyzer-*,
|
||||||
|
bugprone-argument-comment,
|
||||||
|
bugprone-assert-side-effect,
|
||||||
|
bugprone-bad-signal-to-kill-thread,
|
||||||
|
bugprone-branch-clone,
|
||||||
|
bugprone-copy-constructor-init,
|
||||||
|
bugprone-dangling-handle,
|
||||||
|
bugprone-exception-escape,
|
||||||
|
bugprone-integer-division,
|
||||||
|
bugprone-macro-parentheses,
|
||||||
|
bugprone-misplaced-operator-in-strlen-in-alloc,
|
||||||
|
bugprone-multiple-new-delete-leaks,
|
||||||
|
bugprone-sizeof-expression,
|
||||||
|
bugprone-suspicious-missing-comma,
|
||||||
|
bugprone-throw-keyword-missing,
|
||||||
|
bugprone-unhandled-self-assignment,
|
||||||
|
bugprone-unused-return-value,
|
||||||
|
clang-analyzer-security.*,
|
||||||
|
clang-analyzer-cplusplus.*,
|
||||||
|
clang-analyzer-core.*
|
||||||
|
HeaderFilterRegex: '(src|tests)/'
|
||||||
|
AnalyzeTemporaryDtors: false
|
||||||
|
FormatStyle: none
|
||||||
|
WarningsAsErrors: ''
|
||||||
|
|
||||||
|
# Phase 1: advisory only (warnings do not fail CI)
|
||||||
|
CheckOptions:
|
||||||
|
- key: bugprone-assert-side-effect.AssertMacros
|
||||||
|
value: 'assert'
|
138
README.md
138
README.md
@@ -1,94 +1,94 @@
|
|||||||
# C++ Linter Template
|
# C++ Linter Template
|
||||||
|
|
||||||
這是一個展示如何在 C++ 專案中整合 linter 工具的模板專案。
|
這是一個符合最佳實務、可漸進式導入的 C++ linter 自動化模板。現為 Phase 1:格式嚴格、靜態分析建議不擋流程。
|
||||||
|
|
||||||
## 目的
|
## 目標
|
||||||
- 展示 clang-tidy 在舊 C++ 代碼中的應用
|
- 對舊 C++ 專案導入 `clang-tidy` 與 `clang-format`
|
||||||
- 提供漸進式導入 linter 的範例
|
- 提供「先格式、後強化」的漸進策略
|
||||||
- Azure DevOps CI/CD 整合範例
|
- 內建 Azure DevOps CI/CD 串接與 PR 差異分析
|
||||||
|
|
||||||
## 快速開始
|
## 快速開始(Phase 1)
|
||||||
|
|
||||||
### 1. 本地開發環境設定
|
### 1) 安裝工具
|
||||||
```bash
|
```bash
|
||||||
# 安裝相依套件 (Ubuntu/Debian)
|
# Ubuntu/Debian
|
||||||
sudo apt install clang-tidy clang-format cmake build-essential
|
sudo apt install clang-tidy clang-format cmake build-essential
|
||||||
|
|
||||||
# 安裝相依套件 (macOS)
|
# macOS
|
||||||
brew install llvm cmake
|
brew install llvm cmake
|
||||||
|
|
||||||
# 克隆專案
|
|
||||||
git clone <your-repo-url>
|
|
||||||
cd cpp-linter-template
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. 執行 Linter
|
### 2) 產出 compile_commands.json(建議)
|
||||||
```bash
|
```bash
|
||||||
# 使用提供的腳本
|
mkdir -p build && cd build
|
||||||
|
cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
||||||
|
cd -
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3) 執行 Linter
|
||||||
|
```bash
|
||||||
|
# 使用腳本(會自動偵測 build/compile_commands.json)
|
||||||
./scripts/run-linter.sh
|
./scripts/run-linter.sh
|
||||||
|
|
||||||
# 或手動執行
|
|
||||||
clang-tidy src/*.cpp src/*.h tests/*.cpp --config-file=.clang-tidy
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. 建構專案
|
### 4) 安裝 Git hooks(建議)
|
||||||
```bash
|
```bash
|
||||||
mkdir build && cd build
|
./scripts/setup-hooks.sh
|
||||||
cmake ..
|
```
|
||||||
make
|
- pre-commit 會自動 clang-format 已 staged 的 C/C++ 檔並要求你重提一次 commit。
|
||||||
|
- clang-tidy 以建議模式執行(不擋提交)。
|
||||||
|
|
||||||
|
### 5) 建構與執行
|
||||||
|
```bash
|
||||||
|
mkdir -p build && cd build
|
||||||
|
cmake .. -DCMAKE_BUILD_TYPE=Debug
|
||||||
|
make -j$(nproc)
|
||||||
|
./tests
|
||||||
./main
|
./main
|
||||||
```
|
```
|
||||||
|
|
||||||
## Linter 配置說明
|
## Phase 1 政策(建議 → 強制的起點)
|
||||||
### 當前採用階段一設定:
|
- 格式:以 `.clang-format` 為準;CI 以 `--dry-run --Werror` 強制。
|
||||||
- 只檢查最關鍵的錯誤
|
- 靜態分析:`.clang-tidy` 啟用 `clang-analyzer-*` 與精選 `bugprone-*`;僅回報警告,不讓 CI 失敗。
|
||||||
- 不會因 linter 警告而中斷 CI
|
- PR:僅分析變更檔案,加速回饋。
|
||||||
- 適合舊代碼逐步改進
|
|
||||||
|
|
||||||
### 後續階段計劃
|
## CI 流程(Azure Pipelines)
|
||||||
- 階段二:增加記憶體和資源管理檢查
|
1. 安裝工具與版本資訊
|
||||||
- 階段三:加入可讀性和現代化建議
|
2. `clang-format --dry-run --Werror`(不合格式即失敗)
|
||||||
- 階段四:強制執行,警告視為錯誤
|
3. 以 CMake 匯出 `build/compile_commands.json`
|
||||||
|
4. `clang-tidy -p build` 掃描(建議模式,不擋流程)
|
||||||
|
5. Build 專案與執行 `./tests`、`./main`
|
||||||
|
6. PR Job 僅對變更檔案跑 `clang-tidy -p build`
|
||||||
|
|
||||||
## 在 Azure DevOps 中使用
|
## 自定義規則
|
||||||
1. 將此專案推送到 Azure DevOps
|
- `.clang-tidy`:Phase 1 強調重大缺陷檢查(例如 analyzer、部分 bugprone)。
|
||||||
2. 設定 Pipeline 使用 azure-pipelines.yml
|
- `.clang-format`:基於 LLVM 風格(IndentWidth=4, ColumnLimit=100)。
|
||||||
3. 建立 Pull Request 時會自動執行 linter
|
|
||||||
|
|
||||||
## 自定義配置
|
## 文件
|
||||||
編輯 .clang-tidy 檔案來調整檢查規則:
|
- `docs/linter-setup.md`:本地與 CI 設定流程
|
||||||
```yaml
|
- `docs/coding-standards.md`:編碼與格式規範(Phase 1)
|
||||||
# 增加更多檢查
|
|
||||||
Checks: '-*,clang-analyzer-*,bugprone-*,readability-*'
|
|
||||||
```
|
|
||||||
|
|
||||||
## 檔案說明
|
|
||||||
`.clang-tidy:` Linter 配置檔
|
|
||||||
`.clang-format`: 程式碼格式化配置
|
|
||||||
`azure-pipelines.yml`: Azure DevOps CI/CD 配置
|
|
||||||
`scripts/run-linter.sh`: 本地執行 linter 腳本
|
|
||||||
|
|
||||||
## 注意事項
|
|
||||||
- 此模板使用 C++98 標準,適合舊代碼
|
|
||||||
- Linter 設定較為寬鬆,適合逐步導入
|
|
||||||
- 可以根據團隊需求調整檢查規則
|
|
||||||
|
|
||||||
## 專案結構
|
## 專案結構
|
||||||
cpp-linter-template/
|
cpp-linter-template/
|
||||||
├── .clang-tidy # linter 配置檔
|
├── .clang-tidy # linter 配置檔(Phase 1)
|
||||||
├── .clang-format # 格式化配置檔
|
├── .clang-format # 格式化配置
|
||||||
├── azure-pipelines.yml # Azure DevOps CI/CD 配置
|
├── azure-pipelines.yml # Azure DevOps CI/CD 配置
|
||||||
├── CMakeLists.txt # 建構配置
|
├── CMakeLists.txt # 建構配置(C++98)
|
||||||
├── README.md # 專案說明
|
├── README.md # 專案說明(本檔)
|
||||||
├── docs/ # 文件目錄
|
├── docs/ # 文件目錄
|
||||||
│ ├── linter-setup.md # Linter 設定指南
|
│ ├── linter-setup.md # Linter 設定指南
|
||||||
│ └── coding-standards.md # 編碼標準
|
│ └── coding-standards.md # 編碼標準(Phase 1)
|
||||||
├── src/ # 原始碼
|
├── src/ # 原始碼
|
||||||
│ ├── main.cpp # 主程式(含各種測試案例)
|
│ ├── main.cpp # 主程式(含測試片段)
|
||||||
│ ├── utils.cpp # 工具函數
|
│ ├── utils.cpp # 工具函數
|
||||||
│ └── utils.h # 標頭檔
|
│ └── utils.h # 標頭檔
|
||||||
├── tests/ # 測試程式碼
|
├── tests/ # 測試程式碼
|
||||||
│ └── test_main.cpp # 簡單測試
|
│ └── test_main.cpp # 最小測試(無框架)
|
||||||
└── scripts/ # 輔助腳本
|
└── scripts/ # 輔助腳本
|
||||||
├── run-linter.sh # 本地執行 linter
|
├── run-linter.sh # 本地執行 linter
|
||||||
└── setup-hooks.sh # 設定 git hooks
|
└── setup-hooks.sh # 安裝 pre-commit hooks
|
||||||
|
|
||||||
|
## 後續階段(預覽)
|
||||||
|
- Phase 2:對關鍵 tidy 規則轉為失敗門檻(資源管理/未定義行為)。
|
||||||
|
- Phase 3:引入 readability/modernize 並在 PR 變更檔上強制。
|
||||||
|
- Phase 4:全域強制,警告視為錯誤(需技術債清理完成)。
|
||||||
|
@@ -32,6 +32,7 @@ stages:
|
|||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y clang-tidy clang-format cmake build-essential
|
sudo apt-get install -y clang-tidy clang-format cmake build-essential
|
||||||
clang-tidy --version
|
clang-tidy --version
|
||||||
|
cmake --version
|
||||||
|
|
||||||
- task: Bash@3
|
- task: Bash@3
|
||||||
displayName: 'Check Code Format'
|
displayName: 'Check Code Format'
|
||||||
@@ -42,14 +43,26 @@ stages:
|
|||||||
find src tests -name "*.cpp" -o -name "*.h" | xargs clang-format --dry-run --Werror
|
find src tests -name "*.cpp" -o -name "*.h" | xargs clang-format --dry-run --Werror
|
||||||
|
|
||||||
- task: Bash@3
|
- task: Bash@3
|
||||||
displayName: 'Run clang-tidy on all files'
|
displayName: 'Configure build (export compile_commands)'
|
||||||
inputs:
|
inputs:
|
||||||
targetType: 'inline'
|
targetType: 'inline'
|
||||||
script: |
|
script: |
|
||||||
echo "Running clang-tidy..."
|
echo "Configuring CMake to export compile_commands.json..."
|
||||||
find src tests -name "*.cpp" -o -name "*.h" | xargs clang-tidy --config-file=.clang-tidy
|
mkdir -p build
|
||||||
|
cd build
|
||||||
|
cmake .. -DCMAKE_BUILD_TYPE=${{ variables.buildConfiguration }} -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
||||||
|
ls -la
|
||||||
|
|
||||||
# 階段一:只顯示警告,不中斷 CI
|
- task: Bash@3
|
||||||
|
displayName: 'Run clang-tidy on all files (advisory)'
|
||||||
|
inputs:
|
||||||
|
targetType: 'inline'
|
||||||
|
script: |
|
||||||
|
echo "Running clang-tidy (Phase 1: advisory only)..."
|
||||||
|
FILES=$(find src tests -type f \( -name "*.cpp" -o -name "*.cxx" -o -name "*.cc" -o -name "*.c++" -o -name "*.h" -o -name "*.hpp" -o -name "*.hxx" \))
|
||||||
|
if [ -n "$FILES" ]; then
|
||||||
|
echo "$FILES" | xargs -r clang-tidy -p build --config-file=.clang-tidy || true
|
||||||
|
fi
|
||||||
echo "Linter completed. Review warnings above."
|
echo "Linter completed. Review warnings above."
|
||||||
|
|
||||||
- task: Bash@3
|
- task: Bash@3
|
||||||
@@ -57,7 +70,6 @@ stages:
|
|||||||
inputs:
|
inputs:
|
||||||
targetType: 'inline'
|
targetType: 'inline'
|
||||||
script: |
|
script: |
|
||||||
mkdir build
|
|
||||||
cd build
|
cd build
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=${{ variables.buildConfiguration }}
|
cmake .. -DCMAKE_BUILD_TYPE=${{ variables.buildConfiguration }}
|
||||||
make -j$(nproc)
|
make -j$(nproc)
|
||||||
@@ -81,8 +93,18 @@ stages:
|
|||||||
targetType: 'inline'
|
targetType: 'inline'
|
||||||
script: |
|
script: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y clang-tidy
|
sudo apt-get install -y clang-tidy cmake build-essential
|
||||||
|
cmake --version
|
||||||
|
|
||||||
|
- task: Bash@3
|
||||||
|
displayName: 'Configure build (export compile_commands)'
|
||||||
|
inputs:
|
||||||
|
targetType: 'inline'
|
||||||
|
script: |
|
||||||
|
echo "Configuring CMake to export compile_commands.json for PR analysis..."
|
||||||
|
mkdir -p build
|
||||||
|
cd build
|
||||||
|
cmake .. -DCMAKE_BUILD_TYPE=${{ variables.buildConfiguration }} -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
||||||
- task: Bash@3
|
- task: Bash@3
|
||||||
displayName: 'Analyze Changed Files Only'
|
displayName: 'Analyze Changed Files Only'
|
||||||
inputs:
|
inputs:
|
||||||
@@ -102,5 +124,5 @@ stages:
|
|||||||
echo "Changed C++ files:"
|
echo "Changed C++ files:"
|
||||||
echo "$CHANGED_FILES"
|
echo "$CHANGED_FILES"
|
||||||
|
|
||||||
echo "Running clang-tidy on changed files..."
|
echo "Running clang-tidy on changed files (advisory)..."
|
||||||
echo "$CHANGED_FILES" | xargs clang-tidy --config-file=.clang-tidy -- -std=c++98
|
echo "$CHANGED_FILES" | xargs -r clang-tidy -p build --config-file=.clang-tidy || true
|
||||||
|
@@ -0,0 +1,22 @@
|
|||||||
|
# Coding Standards (Phase 1)
|
||||||
|
|
||||||
|
## 語言與標準
|
||||||
|
- C++98 為主要標準(舊代碼相容)。
|
||||||
|
- 禁止使用危險 API:偏好安全封裝;必要時以註解說明風險與保護措施。
|
||||||
|
|
||||||
|
## 格式(由 `.clang-format` 強制)
|
||||||
|
- BasedOnStyle: LLVM,IndentWidth: 4,ColumnLimit: 100。
|
||||||
|
- 以 pre-commit 與 CI 確保格式一致性。
|
||||||
|
|
||||||
|
## 一般規範
|
||||||
|
- 生命週期:new/delete 成對,避免裸指標長期持有;儘量早釋放資源。
|
||||||
|
- 控制流:避免過深巢狀;優先早回傳以簡化邏輯。
|
||||||
|
- 註解:描述「為何」而非「做什麼」。
|
||||||
|
- 介面:標頭檔最小公開;避免不必要的 include,採前置宣告以降低耦合。
|
||||||
|
|
||||||
|
## Tidy 規則(Phase 1)
|
||||||
|
- 啟用:`clang-analyzer-*` 與精選 `bugprone-*`,聚焦重大缺陷(洩漏、未定義行為)。
|
||||||
|
- 停用:`modernize-*`、`readability-*`(後續階段再逐步導入)。
|
||||||
|
|
||||||
|
## 例外處理
|
||||||
|
- 舊代碼可逐步改善;若需暫時抑制特定告警,請附上註解與追蹤項(TODO/issue)。
|
||||||
|
@@ -0,0 +1,39 @@
|
|||||||
|
# Linter Setup (Phase 1)
|
||||||
|
|
||||||
|
本文件說明如何在本地與 CI 環境執行 Phase 1 的 linter 自動化。
|
||||||
|
|
||||||
|
## 需求
|
||||||
|
- clang-tidy, clang-format
|
||||||
|
- CMake 3.10+
|
||||||
|
|
||||||
|
## 本地流程
|
||||||
|
1) 安裝工具
|
||||||
|
- Ubuntu/Debian: `sudo apt install clang-tidy clang-format cmake`
|
||||||
|
- macOS: `brew install llvm cmake`
|
||||||
|
|
||||||
|
2) 產出 compile_commands.json(建議,提高 tidy 準確度)
|
||||||
|
- `mkdir -p build && cd build`
|
||||||
|
- `cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON`
|
||||||
|
- `cd -`
|
||||||
|
|
||||||
|
3) 執行 linter
|
||||||
|
- `./scripts/run-linter.sh`
|
||||||
|
- 若偵測到 `build/compile_commands.json`,腳本會自動以 `-p build` 方式執行 clang-tidy。
|
||||||
|
|
||||||
|
4) 安裝 Git hooks(建議)
|
||||||
|
- `./scripts/setup-hooks.sh`
|
||||||
|
- pre-commit 會:
|
||||||
|
- 對 staged C/C++ 檔執行 clang-format 並重新加入索引;若有改動會中止一次提交,請重新檢視並再次提交。
|
||||||
|
- 以建議模式執行 clang-tidy(不阻擋提交)。
|
||||||
|
|
||||||
|
## CI 流程(Azure Pipelines)
|
||||||
|
- 安裝工具 → `clang-format --dry-run --Werror` → CMake 匯出 `compile_commands.json` → 以 `-p build` 跑 clang-tidy(建議模式)→ Build → Run tests。
|
||||||
|
- Pull Request Job 只分析變更檔案,並以建議模式跑 clang-tidy。
|
||||||
|
|
||||||
|
## Phase 1 政策
|
||||||
|
- 格式:必須符合 `.clang-format`,否則 CI 失敗、pre-commit 會自動修正。
|
||||||
|
- Tidy:使用 `.clang-tidy` 的安全規則集合,僅回報警告,不使 CI 失敗。
|
||||||
|
|
||||||
|
## 後續升級(概述)
|
||||||
|
- Phase 2:對關鍵規則(記憶體/資源/未定義行為)提升為失敗門檻。
|
||||||
|
- Phase 3:擴大規則(readability/modernize),對 PR 變更檔強制。
|
||||||
|
@@ -12,7 +12,7 @@ if ! command -v clang-tidy &> /dev/null; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# 尋找所有 C++ 檔案
|
# 尋找所有 C++ 檔案
|
||||||
CPP_FILES=$(find src tests -name "*.cpp" -o -name "*.h" 2>/dev/null)
|
CPP_FILES=$(find src tests -type f \( -name "*.cpp" -o -name "*.cxx" -o -name "*.cc" -o -name "*.c++" -o -name "*.h" -o -name "*.hpp" -o -name "*.hxx" \) 2>/dev/null)
|
||||||
|
|
||||||
if [ -z "$CPP_FILES" ]; then
|
if [ -z "$CPP_FILES" ]; then
|
||||||
echo "No C++ files found."
|
echo "No C++ files found."
|
||||||
@@ -23,7 +23,17 @@ echo "Found files:"
|
|||||||
echo "$CPP_FILES"
|
echo "$CPP_FILES"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
# 執行 clang-tidy
|
# 若存在 compile_commands.json,則使用 -p 指向 build 目錄以提高精準度
|
||||||
echo "$CPP_FILES" | xargs clang-tidy --config-file=.clang-tidy
|
TIDY_CMD_BASE=(clang-tidy --config-file=.clang-tidy)
|
||||||
|
if [ -f "build/compile_commands.json" ]; then
|
||||||
|
echo "Detected build/compile_commands.json; using -p build"
|
||||||
|
TIDY_CMD_BASE+=( -p build )
|
||||||
|
else
|
||||||
|
echo "No compile_commands.json detected. For better results, run:"
|
||||||
|
echo " mkdir -p build && cd build && cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON && cd -"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 執行 clang-tidy(保持 Phase 1:僅回報,不讓流程失敗)
|
||||||
|
echo "$CPP_FILES" | xargs -r "${TIDY_CMD_BASE[@]}"
|
||||||
|
|
||||||
echo "Linter check completed."
|
echo "Linter check completed."
|
@@ -0,0 +1,59 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# 安裝 git hooks(pre-commit)以執行 clang-format 與可選的 clang-tidy 提示
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
HOOKS_DIR=".git/hooks"
|
||||||
|
PRE_COMMIT="$HOOKS_DIR/pre-commit"
|
||||||
|
|
||||||
|
if [ ! -d "$HOOKS_DIR" ]; then
|
||||||
|
echo "This script must be run inside a Git repository."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat > "$PRE_COMMIT" <<'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
echo "[pre-commit] Checking/formatting C++ sources..."
|
||||||
|
|
||||||
|
# Collect staged C/C++ files
|
||||||
|
STAGED=$(git diff --cached --name-only --diff-filter=ACMR | grep -E '\.(cpp|cxx|cc|c\+\+|h|hpp|hxx)$' || true)
|
||||||
|
|
||||||
|
if [ -z "$STAGED" ]; then
|
||||||
|
echo "[pre-commit] No C/C++ files staged."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 1) clang-format in-place, then re-stage
|
||||||
|
if command -v clang-format >/dev/null 2>&1; then
|
||||||
|
echo "$STAGED" | xargs -r clang-format -i
|
||||||
|
echo "$STAGED" | xargs -r git add
|
||||||
|
else
|
||||||
|
echo "[pre-commit] clang-format not found; skipping formatting." >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If formatting changed files, fail once to let user review
|
||||||
|
CHANGES=$(git diff --name-only --diff-filter=ACMR | grep -E '\\.(cpp|cxx|cc|c\\+\\+|h|hpp|hxx)$' || true)
|
||||||
|
if [ -n "$CHANGES" ]; then
|
||||||
|
echo "[pre-commit] Formatting applied to:"
|
||||||
|
echo "$CHANGES"
|
||||||
|
echo "[pre-commit] Please review changes and re-commit."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 2) Optional clang-tidy advisory (Phase 1: do not block commits)
|
||||||
|
if command -v clang-tidy >/dev/null 2>&1; then
|
||||||
|
if [ -f build/compile_commands.json ]; then
|
||||||
|
echo "[pre-commit] Running clang-tidy (advisory)..."
|
||||||
|
echo "$STAGED" | xargs -r clang-tidy -p build --config-file=.clang-tidy || true
|
||||||
|
else
|
||||||
|
echo "[pre-commit] No build/compile_commands.json; skip clang-tidy. Run CMake with -DCMAKE_EXPORT_COMPILE_COMMANDS=ON."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x "$PRE_COMMIT"
|
||||||
|
echo "Installed pre-commit hook to $PRE_COMMIT"
|
||||||
|
@@ -0,0 +1,21 @@
|
|||||||
|
#include "utils.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::vector<int> v;
|
||||||
|
v.push_back(1);
|
||||||
|
v.push_back(2);
|
||||||
|
v.push_back(3);
|
||||||
|
int sum = calculateSum(v);
|
||||||
|
if (sum != 6) {
|
||||||
|
std::cerr << "Test failed: expected 6, got " << sum << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (!isPositive(1) || isPositive(-1)) {
|
||||||
|
std::cerr << "Test failed: isPositive check" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
std::cout << "All basic tests passed" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user