refactor: manifest 的写入收进模块函数,依赖写在签名上
Save-ItemRecord 原先直接用脚本级的 $manifest —— "这个函数会改全局账本"这条事实只存在于读代码的人的注意力里。搬进模块后 Manifest 是必填参数,13 个调用点每一个都能看出自己在动账本。 关键判断:**不需要接返回值**。$Manifest.items 是哈希表,传参是引用语义,函数里的写入直接落在调用方那份 manifest 上,所以调用点的形状只是"多了一个 -Manifest $manifest",行为一字不改。这是"有状态依赖该做成什么"的答案里最省的一种:显式参数 + 引用语义。 两条刻意保留、容易被改错的语义也写进了注释并原样搬过来:warnings 与 security 描述的是"当前在位的归档"而不是"这次尝试",只有真的换掉归档才更新 —— 否则"因不完整而保留旧归档"之后,下一次就失去保护了。 搬的过程里把 $Record.finishedAt 那行写坏了(外层双引号把 $Record 提前插值成空,文件里变成 ".finishedAt = ...")。**注意这是上一轮刚记下的同一个坑**:往文件里写 PowerShell 代码时外层一律用单引号。这次是"绿了才提交"把它拦在提交之外 —— 流程修正当场生效。 验收:test.ps1 9/9 全绿(7 与 5.1)、真实清单只读冒烟 4/4。Backup.ps1 从 889 行降到 846 行。
This commit is contained in:
1 parent
319ec1da78
commit
c4452a749c
4 files changed
+76
-56
No files matched your search
+13
-56
@@ -183,49 +183,6 @@ if ($freeSpaceGB -ge 0) {
|
||||
|
||||
|
||||
|
||||
function Save-ItemRecord {
|
||||
param($Record, [string]$Action, [string]$Reason, [bool]$ArchiveWarnings = $false)
|
||||
|
||||
$previous = $null
|
||||
if ($manifest.items.Contains($Record.baseName)) { $previous = $manifest.items[$Record.baseName] }
|
||||
|
||||
$Record.action = $Action
|
||||
$Record.reason = $Reason
|
||||
$Record.finishedAt = (Get-Date).ToString('o')
|
||||
|
||||
# warnings 描述的是"当前在位的归档",不是"这次尝试"。
|
||||
# 只有真正换掉了归档才更新它;否则沿用上一条记录,
|
||||
# 否则"因为不完整而保留旧归档"之后,下一次就失去保护了。
|
||||
if ($Action -eq 'backed-up') {
|
||||
$Record.warnings = $ArchiveWarnings
|
||||
}
|
||||
elseif ($previous -and ($previous.PSObject.Properties.Name -contains 'warnings')) {
|
||||
$Record.warnings = [bool]$previous.warnings
|
||||
}
|
||||
|
||||
# security 描述的是"当前在位的归档"的旁挂文件,和 warnings 同理:
|
||||
# 只有真的换了归档才更新它,否则跳过的那次会把已有记录清成 $null。
|
||||
if ($Action -ne 'backed-up' -and $previous -and ($previous.PSObject.Properties.Name -contains 'security')) {
|
||||
$Record.security = $previous.security
|
||||
}
|
||||
|
||||
if ($previous) {
|
||||
if ($previous.PSObject.Properties.Name -contains 'lastSuccessAt') { $Record.lastSuccessAt = $previous.lastSuccessAt }
|
||||
if ($previous.PSObject.Properties.Name -contains 'successCount') { $Record.successCount = [int]$previous.successCount }
|
||||
if ($previous.PSObject.Properties.Name -contains 'failCount') { $Record.failCount = [int]$previous.failCount }
|
||||
}
|
||||
|
||||
if ($Action -eq 'backed-up') {
|
||||
$Record.lastSuccessAt = $Record.finishedAt
|
||||
$Record.successCount = [int]$Record.successCount + 1
|
||||
}
|
||||
elseif ($Action -eq 'failed') {
|
||||
$Record.failCount = [int]$Record.failCount + 1
|
||||
}
|
||||
|
||||
$manifest.items[$Record.baseName] = $Record
|
||||
return $Record
|
||||
}
|
||||
|
||||
# 压缩 + 校验 + 原子替换;返回 @{ Ok; ExitCode; Warnings; Reason }
|
||||
#
|
||||
@@ -493,7 +450,7 @@ foreach ($line in $lines) {
|
||||
|
||||
if (-not $resolved.BaseName) {
|
||||
$record = New-BakNRetItemRecord -BaseName ('raw:' + $displayPath) -Source $displayPath -ResolvedSource $displayPath -Phase 'parse'
|
||||
Save-ItemRecord -Record $record -Action 'failed' -Reason '无法生成归档名' | Out-Null
|
||||
Save-BakNRetItemRecord -Manifest $manifest -Record $record -Action 'failed' -Reason '无法生成归档名' | Out-Null
|
||||
$failed++; $failures += $displayPath
|
||||
continue
|
||||
}
|
||||
@@ -513,7 +470,7 @@ foreach ($line in $lines) {
|
||||
$reason = "归档名 '$baseName' 与清单中的 '$($seenBaseNames[$baseName])' 重复(由 '$displayPath' 生成),两者会互相覆盖"
|
||||
Write-BakNRetLog "失败: $displayPath,$reason" -Level ERROR
|
||||
$record = New-BakNRetItemRecord -BaseName $baseName -Source $displayPath -ResolvedSource $sourcePath -Phase 'backup'
|
||||
Save-ItemRecord -Record $record -Action 'failed' -Reason $reason | Out-Null
|
||||
Save-BakNRetItemRecord -Manifest $manifest -Record $record -Action 'failed' -Reason $reason | Out-Null
|
||||
$failed++; $failures += $displayPath
|
||||
continue
|
||||
}
|
||||
@@ -537,7 +494,7 @@ foreach ($line in $lines) {
|
||||
# 归档内路径冲突:明确失败,绝不把两块内容静默搅进同一棵树
|
||||
if ($resolved.Blocking) {
|
||||
Write-BakNRetLog "失败: $displayPath,$($resolved.Blocking)" -Level ERROR
|
||||
Save-ItemRecord -Record $record -Action 'failed' -Reason $resolved.Blocking | Out-Null
|
||||
Save-BakNRetItemRecord -Manifest $manifest -Record $record -Action 'failed' -Reason $resolved.Blocking | Out-Null
|
||||
$failed++; $failures += $displayPath
|
||||
continue
|
||||
}
|
||||
@@ -561,7 +518,7 @@ foreach ($line in $lines) {
|
||||
if ($resolved.Items.Count -eq 0) {
|
||||
$reason = if ($resolved.Error) { $resolved.Error } else { '解析不出任何源路径' }
|
||||
Write-BakNRetLog "跳过: $displayPath,$reason" -Level WARN
|
||||
Save-ItemRecord -Record $record -Action 'missing-source' -Reason $reason | Out-Null
|
||||
Save-BakNRetItemRecord -Manifest $manifest -Record $record -Action 'missing-source' -Reason $reason | Out-Null
|
||||
$skipped++
|
||||
continue
|
||||
}
|
||||
@@ -573,7 +530,7 @@ foreach ($line in $lines) {
|
||||
if ($missingItems.Count -ge $resolved.Items.Count) {
|
||||
$missingText = @($missingItems | ForEach-Object { $_.RealPath }) -join ';'
|
||||
Write-BakNRetLog "跳过: $displayPath,源路径不存在" -Level WARN
|
||||
Save-ItemRecord -Record $record -Action 'missing-source' -Reason ('源路径不存在:' + $missingText) | Out-Null
|
||||
Save-BakNRetItemRecord -Manifest $manifest -Record $record -Action 'missing-source' -Reason ('源路径不存在:' + $missingText) | Out-Null
|
||||
$skipped++
|
||||
continue
|
||||
}
|
||||
@@ -602,7 +559,7 @@ foreach ($line in $lines) {
|
||||
$primarySource = $liveItems[0].RealPath
|
||||
if ([string]::IsNullOrWhiteSpace($primarySource)) {
|
||||
Write-BakNRetLog "跳过: $displayPath,无法确定主源路径" -Level WARN
|
||||
Save-ItemRecord -Record $record -Action 'invalid-path' -Reason '归档项没有可用路径' | Out-Null
|
||||
Save-BakNRetItemRecord -Manifest $manifest -Record $record -Action 'invalid-path' -Reason '归档项没有可用路径' | Out-Null
|
||||
$skipped++
|
||||
continue
|
||||
}
|
||||
@@ -636,7 +593,7 @@ foreach ($line in $lines) {
|
||||
if (-not $Force -and $archiveItem -and $sourceLatest -and $sourceLatest -le $archiveItem.LastWriteTime) {
|
||||
Write-BakNRetLog "跳过: $displayPath,源目录未更新" -Level INFO
|
||||
$record.archiveBytes = $archiveItem.Length
|
||||
Save-ItemRecord -Record $record -Action 'skip-unchanged' -Reason ('源最新修改时间 {0} 不晚于归档时间 {1}' -f $sourceLatest, $archiveItem.LastWriteTime) | Out-Null
|
||||
Save-BakNRetItemRecord -Manifest $manifest -Record $record -Action 'skip-unchanged' -Reason ('源最新修改时间 {0} 不晚于归档时间 {1}' -f $sourceLatest, $archiveItem.LastWriteTime) | Out-Null
|
||||
$skipped++
|
||||
continue
|
||||
}
|
||||
@@ -651,7 +608,7 @@ foreach ($line in $lines) {
|
||||
if ($freeSpaceGB -ge 0 -and $estimatedGB -gt 0 -and $freeSpaceGB -lt $estimatedGB) {
|
||||
$reason = ('剩余空间 {0} GB 不足以写入预估 {1} GB 的新归档' -f $freeSpaceGB, [math]::Round($estimatedGB, 2))
|
||||
Write-BakNRetLog "失败: $displayPath,$reason" -Level ERROR
|
||||
Save-ItemRecord -Record $record -Action 'failed' -Reason $reason | Out-Null
|
||||
Save-BakNRetItemRecord -Manifest $manifest -Record $record -Action 'failed' -Reason $reason | Out-Null
|
||||
$failed++; $failures += $displayPath
|
||||
continue
|
||||
}
|
||||
@@ -659,7 +616,7 @@ foreach ($line in $lines) {
|
||||
if ($DryRun) {
|
||||
Write-BakNRetLog ("[试运行] 将打包 {0} -> {1}" -f $sourcePath, $finalPath) -Level INFO
|
||||
$record.reason = '试运行,未执行压缩'
|
||||
Save-ItemRecord -Record $record -Action 'planned' -Reason '试运行,未执行压缩' | Out-Null
|
||||
Save-BakNRetItemRecord -Manifest $manifest -Record $record -Action 'planned' -Reason '试运行,未执行压缩' | Out-Null
|
||||
$planned++
|
||||
continue
|
||||
}
|
||||
@@ -693,7 +650,7 @@ foreach ($line in $lines) {
|
||||
|
||||
if ($excludeError) {
|
||||
Write-BakNRetLog "失败: $displayPath,$excludeError" -Level ERROR
|
||||
Save-ItemRecord -Record $record -Action 'failed' -Reason $excludeError | Out-Null
|
||||
Save-BakNRetItemRecord -Manifest $manifest -Record $record -Action 'failed' -Reason $excludeError | Out-Null
|
||||
$failed++; $failures += $displayPath
|
||||
continue
|
||||
}
|
||||
@@ -731,7 +688,7 @@ foreach ($line in $lines) {
|
||||
|
||||
if (-not $result.Ok) {
|
||||
Write-BakNRetLog "备份失败: $displayPath,$($result.Reason)" -Level ERROR
|
||||
Save-ItemRecord -Record $record -Action 'failed' -Reason $result.Reason | Out-Null
|
||||
Save-BakNRetItemRecord -Manifest $manifest -Record $record -Action 'failed' -Reason $result.Reason | Out-Null
|
||||
$failed++; $failures += $displayPath
|
||||
continue
|
||||
}
|
||||
@@ -793,7 +750,7 @@ foreach ($line in $lines) {
|
||||
|
||||
if ($securityFatal) {
|
||||
Write-BakNRetLog "失败: $displayPath,归档已替换,但安全描述符没能存下来(Security.FailOnError = \$true)" -Level ERROR
|
||||
Save-ItemRecord -Record $record -Action 'failed' -Reason '归档已替换,但安全描述符没能存下来' | Out-Null
|
||||
Save-BakNRetItemRecord -Manifest $manifest -Record $record -Action 'failed' -Reason '归档已替换,但安全描述符没能存下来' | Out-Null
|
||||
$failed++; $failures += $displayPath
|
||||
continue
|
||||
}
|
||||
@@ -813,7 +770,7 @@ foreach ($line in $lines) {
|
||||
Write-BakNRetLog "已留存快照: $target" -Level INFO
|
||||
}
|
||||
|
||||
Save-ItemRecord -Record $record -Action 'backed-up' -Reason $null -ArchiveWarnings $result.Warnings | Out-Null
|
||||
Save-BakNRetItemRecord -Manifest $manifest -Record $record -Action 'backed-up' -Reason $null -ArchiveWarnings $result.Warnings | Out-Null
|
||||
$processed++
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user