feat(tui): 校验后原子保存 + 时间戳备份(第一轮第五块·地基)
三个配置编辑器共用的这块地基(ADR-0013)。顺序是刻意的:① 先校验(调用方给的 -Validate 回调);② **只有校验通过才备份与写盘** —— 校验没过还留下备份会让人以为"动过了";③ 原子替换走 Write-BaknretAtomicText。返回结果对象而不是抛异常:TUI 要把错误显示出来让人继续改,而不是把界面炸掉("TUI 异常不改退出码"这条同样适用)。 给 Write-BaknretAtomicText 加了一个可选 -Encoding(不传时沿用原行为,现有调用点不受影响)。原因:它原先固定用日志编码(无 BOM),而三个配置文件都是带 BOM 的 —— 丢掉 BOM 会让 5.1 把整个文件按 GBK 读,中文全成乱码。这类"编码悄悄变了"的错不会报错,只会让文件在某一个 PowerShell 版本上读出来是乱码。 判据(断言 10 条):校验不过时不写盘、不产生备份、错误原文能带回去;校验通过后新内容落盘、备份里是**原文**、且写回**保留 UTF-8 BOM**(逐字节验 EF BB BF)。 验收:test.ps1 9/9 全绿(5.1 与 7);真实清单只读冒烟 4/4。
This commit is contained in:
1 parent
54972ab341
commit
59ec5a21d4
5 files changed
+91
-2
No files matched your search
@@ -1597,6 +1597,33 @@ Test-Case '清单行表与单行替换:只动那一行,注释与其它行逐
|
||||
Assert-True $threw '行号越界必须抛错'
|
||||
}
|
||||
|
||||
Test-Case '保存配置:校验不过什么都不动,过了才备份 + 原子替换,且保留 BOM' {
|
||||
$dir = Join-Path $env:TEMP ("bnr-save-" + [guid]::NewGuid().ToString('N').Substring(0, 8))
|
||||
New-Item -ItemType Directory -Path $dir -Force | Out-Null
|
||||
$file = Join-Path $dir 'BackupList.txt'
|
||||
$utf8Bom = New-Object System.Text.UTF8Encoding($true)
|
||||
[System.IO.File]::WriteAllText($file, "Edge`n", $utf8Bom)
|
||||
try {
|
||||
# 1) 校验不过:文件不动、也不产生备份(留备份会让人以为"动过了")
|
||||
$bad = Save-BakNRetConfigFile -Path $file -Text "坏行`n" -Validate { param($t) @('第 1 行有问题') } -BackupDirectory (Join-Path $dir 'bak')
|
||||
Assert-Equal $false $bad.Saved '校验不过不能保存'
|
||||
Assert-True ($bad.Error -like '*第 1 行有问题*') '错误原文要带回来(TUI 要显示它)'
|
||||
Assert-Equal "Edge`n" ([System.IO.File]::ReadAllText($file)) '文件内容不动'
|
||||
Assert-True (-not (Test-Path (Join-Path $dir 'bak'))) '校验不过不该产生备份'
|
||||
|
||||
# 2) 校验通过:写进去 + 备份里是原文 + 保留 BOM
|
||||
$ok = Save-BakNRetConfigFile -Path $file -Text "+WindowsTerminal`n" -Validate { param($t) @() } -BackupDirectory (Join-Path $dir 'bak')
|
||||
Assert-Equal $true $ok.Saved '校验通过应当保存'
|
||||
Assert-Equal "+WindowsTerminal`n" ([System.IO.File]::ReadAllText($file)) '新内容写进去了'
|
||||
Assert-True (Test-Path $ok.BackupPath) '应当产生时间戳备份'
|
||||
Assert-Equal "Edge`n" ([System.IO.File]::ReadAllText($ok.BackupPath)) '备份里是原文'
|
||||
$bytes = [System.IO.File]::ReadAllBytes($file)
|
||||
Assert-True ($bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) '写回必须保留 UTF-8 BOM'
|
||||
} finally {
|
||||
Remove-Item -LiteralPath $dir -Recurse -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
Remove-Item -LiteralPath $sandbox -Recurse -Force -ErrorAction SilentlyContinue
|
||||
Remove-Item -LiteralPath $itemSandbox -Recurse -Force -ErrorAction SilentlyContinue
|
||||
|
||||
Reference in new issue
Block a user