refactor: 公共面补 BakNRet 前缀,产品名大小写全仓统一

16 个没有前缀的公共函数补上 BakNRet(Write-Log → Write-BakNRetLog、Resolve-BackupEntry →
Resolve-BakNRetBackupEntry、Find-ChildDirectoryByName → Find-BakNRetChildDirectoryByName 等),
另外把全仓的 Baknret 统一成 BakNRet(47 个文件、940 处、65 个定义文件重命名)。

这不是审美问题:静态分析直接拓出一条实据 —— Write-Log 与本机某个已装模块导出的命令
**重名**(PSAvoidOverwritingBuiltInCmdlets),而重名的后果是导入两个模块时有一方的命令被
静默遮蔽。补前缀正是这条规则的解法,改名后它归零。

为什么敢做这个规模:PowerShell 的函数名解析大小写不敏感,所以 Baknret → BakNRet 在功能
上是零风险;真正要验证的是 16 个补前缀的调用点,而 276 个断言几乎覆盖了每个函数。另外
"名字与文件名一致"这条不变式有断言盯着(加载器点源的文件集合 vs 磁盘)。

踩到并记下的坑:Windows 文件系统大小写不敏感,所以**只改大小写**的重命名会被 Move-Item
当成同一个文件而静默跳过 —— 同一批里同时改了名字的那 16 个文件却成功了,于是"看起来能跑"。
最后用"先移到临时名、再移到目标名"的两步走解决,判断与替换全部改用显式大小写敏感的形式
(-creplace / -cmatch)。

顺带把名录指纹缓存从 MD5 换成 SHA256(PSAvoidUsingBrokenHashAlgorithms):它只是缓存键,
没有兼容负担。

验收:test.ps1 9/9 全绿(7 与 5.1)、100 个文件两版解析零错、276 个断言全过、
构建工具仍能合回单文件(3300 行)。
This commit is contained in:
Shuery committed 2026-09-27 09:56:36 +08:00
1 parent 187d2759fd
commit 42f02d0eca
84 files changed
+1043 -1043

No files matched your search

