🐛 fix(sync_standards): preserve project gitattributes and clarify tsl/tsf
- default to managed .gitattributes block (block/overwrite/skip) - ensure .agents/tsl points to docs/standards/tsl snapshot paths - document expected structure and TSL/TSF constraints
This commit is contained in:
@@ -3,7 +3,7 @@ setlocal enabledelayedexpansion
|
||||
|
||||
rem Sync standards snapshot to project root.
|
||||
rem - Copies <snapshot>\.agents -> <project-root>\.agents\tsl
|
||||
rem - Copies <snapshot>\.gitattributes -> <project-root>\.gitattributes
|
||||
rem - Updates <project-root>\.gitattributes (managed block by default)
|
||||
rem Existing targets are backed up before overwrite.
|
||||
|
||||
set "SCRIPT_DIR=%~dp0"
|
||||
@@ -16,9 +16,19 @@ set "AGENTS_SRC=%SRC%\.agents"
|
||||
set "GITATTR_SRC=%SRC%\.gitattributes"
|
||||
set "AGENTS_NS=%AGENTS_NS%"
|
||||
if "%AGENTS_NS%"=="" set "AGENTS_NS=tsl"
|
||||
echo %AGENTS_NS%| findstr /r "[\\/]" >nul && (
|
||||
echo ERROR: invalid AGENTS_NS=%AGENTS_NS%
|
||||
exit /b 1
|
||||
)
|
||||
echo %AGENTS_NS%| findstr /c:".." >nul && (
|
||||
echo ERROR: invalid AGENTS_NS=%AGENTS_NS%
|
||||
exit /b 1
|
||||
)
|
||||
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 not exist "%AGENTS_SRC%" (
|
||||
echo ERROR: Standards snapshot not found at "%AGENTS_SRC%".
|
||||
@@ -56,30 +66,103 @@ if not exist "%AGENTS_ROOT%\index.md" (
|
||||
>> "%AGENTS_ROOT%\index.md" echo.
|
||||
>> "%AGENTS_ROOT%\index.md" echo 建议约定:
|
||||
>> "%AGENTS_ROOT%\index.md" echo.
|
||||
>> "%AGENTS_ROOT%\index.md" echo - `.agents/tsl/`:TSL 相关标准(由 `sync_standards.*` 同步)
|
||||
>> "%AGENTS_ROOT%\index.md" echo - `.agents/tsl/`:TSL 相关规则集(由 `sync_standards.*` 同步;适用于 `.tsl`/`.tsf`)
|
||||
>> "%AGENTS_ROOT%\index.md" echo - `.agents/cpp/`、`.agents/python/` 等:其他语言的规则集(按需增加)
|
||||
>> "%AGENTS_ROOT%\index.md" echo.
|
||||
>> "%AGENTS_ROOT%\index.md" echo 规则发生冲突时,建议以“更靠近代码的目录规则更具体”为准。
|
||||
>> "%AGENTS_ROOT%\index.md" echo.
|
||||
>> "%AGENTS_ROOT%\index.md" echo 入口建议从:
|
||||
>> "%AGENTS_ROOT%\index.md" echo.
|
||||
>> "%AGENTS_ROOT%\index.md" echo - `.agents/tsl/index.md`(TSL 规则集入口)
|
||||
>> "%AGENTS_ROOT%\index.md" echo - `docs/standards/tsl/docs/tsl/`(TSL 人类开发规范快照,推荐 subtree/vendoring 到该路径)
|
||||
echo Created .agents\index.md
|
||||
)
|
||||
|
||||
:SyncGitAttr
|
||||
if exist "%GITATTR_SRC%" (
|
||||
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.
|
||||
if /I "%SYNC_GITATTR_MODE%"=="skip" (
|
||||
echo Skip: .gitattributes sync ^(SYNC_GITATTR_MODE=skip^).
|
||||
goto AfterGitAttr
|
||||
)
|
||||
|
||||
if /I "%SYNC_GITATTR_MODE%"=="overwrite" (
|
||||
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
|
||||
)
|
||||
|
||||
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!
|
||||
)
|
||||
copy /y "%GITATTR_SRC%" "%GITATTR_DST%" >nul
|
||||
echo Synced .gitattributes from standards ^(overwrite^).
|
||||
goto AfterGitAttr
|
||||
)
|
||||
|
||||
if /I not "%SYNC_GITATTR_MODE%"=="block" (
|
||||
echo ERROR: invalid SYNC_GITATTR_MODE=%SYNC_GITATTR_MODE% ^(use block^|overwrite^|skip^)
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
rem block mode: maintain a managed block inside the destination file
|
||||
set "BEGIN=# BEGIN tsl-playbook .gitattributes"
|
||||
set "END=# END tsl-playbook .gitattributes"
|
||||
set "TMP_FILE=%TEMP%\\gitattributes.%RANDOM%.tmp"
|
||||
|
||||
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="
|
||||
)
|
||||
copy /y "%GITATTR_SRC%" "%GITATTR_DST%" >nul
|
||||
echo Synced .gitattributes from standards.
|
||||
|
||||
set "IN_BLOCK=0"
|
||||
set "DONE=0"
|
||||
|
||||
if not "%DST_IN%"=="" (
|
||||
> "!TMP_FILE!" (
|
||||
for /f "usebackq delims=" %%L in ("!DST_IN!") do (
|
||||
set "LINE=%%L"
|
||||
if "!LINE!"=="%BEGIN%" (
|
||||
if "!DONE!"=="0" (
|
||||
echo %BEGIN%
|
||||
type "%GITATTR_SRC%"
|
||||
echo %END%
|
||||
set "DONE=1"
|
||||
)
|
||||
set "IN_BLOCK=1"
|
||||
) else if "!LINE!"=="%END%" (
|
||||
set "IN_BLOCK=0"
|
||||
) else (
|
||||
if "!IN_BLOCK!"=="0" echo(!LINE!
|
||||
)
|
||||
)
|
||||
if "!DONE!"=="0" (
|
||||
echo.
|
||||
echo %BEGIN%
|
||||
type "%GITATTR_SRC%"
|
||||
echo %END%
|
||||
)
|
||||
)
|
||||
) else (
|
||||
> "!TMP_FILE!" (
|
||||
echo %BEGIN%
|
||||
type "%GITATTR_SRC%"
|
||||
echo %END%
|
||||
)
|
||||
)
|
||||
|
||||
copy /y "!TMP_FILE!" "%GITATTR_DST%" >nul
|
||||
del /q "!TMP_FILE!" >nul 2>nul
|
||||
echo Updated .gitattributes from standards ^(managed block^).
|
||||
)
|
||||
|
||||
:AfterGitAttr
|
||||
|
||||
+60
-15
@@ -1,6 +1,6 @@
|
||||
# Sync standards snapshot to project root.
|
||||
# - Copies <snapshot>/.agents -> <project-root>/.agents/tsl
|
||||
# - Copies <snapshot>/.gitattributes -> <project-root>/.gitattributes
|
||||
# - Updates <project-root>/.gitattributes (managed block by default)
|
||||
# Existing targets are backed up before overwrite.
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
@@ -48,35 +48,80 @@ Write-Host "Synced .agents/$AgentsNs from standards."
|
||||
|
||||
$AgentsIndex = Join-Path $AgentsRoot "index.md"
|
||||
if (-not (Test-Path $AgentsIndex)) {
|
||||
@"
|
||||
@'
|
||||
# .agents(多语言)
|
||||
|
||||
本目录用于存放仓库级/语言级的代理规则集。
|
||||
|
||||
建议约定:
|
||||
|
||||
- `.agents/tsl/`:TSL 相关标准(由 `sync_standards.*` 同步)
|
||||
- `.agents/tsl/`:TSL 相关规则集(由 `sync_standards.*` 同步;适用于 `.tsl`/`.tsf`)
|
||||
- `.agents/cpp/`、`.agents/python/` 等:其他语言的规则集(按需增加)
|
||||
|
||||
规则发生冲突时,建议以“更靠近代码的目录规则更具体”为准。
|
||||
"@ | Set-Content -Path $AgentsIndex -Encoding UTF8
|
||||
|
||||
入口建议从:
|
||||
|
||||
- `.agents/tsl/index.md`(TSL 规则集入口)
|
||||
- `docs/standards/tsl/docs/tsl/`(TSL 人类开发规范快照,推荐 subtree/vendoring 到该路径)
|
||||
'@ | Set-Content -Path $AgentsIndex -Encoding UTF8
|
||||
Write-Host "Created .agents/index.md"
|
||||
}
|
||||
|
||||
$GitAttrDst = Join-Path $Root ".gitattributes"
|
||||
if (Test-Path $GitAttrSrc) {
|
||||
if ($GitAttrSrc -ieq $GitAttrDst) {
|
||||
Write-Host "Skip: .gitattributes source equals destination."
|
||||
Write-Host "Done."
|
||||
exit 0
|
||||
$mode = $env:SYNC_GITATTR_MODE
|
||||
if (-not $mode) { $mode = "block" }
|
||||
switch ($mode.ToLowerInvariant()) {
|
||||
"skip" {
|
||||
Write-Host "Skip: .gitattributes sync (SYNC_GITATTR_MODE=skip)."
|
||||
break
|
||||
}
|
||||
"overwrite" {
|
||||
if ($GitAttrSrc -ieq $GitAttrDst) {
|
||||
Write-Host "Skip: .gitattributes source equals destination."
|
||||
break
|
||||
}
|
||||
if (Test-Path $GitAttrDst) {
|
||||
$bak = "$GitAttrDst.bak.$timestamp"
|
||||
Move-Item $GitAttrDst $bak
|
||||
Write-Host "Backed up existing .gitattributes -> $bak"
|
||||
}
|
||||
Copy-Item $GitAttrSrc $GitAttrDst -Force
|
||||
Write-Host "Synced .gitattributes from standards (overwrite)."
|
||||
break
|
||||
}
|
||||
"block" {
|
||||
$begin = "# BEGIN tsl-playbook .gitattributes"
|
||||
$end = "# END tsl-playbook .gitattributes"
|
||||
$src = Get-Content -Path $GitAttrSrc -Raw
|
||||
$block = $begin + "`r`n" + $src.TrimEnd() + "`r`n" + $end + "`r`n"
|
||||
|
||||
$dst = ""
|
||||
if (Test-Path $GitAttrDst) {
|
||||
$bak = "$GitAttrDst.bak.$timestamp"
|
||||
Move-Item $GitAttrDst $bak
|
||||
Write-Host "Backed up existing .gitattributes -> $bak"
|
||||
$dst = Get-Content -Path $bak -Raw
|
||||
}
|
||||
|
||||
$pattern = "(?ms)^" + [regex]::Escape($begin) + "\\R.*?^" + [regex]::Escape($end) + "\\R?"
|
||||
if ($dst -and ($dst -match $pattern)) {
|
||||
$new = [regex]::Replace($dst, $pattern, $block)
|
||||
} elseif ($dst) {
|
||||
$new = $dst.TrimEnd() + "`r`n`r`n" + $block
|
||||
} else {
|
||||
$new = $block
|
||||
}
|
||||
|
||||
$new | Set-Content -Path $GitAttrDst -Encoding UTF8
|
||||
Write-Host "Updated .gitattributes from standards (managed block)."
|
||||
break
|
||||
}
|
||||
default {
|
||||
throw "Invalid SYNC_GITATTR_MODE=$mode (use block|overwrite|skip)"
|
||||
}
|
||||
}
|
||||
if (Test-Path $GitAttrDst) {
|
||||
$bak = "$GitAttrDst.bak.$timestamp"
|
||||
Move-Item $GitAttrDst $bak
|
||||
Write-Host "Backed up existing .gitattributes -> $bak"
|
||||
}
|
||||
Copy-Item $GitAttrSrc $GitAttrDst -Force
|
||||
Write-Host "Synced .gitattributes from standards."
|
||||
}
|
||||
|
||||
Write-Host "Done."
|
||||
|
||||
+75
-12
@@ -3,7 +3,7 @@ set -eu
|
||||
|
||||
# Sync standards snapshot to project root.
|
||||
# - Copies <snapshot>/.agents -> <project-root>/.agents/tsl
|
||||
# - Copies <snapshot>/.gitattributes -> <project-root>/.gitattributes
|
||||
# - Updates <project-root>/.gitattributes (managed block by default)
|
||||
# Existing targets are backed up before overwrite.
|
||||
|
||||
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P)"
|
||||
@@ -56,10 +56,15 @@ if [ ! -f "$AGENTS_INDEX" ]; then
|
||||
|
||||
建议约定:
|
||||
|
||||
- `.agents/tsl/`:TSL 相关标准(由 `sync_standards.*` 同步)
|
||||
- `.agents/tsl/`:TSL 相关规则集(由 `sync_standards.*` 同步;适用于 `.tsl`/`.tsf`)
|
||||
- `.agents/cpp/`、`.agents/python/` 等:其他语言的规则集(按需增加)
|
||||
|
||||
规则发生冲突时,建议以“更靠近代码的目录规则更具体”为准。
|
||||
|
||||
入口建议从:
|
||||
|
||||
- `.agents/tsl/index.md`(TSL 规则集入口)
|
||||
- `docs/standards/tsl/docs/tsl/`(TSL 人类开发规范快照,推荐 subtree/vendoring 到该路径)
|
||||
EOF
|
||||
echo "Created .agents/index.md"
|
||||
fi
|
||||
@@ -68,16 +73,74 @@ echo "Synced agents ruleset to $AGENTS_DST."
|
||||
|
||||
GITATTR_DST="$ROOT/.gitattributes"
|
||||
if [ -f "$GITATTR_SRC" ]; then
|
||||
if [ "$(CDPATH= cd -- "$(dirname -- "$GITATTR_SRC")" && pwd -P)/$(basename -- "$GITATTR_SRC")" = "$GITATTR_DST" ]; then
|
||||
echo "Skip: .gitattributes source equals destination."
|
||||
else
|
||||
if [ -e "$GITATTR_DST" ]; then
|
||||
mv "$GITATTR_DST" "$ROOT/.gitattributes.bak.$timestamp"
|
||||
echo "Backed up existing .gitattributes -> .gitattributes.bak.$timestamp"
|
||||
fi
|
||||
cp "$GITATTR_SRC" "$GITATTR_DST"
|
||||
echo "Synced .gitattributes from standards."
|
||||
fi
|
||||
: "${SYNC_GITATTR_MODE:=block}"
|
||||
case "$SYNC_GITATTR_MODE" in
|
||||
skip)
|
||||
echo "Skip: .gitattributes sync (SYNC_GITATTR_MODE=skip)."
|
||||
;;
|
||||
overwrite)
|
||||
if [ "$(CDPATH= cd -- "$(dirname -- "$GITATTR_SRC")" && pwd -P)/$(basename -- "$GITATTR_SRC")" = "$GITATTR_DST" ]; then
|
||||
echo "Skip: .gitattributes source equals destination."
|
||||
else
|
||||
if [ -e "$GITATTR_DST" ]; then
|
||||
mv "$GITATTR_DST" "$ROOT/.gitattributes.bak.$timestamp"
|
||||
echo "Backed up existing .gitattributes -> .gitattributes.bak.$timestamp"
|
||||
fi
|
||||
cp "$GITATTR_SRC" "$GITATTR_DST"
|
||||
echo "Synced .gitattributes from standards (overwrite)."
|
||||
fi
|
||||
;;
|
||||
block)
|
||||
begin="# BEGIN tsl-playbook .gitattributes"
|
||||
end="# END tsl-playbook .gitattributes"
|
||||
|
||||
if [ -e "$GITATTR_DST" ]; then
|
||||
mv "$GITATTR_DST" "$ROOT/.gitattributes.bak.$timestamp"
|
||||
echo "Backed up existing .gitattributes -> .gitattributes.bak.$timestamp"
|
||||
fi
|
||||
|
||||
tmp="${GITATTR_DST}.tmp.${timestamp}"
|
||||
if [ -f "$ROOT/.gitattributes.bak.$timestamp" ]; then
|
||||
src_dst="$ROOT/.gitattributes.bak.$timestamp"
|
||||
else
|
||||
src_dst=""
|
||||
fi
|
||||
|
||||
if [ -n "$src_dst" ]; then
|
||||
awk -v begin="$begin" -v end="$end" -v src="$GITATTR_SRC" '
|
||||
function emit_src() {
|
||||
print begin
|
||||
while ((getline line < src) > 0) print line
|
||||
close(src)
|
||||
print end
|
||||
}
|
||||
BEGIN { in_block=0; done=0 }
|
||||
$0 == begin { in_block=1; if (!done) { emit_src(); done=1 } ; next }
|
||||
$0 == end { in_block=0; next }
|
||||
!in_block { print }
|
||||
END {
|
||||
if (!done) {
|
||||
if (NR > 0) print ""
|
||||
emit_src()
|
||||
}
|
||||
}
|
||||
' "$src_dst" >"$tmp"
|
||||
else
|
||||
{
|
||||
printf "%s\n" "$begin"
|
||||
cat "$GITATTR_SRC"
|
||||
printf "\n%s\n" "$end"
|
||||
} >"$tmp"
|
||||
fi
|
||||
|
||||
mv "$tmp" "$GITATTR_DST"
|
||||
echo "Updated .gitattributes from standards (managed block)."
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: invalid SYNC_GITATTR_MODE=$SYNC_GITATTR_MODE (use block|overwrite|skip)" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
echo "Done."
|
||||
|
||||
Reference in New Issue
Block a user