已合并
feat(pre-commit): 拦截类钩子报告统一落盘 pre-commit_reports + 健壮性与策略对齐 #12834
feat(pre-commit): 拦截类钩子报告统一落盘 pre-commit_reports + 健壮性与策略对齐 #12834
已合并
景明创建于 9月23日
共 8 个文件变更+58-28
@@ -1,5 +1,5 @@
1# -----------------------------------------------------------------------------------------------------------1# -----------------------------------------------------------------------------------------------------------
2-# Copyright (c) 2025 Huawei Technologies Co., Ltd.2+# Copyright (c) 2026 Huawei Technologies Co., Ltd.
3# This program is free software, you can redistribute it and/or modify it under the terms and conditions of3# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4# CANN Open Software License Agreement Version 2.0 (the "License").4# CANN Open Software License Agreement Version 2.0 (the "License").
5# Please refer to the License for details. You may not use this file except in compliance with the License.5# Please refer to the License for details. You may not use this file except in compliance with the License.
@@ -56,7 +56,7 @@ PackConstructorInitializers: Never
56 56 
57# pointer aligment57# pointer aligment
58DerivePointerAlignment: false58DerivePointerAlignment: false
59-PointerAlignment: Right59+PointerAlignment: Left
60 60 
61# single line layout61# single line layout
62AllowShortBlocksOnASingleLine: false62AllowShortBlocksOnASingleLine: false
@@ -51,4 +51,4 @@ third_party/
51 51 
52# pre-commit log52# pre-commit log
53log/53log/
54-oat_reports/54+pre-commit_reports/
@@ -21,6 +21,8 @@ repos:
21 rev: v4.6.021 rev: v4.6.0
22 hooks:22 hooks:
23 - id: trailing-whitespace23 - id: trailing-whitespace
24+ # md 保留行尾双空格(markdown 硬换行语法),其余尾随空白照删
25+ args: ["--markdown-linebreak-ext=md"]
24 - id: end-of-file-fixer26 - id: end-of-file-fixer
25 - id: check-yaml27 - id: check-yaml
26 args: ["--allow-multiple-documents"]28 args: ["--allow-multiple-documents"]
@@ -57,6 +59,8 @@ repos:
57 rev: v2.4.159 rev: v2.4.1
58 hooks:60 hooks:
59 - id: codespell61 - id: codespell
62+ # 包装 entry:输出 tee 到 pre-commit_reports/codespell.log(仍跑在托管 venv)
63+ entry: bash scripts/run_codespell.sh
60 args: [64 args: [
61 "-L",65 "-L",
62 "CANN,cann,NNAL,nnal,ASCEND,ascend,EnQue,CopyIn,ArchType,AND,ND,tbe,copyin,alog,wIh,dout,indexs,inH,padD,outWeight",66 "CANN,cann,NNAL,nnal,ASCEND,ascend,EnQue,CopyIn,ArchType,AND,ND,tbe,copyin,alog,wIh,dout,indexs,inH,padD,outWeight",
MOAT.xml+4-0
@@ -25,6 +25,8 @@
25 <!--filteritem type="filepath" name="projectroot/[a-zA-Z0-9]{20,}.sh" desc="Temp files"/-->25 <!--filteritem type="filepath" name="projectroot/[a-zA-Z0-9]{20,}.sh" desc="Temp files"/-->
26 </filefilter>26 </filefilter>
27 <filefilter name="defaultPolicyFilter" desc="Filters for compatibility,license header policies">27 <filefilter name="defaultPolicyFilter" desc="Filters for compatibility,license header policies">
28+ <filteritem type="filename" name="requirements*.txt" desc="Dependency manifest files, license header not applicable"/>
29+ <filteritem type="filename" name="*.info" desc="CMake help info files, no license header"/>
28 <!--filteritem type="filename" name="*.uvwxyz" desc="Describe the reason for filtering scan results"/-->30 <!--filteritem type="filename" name="*.uvwxyz" desc="Describe the reason for filtering scan results"/-->
29 <!--filteritem type="filepath" name="abcdefg/.*.uvwxyz" desc="Describe the reason for filtering scan results"/-->31 <!--filteritem type="filepath" name="abcdefg/.*.uvwxyz" desc="Describe the reason for filtering scan results"/-->
30 <!--filteritem type="filepath" name="projectroot/[a-zA-Z0-9]{20,}.sh" desc="Temp files"/-->32 <!--filteritem type="filepath" name="projectroot/[a-zA-Z0-9]{20,}.sh" desc="Temp files"/-->
@@ -33,6 +35,8 @@
33 <filteritem type="filename" name="*.csv" desc="CSV test case files, no license header required"/>35 <filteritem type="filename" name="*.csv" desc="CSV test case files, no license header required"/>
34 </filefilter>36 </filefilter>
35 <filefilter name="copyrightPolicyFilter" desc="Filters for copyright header policies">37 <filefilter name="copyrightPolicyFilter" desc="Filters for copyright header policies">
38+ <filteritem type="filename" name="requirements*.txt" desc="Dependency manifest files, copyright header not applicable"/>
39+ <filteritem type="filename" name="*.info" desc="CMake help info files, copyright header not applicable"/>
36 <!--filteritem type="filename" name="*.uvwxyz" desc="Describe the reason for filtering scan results"/-->40 <!--filteritem type="filename" name="*.uvwxyz" desc="Describe the reason for filtering scan results"/-->
37 <!--filteritem type="filepath" name="abcdefg/.*.uvwxyz" desc="Describe the reason for filtering scan results"/-->41 <!--filteritem type="filepath" name="abcdefg/.*.uvwxyz" desc="Describe the reason for filtering scan results"/-->
38 <!--filteritem type="filepath" name="projectroot/[a-zA-Z0-9]{20,}.sh" desc="Temp files"/-->42 <!--filteritem type="filepath" name="projectroot/[a-zA-Z0-9]{20,}.sh" desc="Temp files"/-->
@@ -75,6 +75,8 @@ git commit --no-verify -m "msg"
75 75 
76搜索输出中的 `Failed` 定位失败项,查看该 hook 下方输出处理,或粘贴给 AI 获取修复建议。76搜索输出中的 `Failed` 定位失败项,查看该 hook 下方输出处理,或粘贴给 AI 获取修复建议。
77 77 
78+拦截类钩子的报告同时落盘在 `pre-commit_reports/`(不入 git):`codespell.log`(拼写命中清单)、`oat_result.txt`(合规违规明细),可随时复查。
79+ 
78| 报错 | 原因 | 处理方式 |80| 报错 | 原因 | 处理方式 |
79|-----------------------|--------------------|---------------------------------------------------|81|-----------------------|--------------------|---------------------------------------------------|
80| clang-format Failed | 代码存在规范问题 | 钩子会自动修复文件,重新 `git add` 后再次 commit 即可 |82| clang-format Failed | 代码存在规范问题 | 钩子会自动修复文件,重新 `git add` 后再次 commit 即可 |
@@ -94,7 +96,7 @@ git pc <commit>^ # 某一笔提交
94## 七、检查项说明96## 七、检查项说明
95 97 
961. **pre-commit-hooks** (v4.6.0):trailing-whitespace、end-of-file-fixer、check-yaml/json、check-added-large-files、check-merge-conflict、detect-private-key981. **pre-commit-hooks** (v4.6.0):trailing-whitespace、end-of-file-fixer、check-yaml/json、check-added-large-files、check-merge-conflict、detect-private-key
97-2. **clang-format** (v18.1.8):遵循项目 `.clang-format`(Google 风格,4 空格缩进,不限列宽不自动拆行,枚举逐行,构造函数初始化列表逐行换行,函数定义大括号换行,指针右对齐 `int *ptr`)99+2. **clang-format** (v18.1.8):遵循项目 `.clang-format`(Google 风格,4 空格缩进,不限列宽不自动拆行,枚举逐行,构造函数初始化列表逐行换行,函数定义大括号换行,指针左对齐 `int* ptr`)
983. **ruff** (v0.14.14):ruff-check(`--fix` 自动修复)+ ruff-format1003. **ruff** (v0.14.14):ruff-check(`--fix` 自动修复)+ ruff-format
994. **codespell** (v2.4.1):拼写检查,CANN、ascend、EnQue 等术语已加白名单1014. **codespell** (v2.4.1):拼写检查,CANN、ascend、EnQue 等术语已加白名单
1005. **OAT**:基于 oat-py,检查许可证头(YAML/CSV 已豁免)、禁止二进制和归档文件1025. **OAT**:基于 oat-py,检查许可证头(YAML/CSV 已豁免)、禁止二进制和归档文件
@@ -16,7 +16,8 @@ REPO_ROOT=$(dirname "$SCRIPT_DIR")
16 16 
17FORMAT_DIR="${1:-${REPO_ROOT}}"17FORMAT_DIR="${1:-${REPO_ROOT}}"
18if [[ ! -d ${FORMAT_DIR} ]]; then18if [[ ! -d ${FORMAT_DIR} ]]; then
19- echo "Please specify a directory."19+ echo "Error: directory not found: ${FORMAT_DIR}" >&2
20+ exit 1
20fi21fi
21 22 
22CLANG_FORMAT="${CLANG_FORMAT:-clang-format}"23CLANG_FORMAT="${CLANG_FORMAT:-clang-format}"
@@ -36,10 +37,10 @@ echo "Using $CLANG_FORMAT ..."
36"$CLANG_FORMAT" --version37"$CLANG_FORMAT" --version
37 38 
38EXCLUDE_DIRS=(39EXCLUDE_DIRS=(
39- "build/"40+ "build"
40- "build_out/"41+ "build_out"
41- "third_party/"42+ "third_party"
42- ".git/"43+ ".git"
43)44)
44 45 
45FIND_EXPR=()46FIND_EXPR=()
@@ -82,14 +82,14 @@ fi
82REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)82REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
83REPO_NAME=$(basename "$REPO_ROOT")83REPO_NAME=$(basename "$REPO_ROOT")
84OAT_REPORT_DIR="${TMPDIR:-/tmp}/oat_reports_$$"84OAT_REPORT_DIR="${TMPDIR:-/tmp}/oat_reports_$$"
85-OAT_RESULT_DIR="$REPO_ROOT/oat_reports"85+OAT_RESULT_DIR="$REPO_ROOT/pre-commit_reports"
86 86 
87# ---------------------------------------------------------------------------87# ---------------------------------------------------------------------------
88# 2a. PR-range deduplication (pure git, no CI env vars required)88# 2a. PR-range deduplication (pure git, no CI env vars required)
89#89#
90# Strategy:90# Strategy:
91# 1. Find the merge-base between HEAD and the upstream branch (origin/master91# 1. Find the merge-base between HEAD and the upstream branch (origin/master
92-# or similar). If found, this is a feature-branch context ??collect ALL92+# or similar). If found, this is a feature-branch context →collect ALL
93# files changed since the branch diverged (full PR diff).93# files changed since the branch diverged (full PR diff).
94# 2. Key a done-marker on the HEAD SHA. The first invocation runs the scan;94# 2. Key a done-marker on the HEAD SHA. The first invocation runs the scan;
95# every subsequent invocation for the same HEAD exits 0 immediately.95# every subsequent invocation for the same HEAD exits 0 immediately.
@@ -134,6 +134,7 @@ if [ -n "$_HEAD_SHA" ]; then
134 if [ -n "$_PR_MERGE_BASE" ] && [ "$_PR_MERGE_BASE" != "$(git rev-parse HEAD 2>/dev/null)" ]; then134 if [ -n "$_PR_MERGE_BASE" ] && [ "$_PR_MERGE_BASE" != "$(git rev-parse HEAD 2>/dev/null)" ]; then
135 mkdir -p "$OAT_RESULT_DIR"135 mkdir -p "$OAT_RESULT_DIR"
136 _DONE_MARKER="$OAT_RESULT_DIR/.done_${_HEAD_SHA}"136 _DONE_MARKER="$OAT_RESULT_DIR/.done_${_HEAD_SHA}"
137+ # 显式文件清单调用永不跳过(args 模式扫的是 staged 子集,与全量 marker 无关)
137 if [ $# -eq 0 ] && [ -f "$_DONE_MARKER" ]; then138 if [ $# -eq 0 ] && [ -f "$_DONE_MARKER" ]; then
138 echo "[OAT] [SKIP] Already scanned HEAD=${_HEAD_SHA}. Skipping duplicate invocation."139 echo "[OAT] [SKIP] Already scanned HEAD=${_HEAD_SHA}. Skipping duplicate invocation."
139 exit 0140 exit 0
@@ -157,6 +158,7 @@ if command -v flock >/dev/null 2>&1; then
157 flock -w 120 9158 flock -w 120 9
158 # Re-check done marker: if the scanning instance completed normally, skip.159 # Re-check done marker: if the scanning instance completed normally, skip.
159 # If it exited abnormally (no marker), fall through and run the scan ourselves.160 # If it exited abnormally (no marker), fall through and run the scan ourselves.
161+ # 显式文件清单调用不参与并行去重
160 if [ $# -eq 0 ] && [ -n "$_DONE_MARKER" ] && [ -f "$_DONE_MARKER" ]; then162 if [ $# -eq 0 ] && [ -n "$_DONE_MARKER" ] && [ -f "$_DONE_MARKER" ]; then
161 echo "[OAT] Scan already completed by another instance. Skipping."163 echo "[OAT] Scan already completed by another instance. Skipping."
162 exit 0164 exit 0
@@ -167,12 +169,12 @@ if command -v flock >/dev/null 2>&1; then
167 # This instance now owns the lock and will run the scan.169 # This instance now owns the lock and will run the scan.
168fi170fi
169 171 
170-echo "[OAT] Running OAT scan (Python Edition) ??INCREMENTAL MODE"172+echo "[OAT] Running OAT scan (Python Edition) →INCREMENTAL MODE"
171echo "[OAT] Project: $REPO_NAME"173echo "[OAT] Project: $REPO_NAME"
172if [ -n "$_PR_MERGE_BASE" ]; then174if [ -n "$_PR_MERGE_BASE" ]; then
173- echo "[OAT] Mode: PR range ??scanning all files changed since merge-base"175+ echo "[OAT] Mode: PR range →scanning all files changed since merge-base"
174else176else
175- echo "[OAT] Mode: staged files ??scanning only currently staged files"177+ echo "[OAT] Mode: staged files →scanning only currently staged files"
176fi178fi
177 179 
178# ---------------------------------------------------------------------------180# ---------------------------------------------------------------------------
@@ -255,27 +257,27 @@ mkdir -p "$OAT_REPORT_DIR"
255mkdir -p "$OAT_RESULT_DIR"257mkdir -p "$OAT_RESULT_DIR"
256 258 
257# ---------------------------------------------------------------------------259# ---------------------------------------------------------------------------
258-# 5. Build oat command — use OAT.xml if present in repo root260+# 5. Build oat command →use OAT.xml if present in repo root
259# ---------------------------------------------------------------------------261# ---------------------------------------------------------------------------
260-_OAT_BASE_CMD="$_PYTHON -m oat -mode s -s $REPO_ROOT -r $OAT_REPORT_DIR -n $REPO_NAME -w 1"262+_OAT_ARGS=(-mode s -s "$REPO_ROOT" -r "$OAT_REPORT_DIR" -n "$REPO_NAME" -w 1)
261 263 
262_OAT_XML="$REPO_ROOT/OAT.xml"264_OAT_XML="$REPO_ROOT/OAT.xml"
263if [ -f "$_OAT_XML" ]; then265if [ -f "$_OAT_XML" ]; then
264- _OAT_BASE_CMD="$_OAT_BASE_CMD -oatconfig $_OAT_XML"266+ _OAT_ARGS+=(-oatconfig "$_OAT_XML")
265fi267fi
266 268 
267# ---------------------------------------------------------------------------269# ---------------------------------------------------------------------------
268-# 6. Run oat scan — batch file list if -f argument exceeds OS single-arg limit270+# 6. Run oat scan
269-# (Linux MAX_ARG_STRLEN ≈ 128KB; exit code 126 = E2BIG when exceeded)
270# ---------------------------------------------------------------------------271# ---------------------------------------------------------------------------
271_MAX_F_LEN=120000272_MAX_F_LEN=120000
272_SCAN_FAILED=0273_SCAN_FAILED=0
273_BATCH_ISSUES=0274_BATCH_ISSUES=0
275+_BATCH_COUNT=0
274 276 
275_run_oat_batch() {277_run_oat_batch() {
276 echo "[OAT] Running compliance scan..."278 echo "[OAT] Running compliance scan..."
277 set +e279 set +e
278- eval "$_OAT_BASE_CMD -f $1" >/dev/null 2>&1280+ "$_PYTHON" -m oat "${_OAT_ARGS[@]}" -f "$1" >/dev/null 2>&1
279 _OAT_RC=$?281 _OAT_RC=$?
280 set -e282 set -e
281 if [ "$_OAT_RC" -ne 0 ] && [ "$_OAT_RC" -ne 1 ]; then283 if [ "$_OAT_RC" -ne 0 ] && [ "$_OAT_RC" -ne 1 ]; then
@@ -302,7 +304,6 @@ else
302 echo "[OAT] File list exceeds ${_MAX_F_LEN} bytes, scanning in batches..."304 echo "[OAT] File list exceeds ${_MAX_F_LEN} bytes, scanning in batches..."
303 rm -f "$OAT_RESULT_DIR/batch_details.txt" 2>/dev/null || true305 rm -f "$OAT_RESULT_DIR/batch_details.txt" 2>/dev/null || true
304 _BATCH=""306 _BATCH=""
305- _BATCH_COUNT=0
306 _IFS_BAK="$IFS"307 _IFS_BAK="$IFS"
307 IFS=","308 IFS=","
308 for _f in $FILE_LIST; do309 for _f in $FILE_LIST; do
@@ -340,7 +341,7 @@ if [ "$_SCAN_FAILED" -ne 0 ]; then
340fi341fi
341 342 
342# Batch mode: use accumulated issue count to decide343# Batch mode: use accumulated issue count to decide
343-if [ -n "$_BATCH_COUNT" ] && [ "$_BATCH_COUNT" -gt 1 ] 2>/dev/null; then344+if [ "$_BATCH_COUNT" -gt 1 ] 2>/dev/null; then
344 if [ "$_BATCH_ISSUES" -gt 0 ]; then345 if [ "$_BATCH_ISSUES" -gt 0 ]; then
345 echo ""346 echo ""
346 echo "===================================================================="347 echo "===================================================================="
@@ -362,11 +363,11 @@ if [ -n "$_BATCH_COUNT" ] && [ "$_BATCH_COUNT" -gt 1 ] 2>/dev/null; then
362 cat "$OAT_RESULT_DIR/batch_details.txt"363 cat "$OAT_RESULT_DIR/batch_details.txt"
363 fi364 fi
364 echo "==================================="365 echo "==================================="
365- } > "$OAT_RESULT_DIR/result.txt"366+ } > "$OAT_RESULT_DIR/oat_result.txt"
366 echo "[OAT] Found $_BATCH_ISSUES compliance issue(s) across $_BATCH_COUNT batches."367 echo "[OAT] Found $_BATCH_ISSUES compliance issue(s) across $_BATCH_COUNT batches."
367 echo "[OAT] Details (also saved to: $OAT_RESULT_DIR/batch_details.txt):"368 echo "[OAT] Details (also saved to: $OAT_RESULT_DIR/batch_details.txt):"
368 echo "---"369 echo "---"
369- cat "$OAT_RESULT_DIR/result.txt"370+ cat "$OAT_RESULT_DIR/oat_result.txt"
370 echo "---"371 echo "---"
371 echo ""372 echo ""
372 echo "Fix the issues and recommit, or skip with:"373 echo "Fix the issues and recommit, or skip with:"
@@ -391,7 +392,7 @@ fi
391# Only: Invalid File Type + License Header Invalid (no copyright)392# Only: Invalid File Type + License Header Invalid (no copyright)
392# ---------------------------------------------------------------------------393# ---------------------------------------------------------------------------
393REPORT_FILE="$OAT_REPORT_DIR/PlainReport_${REPO_NAME}.txt"394REPORT_FILE="$OAT_REPORT_DIR/PlainReport_${REPO_NAME}.txt"
394-RESULT_FILE="$OAT_RESULT_DIR/result.txt"395+RESULT_FILE="$OAT_RESULT_DIR/oat_result.txt"
395 396 
396# Section headers used as stop-boundaries when extracting sections397# Section headers used as stop-boundaries when extracting sections
397_ALL_HEADERS="Invalid File Type Total Count:|License Not Compatible Total Count:|License Header Invalid Total Count:|Copyright Header Invalid Total Count:|No License File Total Count:|No Readme.OpenSource Total Count:|No Readme Total Count:|Import Invalid Total Count:|Redundant License File Total Count:|Third Party Software Info Total Count:"398_ALL_HEADERS="Invalid File Type Total Count:|License Not Compatible Total Count:|License Header Invalid Total Count:|Copyright Header Invalid Total Count:|No License File Total Count:|No Readme.OpenSource Total Count:|No Readme Total Count:|Import Invalid Total Count:|Redundant License File Total Count:|Third Party Software Info Total Count:"
@@ -424,7 +425,9 @@ if [ ! -f "$REPORT_FILE" ]; then
424 if [ "$_OAT_RC" -eq 0 ]; then425 if [ "$_OAT_RC" -eq 0 ]; then
425 # oat exited cleanly with no report: all staged files were filtered out426 # oat exited cleanly with no report: all staged files were filtered out
426 echo "[OAT] [OK] All checks passed ($FILE_COUNT file(s) checked)."427 echo "[OAT] [OK] All checks passed ($FILE_COUNT file(s) checked)."
427- [ -n "$_DONE_MARKER" ] && touch "$_DONE_MARKER" 2>/dev/null || true428+ if [ $# -eq 0 ] && [ -n "$_DONE_MARKER" ]; then
429+ touch "$_DONE_MARKER" 2>/dev/null || true
430+ fi
428 rm -rf "$OAT_REPORT_DIR"431 rm -rf "$OAT_REPORT_DIR"
429 exit 0432 exit 0
430 else433 else
@@ -434,7 +437,7 @@ if [ ! -f "$REPORT_FILE" ]; then
434 echo "[OAT] [ERROR] oat exited with code $_OAT_RC but no report was generated."437 echo "[OAT] [ERROR] oat exited with code $_OAT_RC but no report was generated."
435 echo "[OAT] This may indicate a disk error or an oat internal bug."438 echo "[OAT] This may indicate a disk error or an oat internal bug."
436 echo "[OAT] To investigate, run manually:"439 echo "[OAT] To investigate, run manually:"
437- echo " $_OAT_CMD"440+ echo " python3 -m oat -mode s -s <repo> -f <files>"
438 echo "[OAT] Blocking commit to prevent silent compliance bypass."441 echo "[OAT] Blocking commit to prevent silent compliance bypass."
439 echo ""442 echo ""
440 rm -rf "$OAT_REPORT_DIR"443 rm -rf "$OAT_REPORT_DIR"
@@ -442,7 +445,7 @@ if [ ! -f "$REPORT_FILE" ]; then
442 fi445 fi
443fi446fi
444 447 
445-# Parse counts ??use || true to prevent set -e from triggering if grep finds no match448+# Parse counts →use || true to prevent set -e from triggering if grep finds no match
446_INVALID_TYPE=$(grep "^Invalid File Type Total Count:" "$REPORT_FILE" | grep -oE '[0-9]+' | head -1 || true)449_INVALID_TYPE=$(grep "^Invalid File Type Total Count:" "$REPORT_FILE" | grep -oE '[0-9]+' | head -1 || true)
447_LICENSE_INVALID=$(grep "^License Header Invalid Total Count:" "$REPORT_FILE" | grep -oE '[0-9]+' | head -1 || true)450_LICENSE_INVALID=$(grep "^License Header Invalid Total Count:" "$REPORT_FILE" | grep -oE '[0-9]+' | head -1 || true)
448_INVALID_TYPE=${_INVALID_TYPE:-0}451_INVALID_TYPE=${_INVALID_TYPE:-0}
@@ -505,6 +508,7 @@ echo "[OAT] [OK] All checks passed ($FILE_COUNT file(s) checked)."
505echo "[OAT] Summary: cat $RESULT_FILE"508echo "[OAT] Summary: cat $RESULT_FILE"
506echo ""509echo ""
507# Mark scan as done for CI range mode (prevents redundant re-runs on same PR head)510# Mark scan as done for CI range mode (prevents redundant re-runs on same PR head)
511+# 仅无参 PR-range 全量扫描才落 marker;args 模式(staged 子集)不得冒充全量覆盖
508if [ $# -eq 0 ] && [ -n "$_DONE_MARKER" ]; then512if [ $# -eq 0 ] && [ -n "$_DONE_MARKER" ]; then
509 touch "$_DONE_MARKER" 2>/dev/null || true513 touch "$_DONE_MARKER" 2>/dev/null || true
510 echo "[OAT] Done-marker created: $_DONE_MARKER"514 echo "[OAT] Done-marker created: $_DONE_MARKER"
@@ -0,0 +1,15 @@
1+#!/bin/bash
2+# -----------------------------------------------------------------------------------------------------------
3+# Copyright (c) 2026 Huawei Technologies Co., Ltd.
4+# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
5+# CANN Open Software License Agreement Version 2.0 (the "License").
6+# Please refer to the License for details. You may not use this file except in compliance with the License.
7+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
8+# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
9+# See LICENSE in the root of the software repository for the full text of the License.
10+# -----------------------------------------------------------------------------------------------------------
11+# codespell 输出留证:终端打印的同时写入 pre-commit_reports/codespell.log
12+REPORT_DIR="pre-commit_reports"
13+mkdir -p "$REPORT_DIR"
14+codespell "$@" 2>&1 | tee "$REPORT_DIR/codespell.log"
15+exit "${PIPESTATUS[0]}"