✨ feat(sync_standards): default gitattributes to append
This commit is contained in:
parent
da0ef2b7a2
commit
e97fb00649
11
README.md
11
README.md
|
|
@ -153,13 +153,12 @@ git commit -m ":package: deps(playbook): add tsl standards"
|
|||
- 规则入口可读:`.agents/tsl/index.md`
|
||||
- (可选)C++ 规则入口可读:`.agents/cpp/index.md`
|
||||
- 标准文档可读:`docs/standards/playbook/docs/index.md`
|
||||
- `.gitattributes` 包含区块:`# BEGIN playbook .gitattributes` /
|
||||
`# END playbook .gitattributes`
|
||||
- `.gitattributes` 包含追加块头:`# Added from playbook .gitattributes`
|
||||
|
||||
4. 将同步产物纳入版本控制(目标项目建议提交):
|
||||
- `docs/standards/playbook/`(标准快照)
|
||||
- `.agents/tsl/`(落地规则集)
|
||||
- `.gitattributes`(managed block 更新)
|
||||
- `.gitattributes`(追加缺失规则)
|
||||
- `AGENTS.md`(若本次自动生成)
|
||||
|
||||
#### 新项目 / 旧项目(命令示例)
|
||||
|
|
@ -240,8 +239,8 @@ sh docs/standards/playbook/scripts/sync_standards.sh tsl cpp
|
|||
同步脚本行为(目标项目内的最终落地内容):
|
||||
|
||||
- 覆盖/更新:`.agents/<AGENTS_NS>/`(默认 `.agents/tsl/`)
|
||||
- 更新 `.gitattributes`:默认只维护 `# BEGIN playbook .gitattributes` 区块(可用
|
||||
`SYNC_GITATTR_MODE=block|overwrite|skip` 控制)
|
||||
- 更新 `.gitattributes`:默认追加缺失规则(可用
|
||||
`SYNC_GITATTR_MODE=append|block|overwrite|skip` 控制)
|
||||
- 缺省创建:`.agents/index.md`
|
||||
- 覆盖前备份:写入同目录的 `*.bak.*`(或 Windows 下随机后缀)
|
||||
- 不修改:`.gitignore`(项目自行维护)
|
||||
|
|
@ -256,7 +255,7 @@ sh docs/standards/playbook/scripts/sync_standards.sh tsl cpp
|
|||
| 变量名 | 默认值 | 说明 |
|
||||
| ------------------- | ------- | ------------------------------------------------------------------------------------------- |
|
||||
| `AGENTS_NS` | `tsl` | 同步的规则集名/落地目录名:`.agents/<AGENTS_NS>/`(例如 `tsl`、`cpp`) |
|
||||
| `SYNC_GITATTR_MODE` | `block` | `.gitattributes` 同步模式:`block` 仅维护 managed 区块;`overwrite` 全量覆盖;`skip` 不更新 |
|
||||
| `SYNC_GITATTR_MODE` | `append` | `.gitattributes` 同步模式:`append` 仅追加缺失规则(忽略注释/空行,比对后按块追加);`block` 仅维护 managed 区块;`overwrite` 全量覆盖;`skip` 不更新 |
|
||||
|
||||
</details>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ setlocal enabledelayedexpansion
|
|||
|
||||
rem Sync standards snapshot to project root.
|
||||
rem - Copies <snapshot>\.agents\<AGENTS_NS> -> <project-root>\.agents\<AGENTS_NS>
|
||||
rem - Updates <project-root>\.gitattributes (managed block by default)
|
||||
rem - Updates <project-root>\.gitattributes (append missing rules by default)
|
||||
rem Existing targets are backed up before overwrite.
|
||||
rem
|
||||
rem Multi rulesets:
|
||||
|
|
@ -34,7 +34,7 @@ set "AGENTS_ROOT=%ROOT%\.agents"
|
|||
set "AGENTS_DST=%AGENTS_ROOT%\%AGENTS_NS%"
|
||||
set "GITATTR_DST=%ROOT%\.gitattributes"
|
||||
set "SYNC_GITATTR_MODE=%SYNC_GITATTR_MODE%"
|
||||
if "%SYNC_GITATTR_MODE%"=="" set "SYNC_GITATTR_MODE=block"
|
||||
if "%SYNC_GITATTR_MODE%"=="" set "SYNC_GITATTR_MODE=append"
|
||||
|
||||
rem Multi rulesets: only on outer invocation.
|
||||
if "%SYNC_STANDARDS_INNER%"=="" (
|
||||
|
|
@ -155,8 +155,84 @@ if exist "%GITATTR_SRC%" (
|
|||
goto AfterGitAttr
|
||||
)
|
||||
|
||||
if /I "%SYNC_GITATTR_MODE%"=="append" (
|
||||
for %%I in ("%GITATTR_SRC%") do set "GITATTR_SRC_F=%%~fI"
|
||||
for %%I in ("%GITATTR_DST%") do set "GITATTR_DST_F=%%~fI"
|
||||
if /I "!GITATTR_SRC_F!"=="!GITATTR_DST_F!" (
|
||||
echo Skip: .gitattributes source equals destination.
|
||||
goto AfterGitAttr
|
||||
)
|
||||
|
||||
set "TMP_DST=%TEMP%\\gitattributes.dst.%RANDOM%.tmp"
|
||||
set "TMP_MISS=%TEMP%\\gitattributes.missing.%RANDOM%.tmp"
|
||||
if exist "!TMP_DST!" del /q "!TMP_DST!" >nul 2>nul
|
||||
if exist "!TMP_MISS!" del /q "!TMP_MISS!" >nul 2>nul
|
||||
type nul > "!TMP_DST!"
|
||||
type nul > "!TMP_MISS!"
|
||||
|
||||
if exist "%GITATTR_DST%" (
|
||||
for /f "usebackq delims=" %%L in ("%GITATTR_DST%") do (
|
||||
set "LINE=%%L"
|
||||
for /f "tokens=* delims= " %%A in ("!LINE!") do set "LINE=%%A"
|
||||
if not "!LINE!"=="" (
|
||||
if /I not "!LINE:~0,1!"=="#" (
|
||||
echo(!LINE!>>"!TMP_DST!"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
for /f "usebackq delims=" %%L in ("%GITATTR_SRC%") do (
|
||||
set "LINE=%%L"
|
||||
for /f "tokens=* delims= " %%A in ("!LINE!") do set "LINE=%%A"
|
||||
if not "!LINE!"=="" (
|
||||
if /I not "!LINE:~0,1!"=="#" (
|
||||
findstr /x /l /c:"!LINE!" "!TMP_DST!" >nul || (
|
||||
findstr /x /l /c:"!LINE!" "!TMP_MISS!" >nul || echo(!LINE!>>"!TMP_MISS!"
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
set "MISS_SIZE=0"
|
||||
if exist "!TMP_MISS!" for %%S in ("!TMP_MISS!") do set "MISS_SIZE=%%~zS"
|
||||
if "!MISS_SIZE!"=="0" (
|
||||
del /q "!TMP_DST!" "!TMP_MISS!" >nul 2>nul
|
||||
echo No missing .gitattributes rules to append.
|
||||
goto AfterGitAttr
|
||||
)
|
||||
|
||||
if exist "%GITATTR_DST%" (
|
||||
set "RAND=%RANDOM%"
|
||||
set "BAK_NAME=.gitattributes.bak.!RAND!"
|
||||
ren "%GITATTR_DST%" "!BAK_NAME!"
|
||||
echo Backed up existing .gitattributes -> !BAK_NAME!
|
||||
set "DST_IN=%ROOT%\\!BAK_NAME!"
|
||||
) else (
|
||||
set "DST_IN="
|
||||
)
|
||||
|
||||
set "TMP_OUT=%TEMP%\\gitattributes.out.%RANDOM%.tmp"
|
||||
if exist "!TMP_OUT!" del /q "!TMP_OUT!" >nul 2>nul
|
||||
|
||||
if not "!DST_IN!"=="" (
|
||||
type "!DST_IN!" > "!TMP_OUT!"
|
||||
for %%S in ("!DST_IN!") do set "DST_SIZE=%%~zS"
|
||||
if not "!DST_SIZE!"=="0" echo.>>"!TMP_OUT!"
|
||||
)
|
||||
|
||||
set "SOURCE_NOTE=%GITATTR_SRC%"
|
||||
>>"!TMP_OUT!" echo # Added from playbook .gitattributes ^(source: !SOURCE_NOTE!^)
|
||||
type "!TMP_MISS!" >> "!TMP_OUT!"
|
||||
|
||||
copy /y "!TMP_OUT!" "%GITATTR_DST%" >nul
|
||||
del /q "!TMP_DST!" "!TMP_MISS!" "!TMP_OUT!" >nul 2>nul
|
||||
echo Appended missing .gitattributes rules from standards.
|
||||
goto AfterGitAttr
|
||||
)
|
||||
|
||||
if /I not "%SYNC_GITATTR_MODE%"=="block" (
|
||||
echo ERROR: invalid SYNC_GITATTR_MODE=%SYNC_GITATTR_MODE% ^(use block^|overwrite^|skip^)
|
||||
echo ERROR: invalid SYNC_GITATTR_MODE=%SYNC_GITATTR_MODE% ^(use block^|overwrite^|append^|skip^)
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Sync standards snapshot to project root.
|
||||
# - Copies <snapshot>/.agents/<AGENTS_NS> -> <project-root>/.agents/<AGENTS_NS>
|
||||
# - Updates <project-root>/.gitattributes (managed block by default)
|
||||
# - Updates <project-root>/.gitattributes (append missing rules by default)
|
||||
# Existing targets are backed up before overwrite.
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
|
|
@ -38,7 +38,7 @@ if (-not $env:SYNC_STANDARDS_INNER -and $Langs -and $Langs.Count -gt 0) {
|
|||
$oldMode = $env:SYNC_GITATTR_MODE
|
||||
|
||||
$syncModeFirst = $env:SYNC_GITATTR_MODE
|
||||
if (-not $syncModeFirst) { $syncModeFirst = "block" }
|
||||
if (-not $syncModeFirst) { $syncModeFirst = "append" }
|
||||
|
||||
$first = $true
|
||||
foreach ($ns in $Langs) {
|
||||
|
|
@ -136,7 +136,7 @@ if (-not (Test-Path $AgentsMd)) {
|
|||
$GitAttrDst = Join-Path $Root ".gitattributes"
|
||||
if (Test-Path $GitAttrSrc) {
|
||||
$mode = $env:SYNC_GITATTR_MODE
|
||||
if (-not $mode) { $mode = "block" }
|
||||
if (-not $mode) { $mode = "append" }
|
||||
switch ($mode.ToLowerInvariant()) {
|
||||
"skip" {
|
||||
Write-Host "Skip: .gitattributes sync (SYNC_GITATTR_MODE=skip)."
|
||||
|
|
@ -156,6 +156,65 @@ if (Test-Path $GitAttrSrc) {
|
|||
Write-Host "Synced .gitattributes from standards (overwrite)."
|
||||
break
|
||||
}
|
||||
"append" {
|
||||
if ($GitAttrSrc -ieq $GitAttrDst) {
|
||||
Write-Host "Skip: .gitattributes source equals destination."
|
||||
break
|
||||
}
|
||||
|
||||
$dstLines = @{}
|
||||
if (Test-Path $GitAttrDst) {
|
||||
Get-Content $GitAttrDst | ForEach-Object {
|
||||
$line = $_.Trim()
|
||||
if ($line -eq "" -or $line.StartsWith("#")) { return }
|
||||
$dstLines[$line] = $true
|
||||
}
|
||||
}
|
||||
|
||||
$missing = New-Object System.Collections.Generic.List[string]
|
||||
Get-Content $GitAttrSrc | ForEach-Object {
|
||||
$line = $_.Trim()
|
||||
if ($line -eq "" -or $line.StartsWith("#")) { return }
|
||||
if (-not $dstLines.ContainsKey($line)) {
|
||||
$dstLines[$line] = $true
|
||||
$missing.Add($line)
|
||||
}
|
||||
}
|
||||
|
||||
if ($missing.Count -eq 0) {
|
||||
Write-Host "No missing .gitattributes rules to append."
|
||||
break
|
||||
}
|
||||
|
||||
$bak = $null
|
||||
if (Test-Path $GitAttrDst) {
|
||||
$bak = "$GitAttrDst.bak.$timestamp"
|
||||
Move-Item $GitAttrDst $bak -Force
|
||||
Write-Host "Backed up existing .gitattributes -> $bak"
|
||||
}
|
||||
|
||||
$sourceNote = $GitAttrSrc
|
||||
$rootPrefix = "$Root\"
|
||||
if ($sourceNote.StartsWith($rootPrefix)) {
|
||||
$sourceNote = $sourceNote.Substring($rootPrefix.Length)
|
||||
}
|
||||
$header = "# Added from playbook .gitattributes (source: $sourceNote)"
|
||||
|
||||
$content = @()
|
||||
if ($bak -and (Test-Path $bak)) {
|
||||
$existing = Get-Content $bak
|
||||
if ($existing.Count -gt 0) {
|
||||
$content += $existing
|
||||
$content += ""
|
||||
}
|
||||
}
|
||||
$content += $header
|
||||
$content += $missing
|
||||
$content | Set-Content -Path $GitAttrDst -Encoding UTF8
|
||||
|
||||
Write-Host "Appended missing .gitattributes rules from standards."
|
||||
break
|
||||
}
|
||||
"block" {
|
||||
$begin = "# BEGIN playbook .gitattributes"
|
||||
$end = "# END playbook .gitattributes"
|
||||
|
|
@ -186,7 +245,7 @@ if (Test-Path $GitAttrSrc) {
|
|||
break
|
||||
}
|
||||
default {
|
||||
throw "Invalid SYNC_GITATTR_MODE=$mode (use block|overwrite|skip)"
|
||||
throw "Invalid SYNC_GITATTR_MODE=$mode (use block|overwrite|append|skip)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ set -eu
|
|||
|
||||
# Sync standards snapshot to project root.
|
||||
# - Copies <snapshot>/.agents/<AGENTS_NS> -> <project-root>/.agents/<AGENTS_NS>
|
||||
# - Updates <project-root>/.gitattributes (managed block by default)
|
||||
# - Updates <project-root>/.gitattributes (append missing rules by default)
|
||||
# Existing targets are backed up before overwrite.
|
||||
#
|
||||
# Multi rulesets:
|
||||
|
|
@ -48,7 +48,7 @@ if [ "${SYNC_STANDARDS_INNER:-}" != "1" ]; then
|
|||
langs="$*"
|
||||
fi
|
||||
if [ -n "${langs:-}" ]; then
|
||||
sync_mode_first="${SYNC_GITATTR_MODE:-block}"
|
||||
sync_mode_first="${SYNC_GITATTR_MODE:-append}"
|
||||
|
||||
first=1
|
||||
old_ifs="${IFS}"
|
||||
|
|
@ -141,7 +141,7 @@ echo "Synced agents ruleset to $AGENTS_DST."
|
|||
|
||||
GITATTR_DST="$ROOT/.gitattributes"
|
||||
if [ -f "$GITATTR_SRC" ]; then
|
||||
: "${SYNC_GITATTR_MODE:=block}"
|
||||
: "${SYNC_GITATTR_MODE:=append}"
|
||||
case "$SYNC_GITATTR_MODE" in
|
||||
skip)
|
||||
echo "Skip: .gitattributes sync (SYNC_GITATTR_MODE=skip)."
|
||||
|
|
@ -158,6 +158,66 @@ if [ -f "$GITATTR_SRC" ]; then
|
|||
echo "Synced .gitattributes from standards (overwrite)."
|
||||
fi
|
||||
;;
|
||||
append)
|
||||
if [ "$(CDPATH= cd -- "$(dirname -- "$GITATTR_SRC")" && pwd -P)/$(basename -- "$GITATTR_SRC")" = "$GITATTR_DST" ]; then
|
||||
echo "Skip: .gitattributes source equals destination."
|
||||
else
|
||||
if [ -f "$GITATTR_DST" ]; then
|
||||
dst_file="$GITATTR_DST"
|
||||
else
|
||||
dst_file="/dev/null"
|
||||
fi
|
||||
missing_tmp="$(mktemp 2>/dev/null || echo "$ROOT/.gitattributes.missing.$timestamp")"
|
||||
awk '
|
||||
function norm(line) {
|
||||
gsub(/^[ \t]+|[ \t]+$/, "", line)
|
||||
return line
|
||||
}
|
||||
FNR==NR {
|
||||
line=norm($0)
|
||||
if (line == "" || line ~ /^#/) next
|
||||
seen[line]=1
|
||||
next
|
||||
}
|
||||
{
|
||||
line=norm($0)
|
||||
if (line == "" || line ~ /^#/) next
|
||||
if (!seen[line] && !out[line]++) print line
|
||||
}
|
||||
' "$dst_file" "$GITATTR_SRC" >"$missing_tmp"
|
||||
|
||||
if [ ! -s "$missing_tmp" ]; then
|
||||
rm -f "$missing_tmp"
|
||||
echo "No missing .gitattributes rules to append."
|
||||
echo "Done."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ -e "$GITATTR_DST" ]; then
|
||||
mv "$GITATTR_DST" "$ROOT/.gitattributes.bak.$timestamp"
|
||||
echo "Backed up existing .gitattributes -> .gitattributes.bak.$timestamp"
|
||||
fi
|
||||
|
||||
source_note="$GITATTR_SRC"
|
||||
case "$GITATTR_SRC" in
|
||||
"$ROOT"/*) source_note="${GITATTR_SRC#$ROOT/}" ;;
|
||||
esac
|
||||
header="# Added from playbook .gitattributes (source: $source_note)"
|
||||
|
||||
{
|
||||
if [ -f "$ROOT/.gitattributes.bak.$timestamp" ]; then
|
||||
cat "$ROOT/.gitattributes.bak.$timestamp"
|
||||
if [ -s "$ROOT/.gitattributes.bak.$timestamp" ]; then
|
||||
printf "\n"
|
||||
fi
|
||||
fi
|
||||
printf "%s\n" "$header"
|
||||
cat "$missing_tmp"
|
||||
} >"$GITATTR_DST"
|
||||
rm -f "$missing_tmp"
|
||||
echo "Appended missing .gitattributes rules from standards."
|
||||
fi
|
||||
;;
|
||||
block)
|
||||
begin="# BEGIN playbook .gitattributes"
|
||||
end="# END playbook .gitattributes"
|
||||
|
|
@ -207,7 +267,7 @@ if [ -f "$GITATTR_SRC" ]; then
|
|||
echo "Updated .gitattributes from standards (managed block)."
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: invalid SYNC_GITATTR_MODE=$SYNC_GITATTR_MODE (use block|overwrite|skip)" >&2
|
||||
echo "ERROR: invalid SYNC_GITATTR_MODE=$SYNC_GITATTR_MODE (use block|overwrite|append|skip)" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ sh check_doc_links.sh
|
|||
- 单语言同步(tsl/cpp)
|
||||
- 多语言同步(tsl cpp)
|
||||
- **.gitattributes 同步**:
|
||||
- 默认模式创建 managed block
|
||||
- 默认模式追加缺失规则
|
||||
- 保留现有内容
|
||||
- 更新已存在的 managed block
|
||||
- **AGENTS.md 处理**:
|
||||
|
|
|
|||
|
|
@ -81,15 +81,15 @@ teardown() {
|
|||
# .gitattributes 同步测试
|
||||
# ==============================================
|
||||
|
||||
@test ".gitattributes - 默认模式创建 managed block" {
|
||||
@test ".gitattributes - 默认模式追加缺失规则" {
|
||||
cd "$TEST_DIR"
|
||||
[ ! -f ".gitattributes" ]
|
||||
|
||||
sh "$SCRIPT_PATH" tsl
|
||||
|
||||
[ -f ".gitattributes" ]
|
||||
grep -q "# BEGIN playbook .gitattributes" .gitattributes
|
||||
grep -q "# END playbook .gitattributes" .gitattributes
|
||||
grep -q "Added from playbook .gitattributes" .gitattributes
|
||||
grep -q "\\*.tsl" .gitattributes
|
||||
}
|
||||
|
||||
@test ".gitattributes - 保留现有内容" {
|
||||
|
|
@ -111,6 +111,7 @@ teardown() {
|
|||
# END playbook .gitattributes
|
||||
EOF
|
||||
|
||||
export SYNC_GITATTR_MODE=block
|
||||
sh "$SCRIPT_PATH" tsl
|
||||
|
||||
# 验证 block 已更新(不再包含 "Old content")
|
||||
|
|
@ -232,6 +233,27 @@ EOF
|
|||
! grep -q "# Custom content" .gitattributes
|
||||
}
|
||||
|
||||
@test "环境变量 - SYNC_GITATTR_MODE=append 追加缺失规则" {
|
||||
cd "$TEST_DIR"
|
||||
echo "# Custom rules only" > .gitattributes
|
||||
export SYNC_GITATTR_MODE=append
|
||||
|
||||
sh "$SCRIPT_PATH" tsl
|
||||
|
||||
grep -q "Added from playbook .gitattributes" .gitattributes
|
||||
grep -q "\\*.tsl" .gitattributes
|
||||
}
|
||||
|
||||
@test "环境变量 - SYNC_GITATTR_MODE=append 无缺失规则不追加" {
|
||||
cd "$TEST_DIR"
|
||||
cp "$PLAYBOOK_ROOT/.gitattributes" .gitattributes
|
||||
export SYNC_GITATTR_MODE=append
|
||||
|
||||
sh "$SCRIPT_PATH" tsl
|
||||
|
||||
! grep -q "Added from playbook .gitattributes" .gitattributes
|
||||
}
|
||||
|
||||
# ==============================================
|
||||
# 幂等性测试
|
||||
# ==============================================
|
||||
|
|
|
|||
Loading…
Reference in New Issue