Files
BakNRet/tools/Install-TestDependencies.ps1
T
Shuery e114cae8c8 P0-P3 全量重构:退出码 / 解析修复、manifest 与 7z t 校验、干跑、排除规则、日志、测试与计划任务
P0 正确性
- 退出码:改用 .NET Process 直接启动、让子进程继承控制台,不再用 Start-Process -PassThru
  (在 7.7.0-preview.4 上 ExitCode 恒为 $null,会把成功的压缩判成失败);
  7z / RAR / tar 三条解压分支统一走同一个取退出码的封装。
- BackupList 解析:先按第一个 :: 切段再处理引号(整行被一对引号包住的写法不再把排除表
  吞进路径);排除表同时接受 , 与 ;(旧实现只认 ;,导致排除从未生效);支持 :- / :+ / @flag。
- 补回 .ssh 与孤儿归档:.ssh 进清单;孤儿归档在备份端也做审计并点名;
  带 -Only / -Skip 时不再把未选中的归档误报成孤儿。
- Resolve-BackupEntry 里 $rootName 在赋值前被引用(会读到外层作用域残留值),已提前赋值。

P1 归档可靠性
- 每个条目写进 manifest.json:源、归档、时间、退出码、校验结果、失败原因,
  并区分 warnings(在位归档)与 attemptWarnings(本次尝试)。
- 归档后做 7z t 内容校验,先写 .tmp、校验通过再原子替换(File.Move overwrite)。
- manifest.roots 记录归档内**真实**的顶层条目名(原先记的是软件名,Edge 实际是 "User Data")。

P2 可用性
- Restore 支持 -WhatIf / -DryRun / -VerifyOnly / -Only / -Skip;
  这三种"只看不写"的模式一个字节都不写(原先会写回 manifest.json)。
- Edge 等高缓存条目加排除规则并实测:1781 MB / 27961 项 -> 72 MB / 2294 项;
  书签、密码、Cookies、偏好、历史、IndexedDB、Local Storage 全部保留。
  普通模式是相对归档根目录锚定的,嵌套的那些(如 OneAuth\WebView2 里的 Crashpad)
  改用 ! 组件形式才会命中。
- 日志落盘 logs/<backup|restore>-<时间戳>.log;退出码按失败数返回。
- tools/Register-BackupTask.ps1 注册每日计划任务;tools/Rename-Archives.ps1 迁移旧归档名。
- root= 标记此前静默失效,现在明确告警(该功能尚未实现)。

P3 测试与验证
- tests/BakNRet.Tests.ps1:Pester 5 套件 62 项(含用子进程跑 Backup.ps1 / Restore.ps1
  的端到端与针对上述缺陷的回归)。
- tests/Run-Pester.ps1 + tools/Install-TestDependencies.ps1:把 Pester 装到仓库内 .tools/,
  不动机器上的全局模块(系统自带的 3.4.0 缺 Should -Be)。
- tests/Restore-Drill.ps1:真实归档恢复演练,明确区分"源在备份后变过"与"归档/解压有问题"。
- tests/Run-Tests.ps1(49 项,零依赖)与 tests/Run-E2E.ps1(23 项)继续可用;三套共 134 项全通过。

真实机器验证
- 生产归档 22/22 通过 7z t;-VerifyOnly 不再改动 manifest.json(SHA256 前后一致)。
- 真实恢复演练 12/12 通过,27,670 个文件与活源逐字节一致。
- 修复了生产 scoop-persist.7z:原先只有 90 字节(空归档)而源有 1.3 GB,
  重打包后 233 MB,恢复演练 26981/26981 全部一致。
2026-09-21 23:02:47 +08:00

72 lines
2.4 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<#
.SYNOPSIS
把测试用的 Pester 5 装进仓库内的 .tools\modules(不动机器上的全局模块)。
.DESCRIPTION
tests\BakNRet.Tests.ps1 需要 Pester 5.0+。本机常见的坑是:
* Windows 自带的是 Pester 3.4.0,没有 `Should -Be`,套件会语法错误;
* 直接 Install-Module 会把 5.x 装到全局,可能影响机器上别的、按 3.x 语法写的脚本。
所以这里用 Save-Module 把指定版本下载到仓库内的 .tools\modules,
tests\Run-Pester.ps1 会自动把该目录加进 PSModulePath。
.tools\ 已进 .gitignore,不会污染版本库。
.EXAMPLE
pwsh -File .\tools\Install-TestDependencies.ps1
.EXAMPLE
pwsh -File .\tools\Install-TestDependencies.ps1 -PesterVersion 5.9.1 -Force
#>
[CmdletBinding()]
param(
[version]$PesterVersion = [version]'5.9.1',
[switch]$Force
)
$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'
$projectRoot = Split-Path -Parent $PSScriptRoot
$target = Join-Path $projectRoot '.tools\modules'
$installed = Join-Path $target ("Pester\{0}" -f $PesterVersion)
Write-Host ''
Write-Host ("目标目录 : {0}" -f $target)
Write-Host ("Pester : {0}" -f $PesterVersion)
Write-Host ''
if ((Test-Path -LiteralPath $installed) -and -not $Force) {
Write-Host "已经装好了,无需重复下载(要重装加 -Force)。" -ForegroundColor Green
exit 0
}
if ($Force -and (Test-Path -LiteralPath (Join-Path $target 'Pester'))) {
Remove-Item -LiteralPath (Join-Path $target 'Pester') -Recurse -Force
}
New-Item -ItemType Directory -Path $target -Force | Out-Null
if (-not (Get-Command Save-Module -ErrorAction SilentlyContinue)) {
Write-Error '当前环境没有 Save-Module(需要 PowerShellGet 2.x)。请改用:Install-Module Pester -Scope CurrentUser -MinimumVersion 5.0.0'
exit 1
}
try {
Save-Module -Name Pester -RequiredVersion $PesterVersion -Path $target -Force -ErrorAction Stop
} catch {
Write-Error "下载失败(多半是访问不到 PSGallery):$_"
exit 1
}
$module = Get-Module -ListAvailable Pester | Where-Object { [version]$_.Version -eq $PesterVersion }
if (-not $module) {
Write-Error "下载结束但找不到 Pester $PesterVersion,请检查 $target。"
exit 1
}
Write-Host ("已安装:Pester {0} -> {1}" -f $module.Version, $module.ModuleBase) -ForegroundColor Green
Write-Host '现在可以跑:.\tests\Run-Pester.ps1' -ForegroundColor Cyan
Write-Host ''
exit 0