+10 -10
View File
@@ -167,7 +167,7 @@ $manifestPath = Join-Path $backupDir 'manifest.json'
Test-Case 'manifest 记录了条目、动作、校验结果、roots 与 layouts' {
Assert-FileExists $manifestPath
$manifest = Read-BaknretManifest -Path $manifestPath
$manifest = Read-BakNRetManifest -Path $manifestPath
Assert-Equal 1 $manifest.items.Count
$record = $manifest.items[$archives[0].BaseName]
@@ -251,7 +251,7 @@ $cleanExitCode = $LASTEXITCODE
$cleanArchive = Get-ChildItem -LiteralPath $lockBackupDir -File -Filter *.7z | Select-Object -First 1
$cleanSize = $cleanArchive.Length
$lockManifestPath = Join-Path $lockBackupDir 'manifest.json'
$cleanRecord = (Read-BaknretManifest -Path $lockManifestPath).items[$cleanArchive.BaseName]
$cleanRecord = (Read-BakNRetManifest -Path $lockManifestPath).items[$cleanArchive.BaseName]
Test-Case '干净归档:退出码 0,manifest 记 warnings=false' {
Assert-Equal 0 $cleanExitCode
@@ -269,7 +269,7 @@ try {
& $backupScript -BackupListPath $lockList -BackupDir $lockBackupDir -ConfigPath $cfg2 -Force -QuietTool
$warnExitCode = $LASTEXITCODE
$afterArchive = Get-ChildItem -LiteralPath $lockBackupDir -File -Filter *.7z | Select-Object -First 1
$afterRecord = (Read-BaknretManifest -Path $lockManifestPath).items[$afterArchive.BaseName]
$afterRecord = (Read-BakNRetManifest -Path $lockManifestPath).items[$afterArchive.BaseName]
Test-Case '有警告时拒绝覆盖完整归档:退出码 1,旧归档原样保留' {
Assert-Equal 1 $warnExitCode
@@ -282,7 +282,7 @@ try {
# 明确接受之后才允许覆盖
& $backupScript -BackupListPath $lockList -BackupDir $lockBackupDir -ConfigPath $cfg2 -Force -QuietTool -AcceptWarnings
$acceptExitCode = $LASTEXITCODE
$acceptedRecord = (Read-BaknretManifest -Path $lockManifestPath).items[$afterArchive.BaseName]
$acceptedRecord = (Read-BakNRetManifest -Path $lockManifestPath).items[$afterArchive.BaseName]
Test-Case '-AcceptWarnings 允许覆盖,并在 manifest 记 warnings=true' {
Assert-Equal 0 $acceptExitCode
@@ -357,7 +357,7 @@ Test-Case '名录条目:一个软件一个归档,归档名 = 软件名;独
}
Test-Case 'manifest.roots 列出各归档项的顶层名,layouts 标出 dir / file' {
$record = (Read-BaknretManifest -Path (Join-Path $catBackupDir 'manifest.json')).items['my-app']
$record = (Read-BakNRetManifest -Path (Join-Path $catBackupDir 'manifest.json')).items['my-app']
Assert-True ($null -ne $record)
$roots = @($record.roots | Sort-Object)
Assert-Equal 3 $roots.Count
@@ -438,7 +438,7 @@ Test-Case '@pathname 覆盖:用名录里的真实路径跑命名算法(独
[System.IO.File]::WriteAllText($pathList, "my-app @pathname :+ Modules:$settingsFile`n", [System.Text.UTF8Encoding]::new($true))
# settings.json 刚才被删了,重建一份,让 Include 的宿主机路径存在
Set-Content -LiteralPath $settingsFile -Value '{"slot":"file"}' -Encoding UTF8
$expectedBase = Get-BackupBaseName -RawPath $dirA
$expectedBase = Get-BakNRetBackupBaseName -RawPath $dirA
& $backupScript -BackupListPath $pathList -BackupDir $pathNameDir -ConfigPath $catConfig -Force -QuietTool
Assert-Equal 0 $LASTEXITCODE
Assert-FileExists (Join-Path $pathNameDir ($expectedBase + '.7z'))
@@ -578,7 +578,7 @@ if ($sevenZip) {
[System.IO.File]::WriteAllText($legacyList, "legacy-file`n", [System.Text.UTF8Encoding]::new($true))
New-E2EConfig -Path $legacyConfig -LogDir $legacyLogDir -SoftwareCatalog $legacyCatalog
$legacyManifest = Read-BaknretManifest -Path (Join-Path $legacyBackupDir 'manifest.json')
$legacyManifest = Read-BakNRetManifest -Path (Join-Path $legacyBackupDir 'manifest.json')
$legacyManifest.items['legacy-file'] = [ordered]@{
baseName = 'legacy-file'
source = 'legacy-file'
@@ -586,7 +586,7 @@ $legacyManifest.items['legacy-file'] = [ordered]@{
action = 'backed-up'
encrypted = $false
}
Write-BaknretManifest -Path (Join-Path $legacyBackupDir 'manifest.json') -Manifest $legacyManifest | Out-Null
Write-BakNRetManifest -Path (Join-Path $legacyBackupDir 'manifest.json') -Manifest $legacyManifest | Out-Null
# 让"恢复确实做了事"可验证:把活文件改成别的内容,恢复后应回到归档里的内容
Set-Content -LiteralPath $legacyLive -Value '{"version":"changed-after-backup"}' -Encoding UTF8
@@ -646,7 +646,7 @@ Test-Case '字面路径不受名录影响,仍走路径命名' {
[System.IO.File]::WriteAllText($literalList, "$dirA2`n", [System.Text.UTF8Encoding]::new($true))
& $backupScript -BackupListPath $literalList -BackupDir $literalDir -ConfigPath $catConfig -Force -QuietTool
Assert-Equal 0 $LASTEXITCODE
Assert-FileExists (Join-Path $literalDir ((Get-BackupBaseName -RawPath $dirA2) + '.7z'))
Assert-FileExists (Join-Path $literalDir ((Get-BakNRetBackupBaseName -RawPath $dirA2) + '.7z'))
}
$missingList = Join-Path $WorkRoot 'missing.txt'
@@ -656,7 +656,7 @@ $missingExitCode = $LASTEXITCODE
Test-Case '源路径不存在被记为 missing-source,退出码仍为 0(跳过不算失败)' {
Assert-Equal 0 $missingExitCode
$after = Read-BaknretManifest -Path $manifestPath
$after = Read-BakNRetManifest -Path $manifestPath
$record = $after.items['definitely-not-here-12345_from_Z_']
Assert-True ($null -ne $record) 'manifest 里应有该条目的记录'
Assert-Equal 'missing-source' $record.action