fix: 让 5.1 真正可用(显式编码 + 原生 stderr 处理 + .psd1 夹具带 BOM)
上一提交让 5.1 能解析源码,但 Unit 与 Smoke 在 5.1 上仍然是红的。根因是三类彼此 无关的 5.1/7 行为差,全部实测确认: 1) 不写 -Encoding 时,5.1 的 Get-Content / Set-Content 默认是 ANSI,7 是 UTF-8。 症状是 UTF-8 字节被按 GBK 解出「璇存槑」这类乱码。62 处补上显式 -Encoding UTF8。 用 AST 而不是正则定位,避免把注释里的散文也改掉。 2) .psd1 夹具用无 BOM 写,而引擎的 .psd1 读取器(Import-PowerShellDataFile)只能靠 BOM 判断编码、没有参数可传,于是 5.1 按 ANSI 解。40 处夹具改为带 BOM 写 —— 这正是 .editorconfig 里 [*.psd1] charset = utf-8-bom 本来就要求的,是夹具违反了自己的约定。 .cmd 批次文件刻意保持无 BOM:cmd.exe 会被 BOM 弄坏。 3) 5.1 在 $ErrorActionPreference = Stop 下会把原生命令写到 stderr 的内容升级成终止性 NativeCommandError,7 改了这条。takeown/icacls 的 ACL 复位调用、以及 test.ps1 自己 调子进程的地方,都需要在 Continue 下跑。 验收:test.ps1 9/9 全绿(Encode + Parse + Unit + Smoke + E2E,在 7 与 5.1 上各跑一遍)。 已知未处理(留待后续提交):tools/lab/** 里还有若干「原生命令 + 2>&1 + Stop」的同类 写法(takeown / icacls / scoop / code / Get-WimInfo)。它们要 Hyper-V 实验机才跑得到, 不在验收门槛内。
This commit is contained in:
1 parent
2d26f78d15
commit
e10503be76
13 files changed
+122
-104
No files matched your search
+2
-2
@@ -134,7 +134,7 @@ if (-not (Test-Path -LiteralPath $BackupListPath)) {
|
|||||||
"# 示例: Edge`n" +
|
"# 示例: Edge`n" +
|
||||||
"# %UserProfile%\.ssh :encrypt`n" +
|
"# %UserProfile%\.ssh :encrypt`n" +
|
||||||
"# 完整语法见 README 与 BackupList.txt 自身的注释。`n"
|
"# 完整语法见 README 与 BackupList.txt 自身的注释。`n"
|
||||||
[System.IO.File]::WriteAllText($BackupListPath, $template, [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($BackupListPath, $template, [System.Text.UTF8Encoding]::new($true))
|
||||||
Write-Log '模板 BackupList.txt 已创建,请编辑后重试。' -Level INFO
|
Write-Log '模板 BackupList.txt 已创建,请编辑后重试。' -Level INFO
|
||||||
Stop-BaknretLog
|
Stop-BaknretLog
|
||||||
exit 0
|
exit 0
|
||||||
@@ -162,7 +162,7 @@ $encryptAll = [bool]$script:Config.Encryption.Enabled
|
|||||||
$showToolOutput = (-not $QuietTool) -and ($script:Config.ToolOutput -ne 'quiet')
|
$showToolOutput = (-not $QuietTool) -and ($script:Config.ToolOutput -ne 'quiet')
|
||||||
$toolQuietArgument = if ($showToolOutput) { @() } else { @('-bso0', '-bsp0') }
|
$toolQuietArgument = if ($showToolOutput) { @() } else { @('-bso0', '-bsp0') }
|
||||||
|
|
||||||
$lines = Get-Content -LiteralPath $BackupListPath
|
$lines = Get-Content -Encoding UTF8 -LiteralPath $BackupListPath
|
||||||
$seenBaseNames = @{}
|
$seenBaseNames = @{}
|
||||||
$processed = 0; $skipped = 0; $failed = 0; $planned = 0
|
$processed = 0; $skipped = 0; $failed = 0; $planned = 0
|
||||||
$securityErrorCount = 0 # 有条目"安全描述符里有读不到的对象"
|
$securityErrorCount = 0 # 有条目"安全描述符里有读不到的对象"
|
||||||
|
|||||||
+2
-2
@@ -484,7 +484,7 @@ if (-not (Test-Path -LiteralPath $BackupListPath)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$content = "# BackupList.txt(自动生成,排除规则需要手工补回)`n" + (($paths -join [Environment]::NewLine) + [Environment]::NewLine)
|
$content = "# BackupList.txt(自动生成,排除规则需要手工补回)`n" + (($paths -join [Environment]::NewLine) + [Environment]::NewLine)
|
||||||
[System.IO.File]::WriteAllText($BackupListPath, $content, [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($BackupListPath, $content, [System.Text.UTF8Encoding]::new($true))
|
||||||
Write-Log "已生成配置,包含 $($paths.Count) 个项目,请检查后重新运行" -Level INFO
|
Write-Log "已生成配置,包含 $($paths.Count) 个项目,请检查后重新运行" -Level INFO
|
||||||
Stop-BaknretLog
|
Stop-BaknretLog
|
||||||
exit 0
|
exit 0
|
||||||
@@ -509,7 +509,7 @@ function Test-EntrySelected {
|
|||||||
# 主流程
|
# 主流程
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
||||||
$lines = Get-Content -LiteralPath $BackupListPath -ErrorAction Stop
|
$lines = Get-Content -Encoding UTF8 -LiteralPath $BackupListPath -ErrorAction Stop
|
||||||
$stats = @{ restored = 0; skipped = 0; failed = 0; verified = 0; planned = 0 }
|
$stats = @{ restored = 0; skipped = 0; failed = 0; verified = 0; planned = 0 }
|
||||||
$securityApplied = 0 # 本次回放成功的安全描述符对象数
|
$securityApplied = 0 # 本次回放成功的安全描述符对象数
|
||||||
$failures = @()
|
$failures = @()
|
||||||
|
|||||||
@@ -94,6 +94,9 @@ function Invoke-ScriptInHost {
|
|||||||
$argumentList = @('-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', $ScriptPath) + $Arguments
|
$argumentList = @('-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', $ScriptPath) + $Arguments
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
# 5.1 在 $ErrorActionPreference = 'Stop' 下会把原生命令写到 stderr 的内容升级成
|
||||||
|
# 终止性错误;而被调脚本往 stderr 写字是正常的(7z 就这么干),不该让验收崩掉。
|
||||||
|
$ErrorActionPreference = 'Continue'
|
||||||
if ($Quiet) {
|
if ($Quiet) {
|
||||||
& $exeOf[$HostName] @argumentList *> $null
|
& $exeOf[$HostName] @argumentList *> $null
|
||||||
} else {
|
} else {
|
||||||
@@ -176,6 +179,7 @@ function Invoke-ParseLayer {
|
|||||||
Set-Content -LiteralPath $probe -Value $parseProbeSource -Encoding ascii
|
Set-Content -LiteralPath $probe -Value $parseProbeSource -Encoding ascii
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
$ErrorActionPreference = 'Continue' # 同上:原生命令的 stderr 不是错误
|
||||||
$output = & $exeOf[$HostName] -NoProfile -ExecutionPolicy Bypass -File $probe $root 2>&1
|
$output = & $exeOf[$HostName] -NoProfile -ExecutionPolicy Bypass -File $probe $root 2>&1
|
||||||
$summary = @($output | Where-Object { $_ -match '^SUMMARY=' })
|
$summary = @($output | Where-Object { $_ -match '^SUMMARY=' })
|
||||||
$failures = @($output | Where-Object { $_ -match '^\s+\[!\]' })
|
$failures = @($output | Where-Object { $_ -match '^\s+\[!\]' })
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ BeforeAll {
|
|||||||
|
|
||||||
function Write-ListFile {
|
function Write-ListFile {
|
||||||
param([Parameter(Mandatory = $true)][string]$Path, [Parameter(Mandatory = $true)][string]$Content)
|
param([Parameter(Mandatory = $true)][string]$Path, [Parameter(Mandatory = $true)][string]$Content)
|
||||||
[System.IO.File]::WriteAllText($Path, $Content, [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($Path, $Content, [System.Text.UTF8Encoding]::new($true))
|
||||||
return $Path
|
return $Path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,18 +102,18 @@ Describe '软件名录:Slot 形状(新契约)' {
|
|||||||
$script:DirB = Join-Path $script:FormatRoot 'dirB'
|
$script:DirB = Join-Path $script:FormatRoot 'dirB'
|
||||||
foreach ($directory in $script:DirA, $script:DirB) {
|
foreach ($directory in $script:DirA, $script:DirB) {
|
||||||
New-Item -ItemType Directory -Path $directory -Force | Out-Null
|
New-Item -ItemType Directory -Path $directory -Force | Out-Null
|
||||||
Set-Content -LiteralPath (Join-Path $directory 'keep.txt') "keep-$directory"
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $directory 'keep.txt') "keep-$directory"
|
||||||
}
|
}
|
||||||
New-Item -ItemType Directory -Path (Join-Path $script:DirA 'Cache') -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $script:DirA 'Cache') -Force | Out-Null
|
||||||
Set-Content -LiteralPath (Join-Path $script:DirA 'Cache\c.bin') 'cache'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:DirA 'Cache\c.bin') 'cache'
|
||||||
$script:CfgFile = Join-Path $script:FormatRoot 'settings.json'
|
$script:CfgFile = Join-Path $script:FormatRoot 'settings.json'
|
||||||
Set-Content -LiteralPath $script:CfgFile '{"a":1}'
|
Set-Content -Encoding UTF8 -LiteralPath $script:CfgFile '{"a":1}'
|
||||||
|
|
||||||
# 两个不同父目录下各有一个**同名**子目录 —— 供"归档内同名"冲突测试用
|
# 两个不同父目录下各有一个**同名**子目录 —— 供"归档内同名"冲突测试用
|
||||||
$script:CollideRoot = Join-Path $script:FormatRoot 'collide'
|
$script:CollideRoot = Join-Path $script:FormatRoot 'collide'
|
||||||
foreach ($parent in 'p1', 'p2') {
|
foreach ($parent in 'p1', 'p2') {
|
||||||
New-Item -ItemType Directory -Path (Join-Path $script:CollideRoot "$parent\dupdir") -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $script:CollideRoot "$parent\dupdir") -Force | Out-Null
|
||||||
Set-Content -LiteralPath (Join-Path $script:CollideRoot "$parent\dupdir\x.txt") $parent
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:CollideRoot "$parent\dupdir\x.txt") $parent
|
||||||
}
|
}
|
||||||
|
|
||||||
$script:MissingDir = Join-Path $script:FormatRoot 'not-here'
|
$script:MissingDir = Join-Path $script:FormatRoot 'not-here'
|
||||||
@@ -324,12 +324,12 @@ Describe '集成:Slot 布局的打包与恢复' -Skip:(-not ($script:HasSevenZ
|
|||||||
New-Item -ItemType Directory -Path $script:SlotCfgDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $script:SlotCfgDir -Force | Out-Null
|
||||||
New-Item -ItemType Directory -Path $script:SlotInclude -Force | Out-Null
|
New-Item -ItemType Directory -Path $script:SlotInclude -Force | Out-Null
|
||||||
|
|
||||||
Set-Content -LiteralPath (Join-Path $script:SlotAppOne 'one.txt') 'one'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:SlotAppOne 'one.txt') 'one'
|
||||||
Set-Content -LiteralPath (Join-Path $script:SlotAppOne 'sub\deep.txt') 'deep'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:SlotAppOne 'sub\deep.txt') 'deep'
|
||||||
Set-Content -LiteralPath (Join-Path $script:SlotAppOne 'Cache\c.bin') 'cache'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:SlotAppOne 'Cache\c.bin') 'cache'
|
||||||
Set-Content -LiteralPath (Join-Path $script:SlotAppTwo 'two.txt') 'two'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:SlotAppTwo 'two.txt') 'two'
|
||||||
Set-Content -LiteralPath (Join-Path $script:SlotCfgDir 'settings.json') '{"a":1}'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:SlotCfgDir 'settings.json') '{"a":1}'
|
||||||
Set-Content -LiteralPath (Join-Path $script:SlotInclude 'mod.txt') 'mod'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:SlotInclude 'mod.txt') 'mod'
|
||||||
|
|
||||||
$appOne = $script:SlotAppOne
|
$appOne = $script:SlotAppOne
|
||||||
$appTwo = $script:SlotAppTwo
|
$appTwo = $script:SlotAppTwo
|
||||||
@@ -388,7 +388,7 @@ Describe '集成:Slot 布局的打包与恢复' -Skip:(-not ($script:HasSevenZ
|
|||||||
Test-Path -LiteralPath (Join-Path $verify 'Extra\two.txt') | Should -BeTrue
|
Test-Path -LiteralPath (Join-Path $verify 'Extra\two.txt') | Should -BeTrue
|
||||||
Test-Path -LiteralPath (Join-Path $verify 'Modules\mod.txt') | Should -BeTrue
|
Test-Path -LiteralPath (Join-Path $verify 'Modules\mod.txt') | Should -BeTrue
|
||||||
Test-Path -LiteralPath (Join-Path $verify 'Cfg') -PathType Leaf | Should -BeTrue
|
Test-Path -LiteralPath (Join-Path $verify 'Cfg') -PathType Leaf | Should -BeTrue
|
||||||
(Get-Content -LiteralPath (Join-Path $verify 'Cfg') -Raw).Trim() | Should -Be '{"a":1}'
|
(Get-Content -Encoding UTF8 -LiteralPath (Join-Path $verify 'Cfg') -Raw).Trim() | Should -Be '{"a":1}'
|
||||||
}
|
}
|
||||||
|
|
||||||
It '真实恢复:目录 Slot、文件 Slot 与 Include 都落回各自的原位' {
|
It '真实恢复:目录 Slot、文件 Slot 与 Include 都落回各自的原位' {
|
||||||
@@ -404,10 +404,10 @@ Describe '集成:Slot 布局的打包与恢复' -Skip:(-not ($script:HasSevenZ
|
|||||||
$run.ExitCode | Should -Be 0
|
$run.ExitCode | Should -Be 0
|
||||||
$run.Output | Should -Match '恢复成功: appkit'
|
$run.Output | Should -Match '恢复成功: appkit'
|
||||||
|
|
||||||
(Get-Content -LiteralPath (Join-Path $script:SlotAppOne 'one.txt') -Raw).Trim() | Should -Be 'one'
|
(Get-Content -Encoding UTF8 -LiteralPath (Join-Path $script:SlotAppOne 'one.txt') -Raw).Trim() | Should -Be 'one'
|
||||||
(Get-Content -LiteralPath (Join-Path $script:SlotAppOne 'sub\deep.txt') -Raw).Trim() | Should -Be 'deep'
|
(Get-Content -Encoding UTF8 -LiteralPath (Join-Path $script:SlotAppOne 'sub\deep.txt') -Raw).Trim() | Should -Be 'deep'
|
||||||
(Get-Content -LiteralPath (Join-Path $script:SlotAppTwo 'two.txt') -Raw).Trim() | Should -Be 'two'
|
(Get-Content -Encoding UTF8 -LiteralPath (Join-Path $script:SlotAppTwo 'two.txt') -Raw).Trim() | Should -Be 'two'
|
||||||
(Get-Content -LiteralPath (Join-Path $script:SlotInclude 'mod.txt') -Raw).Trim() | Should -Be 'mod'
|
(Get-Content -Encoding UTF8 -LiteralPath (Join-Path $script:SlotInclude 'mod.txt') -Raw).Trim() | Should -Be 'mod'
|
||||||
|
|
||||||
# 被 Slot 排除的缓存没有进过归档,自然也不会被恢复出来
|
# 被 Slot 排除的缓存没有进过归档,自然也不会被恢复出来
|
||||||
Test-Path -LiteralPath (Join-Path $script:SlotAppOne 'Cache\c.bin') | Should -BeFalse
|
Test-Path -LiteralPath (Join-Path $script:SlotAppOne 'Cache\c.bin') | Should -BeFalse
|
||||||
@@ -417,7 +417,7 @@ Describe '集成:Slot 布局的打包与恢复' -Skip:(-not ($script:HasSevenZ
|
|||||||
# 目标文件被删掉了,名录解析只能得到 IsFile=false;判据要靠 manifest 的 layouts。
|
# 目标文件被删掉了,名录解析只能得到 IsFile=false;判据要靠 manifest 的 layouts。
|
||||||
$restored = Join-Path $script:SlotCfgDir 'settings.json'
|
$restored = Join-Path $script:SlotCfgDir 'settings.json'
|
||||||
(Test-Path -LiteralPath $restored -PathType Leaf) | Should -BeTrue
|
(Test-Path -LiteralPath $restored -PathType Leaf) | Should -BeTrue
|
||||||
(Get-Content -LiteralPath $restored -Raw).Trim() | Should -Be '{"a":1}'
|
(Get-Content -Encoding UTF8 -LiteralPath $restored -Raw).Trim() | Should -Be '{"a":1}'
|
||||||
}
|
}
|
||||||
|
|
||||||
It '恢复之后 manifest 记下 lastRestoreAt' {
|
It '恢复之后 manifest 记下 lastRestoreAt' {
|
||||||
@@ -440,7 +440,7 @@ Describe '集成:旧布局归档的回退恢复' -Skip:(-not ($script:HasSeven
|
|||||||
$script:LegacyLeaf = 'My Code Space'
|
$script:LegacyLeaf = 'My Code Space'
|
||||||
New-Item -ItemType Directory -Path (Join-Path $script:LegacyHolder $script:LegacyLeaf) -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $script:LegacyHolder $script:LegacyLeaf) -Force | Out-Null
|
||||||
New-Item -ItemType Directory -Path $script:LegacyDestParent -Force | Out-Null
|
New-Item -ItemType Directory -Path $script:LegacyDestParent -Force | Out-Null
|
||||||
Set-Content -LiteralPath (Join-Path $script:LegacyHolder "$script:LegacyLeaf\legacy.txt") 'old-layout'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:LegacyHolder "$script:LegacyLeaf\legacy.txt") 'old-layout'
|
||||||
|
|
||||||
$destPath = Join-Path $script:LegacyDestParent $script:LegacyLeaf
|
$destPath = Join-Path $script:LegacyDestParent $script:LegacyLeaf
|
||||||
$script:LegacyCatalog = Write-ListFile -Path (Join-Path $script:LegacyRoot 'cat.psd1') -Content @"
|
$script:LegacyCatalog = Write-ListFile -Path (Join-Path $script:LegacyRoot 'cat.psd1') -Content @"
|
||||||
@@ -480,7 +480,7 @@ Describe '集成:旧布局归档的回退恢复' -Skip:(-not ($script:HasSeven
|
|||||||
$run.ExitCode | Should -Be 0
|
$run.ExitCode | Should -Be 0
|
||||||
$run.Output | Should -Match '按旧布局回退'
|
$run.Output | Should -Match '按旧布局回退'
|
||||||
Test-Path -LiteralPath (Join-Path $script:LegacyDestParent "$script:LegacyLeaf\legacy.txt") | Should -BeTrue
|
Test-Path -LiteralPath (Join-Path $script:LegacyDestParent "$script:LegacyLeaf\legacy.txt") | Should -BeTrue
|
||||||
(Get-Content -LiteralPath (Join-Path $script:LegacyDestParent "$script:LegacyLeaf\legacy.txt") -Raw).Trim() | Should -Be 'old-layout'
|
(Get-Content -Encoding UTF8 -LiteralPath (Join-Path $script:LegacyDestParent "$script:LegacyLeaf\legacy.txt") -Raw).Trim() | Should -Be 'old-layout'
|
||||||
}
|
}
|
||||||
|
|
||||||
It '归档里既没有 Slot 层、也没有旧布局名字时明确失败(不再"成功地什么都没恢复")' {
|
It '归档里既没有 Slot 层、也没有旧布局名字时明确失败(不再"成功地什么都没恢复")' {
|
||||||
@@ -513,7 +513,7 @@ Describe '集成:归档内路径冲突会被拒绝执行' -Skip:(-not ($script
|
|||||||
$p2 = Join-Path $script:RejectRoot 'p2\dupdir'
|
$p2 = Join-Path $script:RejectRoot 'p2\dupdir'
|
||||||
foreach ($directory in $p1, $p2) {
|
foreach ($directory in $p1, $p2) {
|
||||||
New-Item -ItemType Directory -Path $directory -Force | Out-Null
|
New-Item -ItemType Directory -Path $directory -Force | Out-Null
|
||||||
Set-Content -LiteralPath (Join-Path $directory 'x.txt') 'x'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $directory 'x.txt') 'x'
|
||||||
}
|
}
|
||||||
# Slot 叫 Data,Include 也要放进包内的 Data -> 同一个位置,必须报错
|
# Slot 叫 Data,Include 也要放进包内的 Data -> 同一个位置,必须报错
|
||||||
Write-ListFile -Path $script:RejectCatalog -Content "@{`n 'collide' = @{ Data = @{ Path = '$p1' } }`n}`n" | Out-Null
|
Write-ListFile -Path $script:RejectCatalog -Content "@{`n 'collide' = @{ Data = @{ Path = '$p1' } }`n}`n" | Out-Null
|
||||||
@@ -556,7 +556,7 @@ Describe '条目从清单里消失后,旧归档必须被点名为孤儿' -Skip
|
|||||||
$script:OrphanRoot = Join-Path $script:Sandbox 'orphan-e2e'
|
$script:OrphanRoot = Join-Path $script:Sandbox 'orphan-e2e'
|
||||||
$script:OrphanSource = Join-Path $script:OrphanRoot 'src\My App'
|
$script:OrphanSource = Join-Path $script:OrphanRoot 'src\My App'
|
||||||
New-Item -ItemType Directory -Path $script:OrphanSource -Force | Out-Null
|
New-Item -ItemType Directory -Path $script:OrphanSource -Force | Out-Null
|
||||||
Set-Content -LiteralPath (Join-Path $script:OrphanSource 'data.txt') 'hello'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:OrphanSource 'data.txt') 'hello'
|
||||||
|
|
||||||
$script:OrphanCatalog = Write-ListFile -Path (Join-Path $script:OrphanRoot 'cat.psd1') `
|
$script:OrphanCatalog = Write-ListFile -Path (Join-Path $script:OrphanRoot 'cat.psd1') `
|
||||||
-Content "@{ 'my-app' = @{ Default = @{ Path = '$script:OrphanSource' } } }`n"
|
-Content "@{ 'my-app' = @{ Default = @{ Path = '$script:OrphanSource' } } }`n"
|
||||||
@@ -606,7 +606,7 @@ Describe 'manifest 一致性:archive 字段只在文件真的存在时才写'
|
|||||||
BeforeAll {
|
BeforeAll {
|
||||||
$script:SyncRoot = Join-Path $script:Sandbox 'sync'
|
$script:SyncRoot = Join-Path $script:Sandbox 'sync'
|
||||||
New-Item -ItemType Directory -Path $script:SyncRoot -Force | Out-Null
|
New-Item -ItemType Directory -Path $script:SyncRoot -Force | Out-Null
|
||||||
Set-Content -LiteralPath (Join-Path $script:SyncRoot 'real.7z') 'x'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:SyncRoot 'real.7z') 'x'
|
||||||
|
|
||||||
$script:SyncManifestPath = Join-Path $script:SyncRoot 'manifest.json'
|
$script:SyncManifestPath = Join-Path $script:SyncRoot 'manifest.json'
|
||||||
$manifest = Read-BaknretManifest -Path $script:SyncManifestPath
|
$manifest = Read-BaknretManifest -Path $script:SyncManifestPath
|
||||||
|
|||||||
@@ -97,8 +97,22 @@ BeforeAll {
|
|||||||
<# .SYNOPSIS 先把 ACL 复位再删:拒绝型 / protected 的 DACL 会让 Remove-Item 直接失败。 #>
|
<# .SYNOPSIS 先把 ACL 复位再删:拒绝型 / protected 的 DACL 会让 Remove-Item 直接失败。 #>
|
||||||
param([Parameter(Mandatory = $true)][string]$Path)
|
param([Parameter(Mandatory = $true)][string]$Path)
|
||||||
if (-not (Test-Path -LiteralPath $Path)) { return }
|
if (-not (Test-Path -LiteralPath $Path)) { return }
|
||||||
& takeown.exe /F $Path /R /D Y 2>&1 | Out-Null
|
|
||||||
& icacls.exe $Path /reset /T /C /Q 2>&1 | Out-Null
|
# 这两个是原生命令,失败与否都不该打断测试 —— 它们的唯一目的是"把 ACL 复位到能删"。
|
||||||
|
#
|
||||||
|
# 必须在 Continue 下调用:Windows PowerShell 5.1 在 $ErrorActionPreference = 'Stop'
|
||||||
|
# 时,会把原生命令写到 stderr 的内容升级成终止性的 NativeCommandError 抛出来
|
||||||
|
# (takeown / icacls 对"已经处理过"的对象就会写 stderr)。PowerShell 7 改了这条
|
||||||
|
# 规矩,所以这段在 7 上一直是绿的,只在 5.1 上炸。
|
||||||
|
$previousPreference = $ErrorActionPreference
|
||||||
|
$ErrorActionPreference = 'Continue'
|
||||||
|
try {
|
||||||
|
& takeown.exe /F $Path /R /D Y 2>&1 | Out-Null
|
||||||
|
& icacls.exe $Path /reset /T /C /Q 2>&1 | Out-Null
|
||||||
|
} finally {
|
||||||
|
$ErrorActionPreference = $previousPreference
|
||||||
|
}
|
||||||
|
|
||||||
Remove-Item -LiteralPath $Path -Recurse -Force -ErrorAction SilentlyContinue
|
Remove-Item -LiteralPath $Path -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,7 +174,7 @@ BeforeAll {
|
|||||||
New-Item -ItemType Directory -Path $backupDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $backupDir -Force | Out-Null
|
||||||
|
|
||||||
$listPath = Join-Path $dir 'BackupList.txt'
|
$listPath = Join-Path $dir 'BackupList.txt'
|
||||||
[System.IO.File]::WriteAllText($listPath, "$sourcePath`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($listPath, "$sourcePath`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
|
|
||||||
$configPath = Join-Path $dir 'BackupConfig.psd1'
|
$configPath = Join-Path $dir 'BackupConfig.psd1'
|
||||||
$configText = @"
|
$configText = @"
|
||||||
@@ -180,7 +194,7 @@ BeforeAll {
|
|||||||
DefaultExcludes = @()
|
DefaultExcludes = @()
|
||||||
}
|
}
|
||||||
"@
|
"@
|
||||||
[System.IO.File]::WriteAllText($configPath, $configText, [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($configPath, $configText, [System.Text.UTF8Encoding]::new($true))
|
||||||
|
|
||||||
return [pscustomobject]@{
|
return [pscustomobject]@{
|
||||||
Dir = $dir
|
Dir = $dir
|
||||||
@@ -426,7 +440,7 @@ Describe '与 Backup.ps1 / Restore.ps1 的集成' -Skip:(-not $script:HasSevenZi
|
|||||||
$sidecars.Count | Should -Be 1
|
$sidecars.Count | Should -Be 1
|
||||||
$result.Output | Should -Match '安全描述符:3 个对象'
|
$result.Output | Should -Match '安全描述符:3 个对象'
|
||||||
|
|
||||||
$manifest = Get-Content -LiteralPath (Join-Path $script:Harness.BackupDir 'manifest.json') -Raw | ConvertFrom-Json
|
$manifest = Get-Content -Encoding UTF8 -LiteralPath (Join-Path $script:Harness.BackupDir 'manifest.json') -Raw | ConvertFrom-Json
|
||||||
$key = @($manifest.items.PSObject.Properties.Name)[0]
|
$key = @($manifest.items.PSObject.Properties.Name)[0]
|
||||||
$manifest.items.$key.security.file | Should -Be $sidecars[0].Name
|
$manifest.items.$key.security.file | Should -Be $sidecars[0].Name
|
||||||
$manifest.items.$key.security.objects | Should -Be 3
|
$manifest.items.$key.security.objects | Should -Be 3
|
||||||
|
|||||||
+16
-16
@@ -121,7 +121,7 @@ BeforeAll {
|
|||||||
|
|
||||||
function Write-ListFile {
|
function Write-ListFile {
|
||||||
param([Parameter(Mandatory = $true)][string]$Path, [Parameter(Mandatory = $true)][string]$Content)
|
param([Parameter(Mandatory = $true)][string]$Path, [Parameter(Mandatory = $true)][string]$Content)
|
||||||
[System.IO.File]::WriteAllText($Path, $Content, [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($Path, $Content, [System.Text.UTF8Encoding]::new($true))
|
||||||
return $Path
|
return $Path
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -348,7 +348,7 @@ Describe '归档命名' {
|
|||||||
$script:NamingRoot = Join-Path $script:Sandbox 'naming'
|
$script:NamingRoot = Join-Path $script:Sandbox 'naming'
|
||||||
$script:NamingApp = Join-Path $script:NamingRoot 'Real App'
|
$script:NamingApp = Join-Path $script:NamingRoot 'Real App'
|
||||||
New-Item -ItemType Directory -Path $script:NamingApp -Force | Out-Null
|
New-Item -ItemType Directory -Path $script:NamingApp -Force | Out-Null
|
||||||
Set-Content -LiteralPath (Join-Path $script:NamingApp 'keep.txt') 'k'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:NamingApp 'keep.txt') 'k'
|
||||||
|
|
||||||
$script:NamingCatalog = Write-ListFile -Path (Join-Path $script:NamingRoot 'cat.psd1') -Content @"
|
$script:NamingCatalog = Write-ListFile -Path (Join-Path $script:NamingRoot 'cat.psd1') -Content @"
|
||||||
@{
|
@{
|
||||||
@@ -415,8 +415,8 @@ Describe '7z 排除参数翻译' {
|
|||||||
$script:ExcludeTree = Join-Path $script:Sandbox 'exclude-tree'
|
$script:ExcludeTree = Join-Path $script:Sandbox 'exclude-tree'
|
||||||
New-Item -ItemType Directory -Path (Join-Path $script:ExcludeTree 'sub\Cache') -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $script:ExcludeTree 'sub\Cache') -Force | Out-Null
|
||||||
New-Item -ItemType Directory -Path (Join-Path $script:ExcludeTree 'Keep') -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $script:ExcludeTree 'Keep') -Force | Out-Null
|
||||||
Set-Content -LiteralPath (Join-Path $script:ExcludeTree 'sub\Cache\x.bin') 'x'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:ExcludeTree 'sub\Cache\x.bin') 'x'
|
||||||
Set-Content -LiteralPath (Join-Path $script:ExcludeTree 'Keep\y.bin') 'y'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:ExcludeTree 'Keep\y.bin') 'y'
|
||||||
|
|
||||||
function New-TestArchiveItem {
|
function New-TestArchiveItem {
|
||||||
param([string]$ArchivePath, [string]$RealPath = 'C:\nonexistent-path')
|
param([string]$ArchivePath, [string]$RealPath = 'C:\nonexistent-path')
|
||||||
@@ -573,8 +573,8 @@ Describe '归档项与暂存目录' {
|
|||||||
$script:StagingDir = Join-Path $script:StagingRoot 'real-dir'
|
$script:StagingDir = Join-Path $script:StagingRoot 'real-dir'
|
||||||
$script:StagingFile = Join-Path $script:StagingRoot 'settings.json'
|
$script:StagingFile = Join-Path $script:StagingRoot 'settings.json'
|
||||||
New-Item -ItemType Directory -Path (Join-Path $script:StagingDir 'inner') -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $script:StagingDir 'inner') -Force | Out-Null
|
||||||
Set-Content -LiteralPath (Join-Path $script:StagingDir 'inner\a.txt') 'a'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:StagingDir 'inner\a.txt') 'a'
|
||||||
Set-Content -LiteralPath $script:StagingFile 'file-content'
|
Set-Content -Encoding UTF8 -LiteralPath $script:StagingFile 'file-content'
|
||||||
}
|
}
|
||||||
|
|
||||||
It 'New-BaknretArchiveItem 规范化归档内路径并算出 TopName' {
|
It 'New-BaknretArchiveItem 规范化归档内路径并算出 TopName' {
|
||||||
@@ -611,7 +611,7 @@ Describe '归档项与暂存目录' {
|
|||||||
# 文件项:归档内的名字就叫 Cfg(没有扩展名),内容与源文件一致
|
# 文件项:归档内的名字就叫 Cfg(没有扩展名),内容与源文件一致
|
||||||
$cfg = Get-Item -LiteralPath (Join-Path $stage 'Cfg') -Force
|
$cfg = Get-Item -LiteralPath (Join-Path $stage 'Cfg') -Force
|
||||||
$cfg.PSIsContainer | Should -BeFalse
|
$cfg.PSIsContainer | Should -BeFalse
|
||||||
(Get-Content -LiteralPath $cfg.FullName -Raw).Trim() | Should -Be 'file-content'
|
(Get-Content -Encoding UTF8 -LiteralPath $cfg.FullName -Raw).Trim() | Should -Be 'file-content'
|
||||||
} finally {
|
} finally {
|
||||||
Remove-BaknretArchiveStaging -Root $stage
|
Remove-BaknretArchiveStaging -Root $stage
|
||||||
}
|
}
|
||||||
@@ -734,8 +734,8 @@ Describe '软件名录' {
|
|||||||
New-Item -ItemType Directory -Path (Join-Path $script:CatRoot 'real app') -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $script:CatRoot 'real app') -Force | Out-Null
|
||||||
New-Item -ItemType Directory -Path (Join-Path $script:CatRoot 'other') -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $script:CatRoot 'other') -Force | Out-Null
|
||||||
New-Item -ItemType Directory -Path (Join-Path $script:CatRoot 'inc') -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $script:CatRoot 'inc') -Force | Out-Null
|
||||||
Set-Content -LiteralPath (Join-Path $script:CatRoot 'real app\keep.txt') 'k'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:CatRoot 'real app\keep.txt') 'k'
|
||||||
Set-Content -LiteralPath (Join-Path $script:CatRoot 'file.txt') 'file-content'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:CatRoot 'file.txt') 'file-content'
|
||||||
|
|
||||||
$script:CatReal = Join-Path $script:CatRoot 'real app'
|
$script:CatReal = Join-Path $script:CatRoot 'real app'
|
||||||
$script:CatOther = Join-Path $script:CatRoot 'other'
|
$script:CatOther = Join-Path $script:CatRoot 'other'
|
||||||
@@ -1090,12 +1090,12 @@ Describe '集成:真实 7z 压缩与排除规则' -Skip:(-not $script:HasSeven
|
|||||||
foreach ($directory in 'Default\Cache', 'Default\Code Cache', 'Default\Extensions', 'component_crx_cache', 'Default\IndexedDB') {
|
foreach ($directory in 'Default\Cache', 'Default\Code Cache', 'Default\Extensions', 'component_crx_cache', 'Default\IndexedDB') {
|
||||||
New-Item -ItemType Directory -Path (Join-Path $script:IntegrationPath $directory) -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $script:IntegrationPath $directory) -Force | Out-Null
|
||||||
}
|
}
|
||||||
Set-Content -LiteralPath (Join-Path $script:IntegrationPath 'keep.txt') 'keep'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:IntegrationPath 'keep.txt') 'keep'
|
||||||
Set-Content -LiteralPath (Join-Path $script:IntegrationPath 'Default\Cache\c.bin') 'c'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:IntegrationPath 'Default\Cache\c.bin') 'c'
|
||||||
Set-Content -LiteralPath (Join-Path $script:IntegrationPath 'Default\Code Cache\cc.bin') 'cc'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:IntegrationPath 'Default\Code Cache\cc.bin') 'cc'
|
||||||
Set-Content -LiteralPath (Join-Path $script:IntegrationPath 'Default\Extensions\e.bin') 'e'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:IntegrationPath 'Default\Extensions\e.bin') 'e'
|
||||||
Set-Content -LiteralPath (Join-Path $script:IntegrationPath 'component_crx_cache\x.bin') 'x'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:IntegrationPath 'component_crx_cache\x.bin') 'x'
|
||||||
Set-Content -LiteralPath (Join-Path $script:IntegrationPath 'Default\IndexedDB\i.bin') 'i'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:IntegrationPath 'Default\IndexedDB\i.bin') 'i'
|
||||||
}
|
}
|
||||||
|
|
||||||
It '排除规则与空格处理在真实归档上生效' {
|
It '排除规则与空格处理在真实归档上生效' {
|
||||||
@@ -1326,7 +1326,7 @@ Describe '集成:方向标记与孤儿审计' -Skip:(-not ($script:HasSevenZip
|
|||||||
$script:DirectionRoot = Join-Path $script:Sandbox 'direction'
|
$script:DirectionRoot = Join-Path $script:Sandbox 'direction'
|
||||||
$script:DirectionSource = Join-Path $script:DirectionRoot 'src\Keep Me'
|
$script:DirectionSource = Join-Path $script:DirectionRoot 'src\Keep Me'
|
||||||
New-Item -ItemType Directory -Path $script:DirectionSource -Force | Out-Null
|
New-Item -ItemType Directory -Path $script:DirectionSource -Force | Out-Null
|
||||||
Set-Content -LiteralPath (Join-Path $script:DirectionSource 'data.txt') 'keep'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $script:DirectionSource 'data.txt') 'keep'
|
||||||
|
|
||||||
$script:DirectionBackupDir = Join-Path $script:DirectionRoot 'Backups'
|
$script:DirectionBackupDir = Join-Path $script:DirectionRoot 'Backups'
|
||||||
$script:DirectionList = Join-Path $script:DirectionRoot 'list.txt'
|
$script:DirectionList = Join-Path $script:DirectionRoot 'list.txt'
|
||||||
|
|||||||
@@ -444,7 +444,7 @@ foreach ($name in $Entries) {
|
|||||||
|
|
||||||
[System.IO.File]::WriteAllText($scratchCatalog,
|
[System.IO.File]::WriteAllText($scratchCatalog,
|
||||||
"@{`n '$catalogKey' = @{`n$($slotLines -join "`n")`n }`n}`n", [System.Text.UTF8Encoding]::new($false))
|
"@{`n '$catalogKey' = @{`n$($slotLines -join "`n")`n }`n}`n", [System.Text.UTF8Encoding]::new($false))
|
||||||
[System.IO.File]::WriteAllText($scratchList, "$catalogKey`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($scratchList, "$catalogKey`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
[System.IO.File]::WriteAllText($scratchConfig, @"
|
[System.IO.File]::WriteAllText($scratchConfig, @"
|
||||||
@{
|
@{
|
||||||
BackupDir = '$scratchBackupRoot'
|
BackupDir = '$scratchBackupRoot'
|
||||||
@@ -461,7 +461,7 @@ foreach ($name in $Entries) {
|
|||||||
|
|
||||||
if ($restore.Code -ne 0) {
|
if ($restore.Code -ne 0) {
|
||||||
if ($restore.Log) {
|
if ($restore.Log) {
|
||||||
foreach ($line in @(Get-Content -LiteralPath $restore.Log.FullName -ErrorAction SilentlyContinue | Select-Object -Last 12)) {
|
foreach ($line in @(Get-Content -Encoding UTF8 -LiteralPath $restore.Log.FullName -ErrorAction SilentlyContinue | Select-Object -Last 12)) {
|
||||||
Write-Host (" | {0}" -f $line) -ForegroundColor DarkGray
|
Write-Host (" | {0}" -f $line) -ForegroundColor DarkGray
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-19
@@ -74,7 +74,7 @@ function New-E2EConfig {
|
|||||||
if ($SoftwareCatalog) { $lines += " SoftwareCatalog = '$SoftwareCatalog'" }
|
if ($SoftwareCatalog) { $lines += " SoftwareCatalog = '$SoftwareCatalog'" }
|
||||||
$lines += " CatalogMaxDepth = $CatalogMaxDepth"
|
$lines += " CatalogMaxDepth = $CatalogMaxDepth"
|
||||||
$lines += '}'
|
$lines += '}'
|
||||||
[System.IO.File]::WriteAllText($Path, ($lines -join "`r`n"), [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($Path, ($lines -join "`r`n"), [System.Text.UTF8Encoding]::new($true))
|
||||||
}
|
}
|
||||||
|
|
||||||
function Get-NewestLog {
|
function Get-NewestLog {
|
||||||
@@ -141,7 +141,7 @@ $blob = New-Object byte[] 8192
|
|||||||
(New-Object System.Random 42).NextBytes($blob)
|
(New-Object System.Random 42).NextBytes($blob)
|
||||||
[System.IO.File]::WriteAllBytes((Join-Path $source 'blob.bin'), $blob)
|
[System.IO.File]::WriteAllBytes((Join-Path $source 'blob.bin'), $blob)
|
||||||
|
|
||||||
[System.IO.File]::WriteAllText($listPath, "# e2e`n$source :- logs\,!*Cache`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($listPath, "# e2e`n$source :- logs\,!*Cache`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
|
|
||||||
$expectedHashes = @{}
|
$expectedHashes = @{}
|
||||||
foreach ($relative in 'keep.txt', 'sub\b.txt', 'blob.bin') {
|
foreach ($relative in 'keep.txt', 'sub\b.txt', 'blob.bin') {
|
||||||
@@ -243,7 +243,7 @@ $cfg2 = Join-Path $WorkRoot 'cfg2.psd1'
|
|||||||
New-E2EConfig -Path $cfg2 -LogDir $logDir2
|
New-E2EConfig -Path $cfg2 -LogDir $logDir2
|
||||||
New-Item -ItemType Directory -Path $lockSource -Force | Out-Null
|
New-Item -ItemType Directory -Path $lockSource -Force | Out-Null
|
||||||
Set-Content -LiteralPath (Join-Path $lockSource 'a.txt') -Value 'aaa' -Encoding UTF8
|
Set-Content -LiteralPath (Join-Path $lockSource 'a.txt') -Value 'aaa' -Encoding UTF8
|
||||||
[System.IO.File]::WriteAllText($lockList, "$lockSource`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($lockList, "$lockSource`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
|
|
||||||
& $backupScript -BackupListPath $lockList -BackupDir $lockBackupDir -ConfigPath $cfg2 -Force -QuietTool
|
& $backupScript -BackupListPath $lockList -BackupDir $lockBackupDir -ConfigPath $cfg2 -Force -QuietTool
|
||||||
$cleanExitCode = $LASTEXITCODE
|
$cleanExitCode = $LASTEXITCODE
|
||||||
@@ -335,7 +335,7 @@ Set-Content -LiteralPath (Join-Path $incDir 'i.txt') -Value 'included' -Encoding
|
|||||||
"@, [System.Text.UTF8Encoding]::new($false))
|
"@, [System.Text.UTF8Encoding]::new($false))
|
||||||
|
|
||||||
# 条目级排除用 Slot 前缀点名(AlphaData\plain)+ 任意层级(!*skip);:+ 把 inc 放到归档内 Modules\
|
# 条目级排除用 Slot 前缀点名(AlphaData\plain)+ 任意层级(!*skip);:+ 把 inc 放到归档内 Modules\
|
||||||
[System.IO.File]::WriteAllText($catList, "my-app :- AlphaData\plain,!*skip :+ Modules:$incDir`ncat-excl`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($catList, "my-app :- AlphaData\plain,!*skip :+ Modules:$incDir`ncat-excl`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
New-E2EConfig -Path $catConfig -LogDir $catLogDir -SoftwareCatalog $catFile
|
New-E2EConfig -Path $catConfig -LogDir $catLogDir -SoftwareCatalog $catFile
|
||||||
|
|
||||||
$catHashes = @{
|
$catHashes = @{
|
||||||
@@ -433,7 +433,7 @@ Test-Case '恢复不会把被排除的内容带回来' {
|
|||||||
Test-Case '@pathname 覆盖:用名录里的真实路径跑命名算法(独立备份目录,避免污染共享 manifest)' {
|
Test-Case '@pathname 覆盖:用名录里的真实路径跑命名算法(独立备份目录,避免污染共享 manifest)' {
|
||||||
$pathList = Join-Path $catRoot 'list-pathname.txt'
|
$pathList = Join-Path $catRoot 'list-pathname.txt'
|
||||||
$pathNameDir = Join-Path $catRoot 'Backups-pathname'
|
$pathNameDir = Join-Path $catRoot 'Backups-pathname'
|
||||||
[System.IO.File]::WriteAllText($pathList, "my-app @pathname :+ Modules:$settingsFile`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($pathList, "my-app @pathname :+ Modules:$settingsFile`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
# settings.json 刚才被删了,重建一份,让 Include 的宿主机路径存在
|
# settings.json 刚才被删了,重建一份,让 Include 的宿主机路径存在
|
||||||
Set-Content -LiteralPath $settingsFile -Value '{"slot":"file"}' -Encoding UTF8
|
Set-Content -LiteralPath $settingsFile -Value '{"slot":"file"}' -Encoding UTF8
|
||||||
$expectedBase = Get-BackupBaseName -RawPath $dirA
|
$expectedBase = Get-BackupBaseName -RawPath $dirA
|
||||||
@@ -455,8 +455,8 @@ $ovrConfig = Join-Path $ovrRoot 'config.psd1'
|
|||||||
$ovrExtract = Join-Path $ovrRoot 'verify'
|
$ovrExtract = Join-Path $ovrRoot 'verify'
|
||||||
New-Item -ItemType Directory -Path $ovrTarget -Force | Out-Null
|
New-Item -ItemType Directory -Path $ovrTarget -Force | Out-Null
|
||||||
Set-Content -LiteralPath (Join-Path $ovrTarget 't.txt') -Value 'override-target' -Encoding UTF8
|
Set-Content -LiteralPath (Join-Path $ovrTarget 't.txt') -Value 'override-target' -Encoding UTF8
|
||||||
[System.IO.File]::WriteAllText($ovrCatalog, "@{`n 'ovr-app' = @{ DefaultData = @{ Path = '$ovrRoot\missing-src' } }`n}`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($ovrCatalog, "@{`n 'ovr-app' = @{ DefaultData = @{ Path = '$ovrRoot\missing-src' } }`n}`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
[System.IO.File]::WriteAllText($ovrList, "ovr-app :: $ovrTarget`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($ovrList, "ovr-app :: $ovrTarget`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
New-E2EConfig -Path $ovrConfig -LogDir (Join-Path $ovrRoot 'logs') -SoftwareCatalog $ovrCatalog
|
New-E2EConfig -Path $ovrConfig -LogDir (Join-Path $ovrRoot 'logs') -SoftwareCatalog $ovrCatalog
|
||||||
|
|
||||||
& $backupScript -BackupListPath $ovrList -BackupDir $ovrBackupDir -ConfigPath $ovrConfig -Force -QuietTool
|
& $backupScript -BackupListPath $ovrList -BackupDir $ovrBackupDir -ConfigPath $ovrConfig -Force -QuietTool
|
||||||
@@ -471,7 +471,7 @@ Test-Case ':: 覆盖:备份包内容来自被覆盖的路径,且归档项名
|
|||||||
$null = Invoke-ExternalCommand -FilePath $sevenZip -ArgumentList @('x', '-bso0', '-bsp0', '-y', "-o$ovrExtract", $ovrArchives[0].FullName)
|
$null = Invoke-ExternalCommand -FilePath $sevenZip -ArgumentList @('x', '-bso0', '-bsp0', '-y', "-o$ovrExtract", $ovrArchives[0].FullName)
|
||||||
}
|
}
|
||||||
Assert-FileExists (Join-Path $ovrExtract 'DefaultData\t.txt')
|
Assert-FileExists (Join-Path $ovrExtract 'DefaultData\t.txt')
|
||||||
Assert-Equal 'override-target' (Get-Content -LiteralPath (Join-Path $ovrExtract 'DefaultData\t.txt') -Raw).Trim()
|
Assert-Equal 'override-target' (Get-Content -Encoding UTF8 -LiteralPath (Join-Path $ovrExtract 'DefaultData\t.txt') -Raw).Trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
Test-Case ':: 覆盖:删掉被覆盖的源后仍能恢复回该路径' {
|
Test-Case ':: 覆盖:删掉被覆盖的源后仍能恢复回该路径' {
|
||||||
@@ -479,7 +479,7 @@ Test-Case ':: 覆盖:删掉被覆盖的源后仍能恢复回该路径' {
|
|||||||
& $restoreScript -BackupListPath $ovrList -BackupDir $ovrBackupDir -ConfigPath $ovrConfig -Force
|
& $restoreScript -BackupListPath $ovrList -BackupDir $ovrBackupDir -ConfigPath $ovrConfig -Force
|
||||||
Assert-Equal 0 $LASTEXITCODE
|
Assert-Equal 0 $LASTEXITCODE
|
||||||
Assert-FileExists (Join-Path $ovrTarget 't.txt')
|
Assert-FileExists (Join-Path $ovrTarget 't.txt')
|
||||||
Assert-Equal 'override-target' (Get-Content -LiteralPath (Join-Path $ovrTarget 't.txt') -Raw).Trim()
|
Assert-Equal 'override-target' (Get-Content -Encoding UTF8 -LiteralPath (Join-Path $ovrTarget 't.txt') -Raw).Trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
@@ -499,10 +499,10 @@ New-Item -ItemType Directory -Path $appA -Force | Out-Null
|
|||||||
New-Item -ItemType Directory -Path $appB -Force | Out-Null
|
New-Item -ItemType Directory -Path $appB -Force | Out-Null
|
||||||
Set-Content -LiteralPath (Join-Path $appA 'a.txt') -Value 'dir-a' -Encoding UTF8
|
Set-Content -LiteralPath (Join-Path $appA 'a.txt') -Value 'dir-a' -Encoding UTF8
|
||||||
Set-Content -LiteralPath (Join-Path $appB 'b.txt') -Value 'dir-b' -Encoding UTF8
|
Set-Content -LiteralPath (Join-Path $appB 'b.txt') -Value 'dir-b' -Encoding UTF8
|
||||||
[System.IO.File]::WriteAllText($dirCatalog, "@{`n 'app-a' = @{ DefaultData = @{ Path = '$appA' } }`n 'app-b' = @{ DefaultData = @{ Path = '$appB' } }`n}`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($dirCatalog, "@{`n 'app-a' = @{ DefaultData = @{ Path = '$appA' } }`n 'app-b' = @{ DefaultData = @{ Path = '$appB' } }`n}`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
New-E2EConfig -Path $dirConfig -LogDir $dirLogDir -SoftwareCatalog $dirCatalog
|
New-E2EConfig -Path $dirConfig -LogDir $dirLogDir -SoftwareCatalog $dirCatalog
|
||||||
[System.IO.File]::WriteAllText($dirList1, "+ app-a`napp-b`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($dirList1, "+ app-a`napp-b`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
[System.IO.File]::WriteAllText($dirList2, "+ app-a`n- app-b`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($dirList2, "+ app-a`n- app-b`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
|
|
||||||
& $backupScript -BackupListPath $dirList1 -BackupDir $dirBackupDir -ConfigPath $dirConfig -Force -QuietTool
|
& $backupScript -BackupListPath $dirList1 -BackupDir $dirBackupDir -ConfigPath $dirConfig -Force -QuietTool
|
||||||
Test-Case '行首 + = 仅备份:仍然会被打包' {
|
Test-Case '行首 + = 仅备份:仍然会被打包' {
|
||||||
@@ -539,7 +539,7 @@ Test-Case '恢复端跳过行首 + 的条目、照常恢复 - 的条目' {
|
|||||||
Assert-Equal 0 $LASTEXITCODE
|
Assert-Equal 0 $LASTEXITCODE
|
||||||
Assert-FileMissing $appA '行首 + 的条目不该被恢复'
|
Assert-FileMissing $appA '行首 + 的条目不该被恢复'
|
||||||
Assert-FileExists (Join-Path $appB 'b.txt')
|
Assert-FileExists (Join-Path $appB 'b.txt')
|
||||||
Assert-Equal 'dir-b' (Get-Content -LiteralPath (Join-Path $appB 'b.txt') -Raw).Trim()
|
Assert-Equal 'dir-b' (Get-Content -Encoding UTF8 -LiteralPath (Join-Path $appB 'b.txt') -Raw).Trim()
|
||||||
|
|
||||||
$restoreLog = Get-NewestLog -LogDir $dirLogDir -Prefix 'restore'
|
$restoreLog = Get-NewestLog -LogDir $dirLogDir -Prefix 'restore'
|
||||||
$restoreContent = Get-Content -LiteralPath $restoreLog.FullName -Raw -Encoding UTF8
|
$restoreContent = Get-Content -LiteralPath $restoreLog.FullName -Raw -Encoding UTF8
|
||||||
@@ -572,8 +572,8 @@ if ($sevenZip) {
|
|||||||
-WorkingDirectory $legacyScratch
|
-WorkingDirectory $legacyScratch
|
||||||
}
|
}
|
||||||
|
|
||||||
[System.IO.File]::WriteAllText($legacyCatalog, "@{`n 'legacy-file' = @{ LegacyData = @{ Path = '$legacyLive' } }`n}`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($legacyCatalog, "@{`n 'legacy-file' = @{ LegacyData = @{ Path = '$legacyLive' } }`n}`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
[System.IO.File]::WriteAllText($legacyList, "legacy-file`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($legacyList, "legacy-file`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
New-E2EConfig -Path $legacyConfig -LogDir $legacyLogDir -SoftwareCatalog $legacyCatalog
|
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')
|
||||||
@@ -595,7 +595,7 @@ if ($sevenZip) {
|
|||||||
|
|
||||||
Test-Case '旧布局归档:按 <末级名> 回退,把文件还原回原位' {
|
Test-Case '旧布局归档:按 <末级名> 回退,把文件还原回原位' {
|
||||||
Assert-Equal 0 $legacyExitCode
|
Assert-Equal 0 $legacyExitCode
|
||||||
Assert-Equal '{"version":"old-layout"}' (Get-Content -LiteralPath $legacyLive -Raw).Trim()
|
Assert-Equal '{"version":"old-layout"}' (Get-Content -Encoding UTF8 -LiteralPath $legacyLive -Raw).Trim()
|
||||||
$legacyLog = Get-NewestLog -LogDir $legacyLogDir -Prefix 'restore'
|
$legacyLog = Get-NewestLog -LogDir $legacyLogDir -Prefix 'restore'
|
||||||
$legacyContent = Get-Content -LiteralPath $legacyLog.FullName -Raw -Encoding UTF8
|
$legacyContent = Get-Content -LiteralPath $legacyLog.FullName -Raw -Encoding UTF8
|
||||||
Assert-True ($legacyContent -like '*按旧布局回退*') '回退时必须给出明确告警'
|
Assert-True ($legacyContent -like '*按旧布局回退*') '回退时必须给出明确告警'
|
||||||
@@ -633,7 +633,7 @@ Test-Case 'Backup -DryRun:退出码 0、不写归档也不写 manifest' {
|
|||||||
|
|
||||||
Test-Case '归档名重复时直接报失败,不静默互相覆盖' {
|
Test-Case '归档名重复时直接报失败,不静默互相覆盖' {
|
||||||
$dupList = Join-Path $catRoot 'dup.txt'
|
$dupList = Join-Path $catRoot 'dup.txt'
|
||||||
[System.IO.File]::WriteAllText($dupList, "my-app`nmy-app`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($dupList, "my-app`nmy-app`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
& $backupScript -BackupListPath $dupList -BackupDir $catBackupDir -ConfigPath $catConfig -Force -QuietTool
|
& $backupScript -BackupListPath $dupList -BackupDir $catBackupDir -ConfigPath $catConfig -Force -QuietTool
|
||||||
Assert-Equal 1 $LASTEXITCODE '重复条目应让退出码为 1'
|
Assert-Equal 1 $LASTEXITCODE '重复条目应让退出码为 1'
|
||||||
}
|
}
|
||||||
@@ -641,14 +641,14 @@ Test-Case '归档名重复时直接报失败,不静默互相覆盖' {
|
|||||||
Test-Case '字面路径不受名录影响,仍走路径命名' {
|
Test-Case '字面路径不受名录影响,仍走路径命名' {
|
||||||
$literalList = Join-Path $catRoot 'list-literal.txt'
|
$literalList = Join-Path $catRoot 'list-literal.txt'
|
||||||
$literalDir = Join-Path $catRoot 'Backups-literal'
|
$literalDir = Join-Path $catRoot 'Backups-literal'
|
||||||
[System.IO.File]::WriteAllText($literalList, "$dirA2`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($literalList, "$dirA2`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
& $backupScript -BackupListPath $literalList -BackupDir $literalDir -ConfigPath $catConfig -Force -QuietTool
|
& $backupScript -BackupListPath $literalList -BackupDir $literalDir -ConfigPath $catConfig -Force -QuietTool
|
||||||
Assert-Equal 0 $LASTEXITCODE
|
Assert-Equal 0 $LASTEXITCODE
|
||||||
Assert-FileExists (Join-Path $literalDir ((Get-BackupBaseName -RawPath $dirA2) + '.7z'))
|
Assert-FileExists (Join-Path $literalDir ((Get-BackupBaseName -RawPath $dirA2) + '.7z'))
|
||||||
}
|
}
|
||||||
|
|
||||||
$missingList = Join-Path $WorkRoot 'missing.txt'
|
$missingList = Join-Path $WorkRoot 'missing.txt'
|
||||||
[System.IO.File]::WriteAllText($missingList, "Z:\definitely-not-here-12345`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($missingList, "Z:\definitely-not-here-12345`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
& $backupScript -BackupListPath $missingList -BackupDir $backupDir -ConfigPath $cfg1 -Force -QuietTool
|
& $backupScript -BackupListPath $missingList -BackupDir $backupDir -ConfigPath $cfg1 -Force -QuietTool
|
||||||
$missingExitCode = $LASTEXITCODE
|
$missingExitCode = $LASTEXITCODE
|
||||||
|
|
||||||
|
|||||||
+30
-30
@@ -385,8 +385,8 @@ Test-Case '归档项的属性集与契约一致(没有旧的 Sources / Dirs /
|
|||||||
Test-Case 'New-BaknretArchiveStaging:目录走 junction、文件走硬链接,按归档内名字挂载' {
|
Test-Case 'New-BaknretArchiveStaging:目录走 junction、文件走硬链接,按归档内名字挂载' {
|
||||||
$root = Join-Path $itemSandbox 'stage-src'
|
$root = Join-Path $itemSandbox 'stage-src'
|
||||||
New-Item -ItemType Directory -Path (Join-Path $root 'App') -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $root 'App') -Force | Out-Null
|
||||||
Set-Content -LiteralPath (Join-Path $root 'App\f.txt') -Value 'x'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $root 'App\f.txt') -Value 'x'
|
||||||
Set-Content -LiteralPath (Join-Path $root 'settings.json') -Value '{}'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $root 'settings.json') -Value '{}'
|
||||||
|
|
||||||
$items = @(
|
$items = @(
|
||||||
(New-BaknretArchiveItem -ArchivePath 'AlphaData' -RealPath (Join-Path $root 'App') -Exists $true),
|
(New-BaknretArchiveItem -ArchivePath 'AlphaData' -RealPath (Join-Path $root 'App') -Exists $true),
|
||||||
@@ -412,7 +412,7 @@ Test-Case 'New-BaknretJunction / Remove-BaknretJunction:只删连接点,不
|
|||||||
$target = Join-Path $itemSandbox 'j-target'
|
$target = Join-Path $itemSandbox 'j-target'
|
||||||
$link = Join-Path $itemSandbox 'j-link'
|
$link = Join-Path $itemSandbox 'j-link'
|
||||||
New-Item -ItemType Directory -Path $target -Force | Out-Null
|
New-Item -ItemType Directory -Path $target -Force | Out-Null
|
||||||
Set-Content -LiteralPath (Join-Path $target 'keep.txt') -Value 'keep'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $target 'keep.txt') -Value 'keep'
|
||||||
|
|
||||||
New-BaknretJunction -Path $link -Target $target | Out-Null
|
New-BaknretJunction -Path $link -Target $target | Out-Null
|
||||||
Assert-Equal 'Junction' (Get-Item -LiteralPath $link -Force).LinkType
|
Assert-Equal 'Junction' (Get-Item -LiteralPath $link -Force).LinkType
|
||||||
@@ -630,7 +630,7 @@ Test-Case '配置缺失时返回默认值' {
|
|||||||
|
|
||||||
Test-Case '配置嵌套段落合并且不丢默认键' {
|
Test-Case '配置嵌套段落合并且不丢默认键' {
|
||||||
$path = Join-Path $sandbox 'cfg.psd1'
|
$path = Join-Path $sandbox 'cfg.psd1'
|
||||||
Set-Content -LiteralPath $path -Value "@{ Encryption = @{ Enabled = `$true }; CompressionLevel = 5 }"
|
Set-Content -Encoding UTF8 -LiteralPath $path -Value "@{ Encryption = @{ Enabled = `$true }; CompressionLevel = 5 }"
|
||||||
$config = Get-BaknretConfig -Path $path
|
$config = Get-BaknretConfig -Path $path
|
||||||
Assert-Equal 5 $config.CompressionLevel
|
Assert-Equal 5 $config.CompressionLevel
|
||||||
Assert-True $config.Encryption.Enabled
|
Assert-True $config.Encryption.Enabled
|
||||||
@@ -663,7 +663,7 @@ $configDir = Join-Path $catalogSandbox 'Config'
|
|||||||
Test-Case '名录解析:裸键、引号键、带 - 与 . 的名字' {
|
Test-Case '名录解析:裸键、引号键、带 - 与 . 的名字' {
|
||||||
$catPath = Join-Path $catalogSandbox 'SoftwareCatalog.psd1'
|
$catPath = Join-Path $catalogSandbox 'SoftwareCatalog.psd1'
|
||||||
$content = "@{`n FooClolor = @{ DefaultData = @{ Path = '$appDir' } }`n 'scoop-config' = @{ DefaultConfig = @{ Path = '$configDir' } }`n '.ssh' = @{ DefaultData = @{ Path = '$appDir' } }`n}`n"
|
$content = "@{`n FooClolor = @{ DefaultData = @{ Path = '$appDir' } }`n 'scoop-config' = @{ DefaultConfig = @{ Path = '$configDir' } }`n '.ssh' = @{ DefaultData = @{ Path = '$appDir' } }`n}`n"
|
||||||
[System.IO.File]::WriteAllText($catPath, $content, [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($catPath, $content, [System.Text.UTF8Encoding]::new($true))
|
||||||
|
|
||||||
$catalog = Get-SoftwareCatalog -Path $catPath -NoCache
|
$catalog = Get-SoftwareCatalog -Path $catPath -NoCache
|
||||||
Assert-Equal 3 $catalog.Count
|
Assert-Equal 3 $catalog.Count
|
||||||
@@ -675,7 +675,7 @@ Test-Case '名录解析:裸键、引号键、带 - 与 . 的名字' {
|
|||||||
|
|
||||||
Test-Case '名录:Slot 按名字排序(哈希表顺序不可依赖)' {
|
Test-Case '名录:Slot 按名字排序(哈希表顺序不可依赖)' {
|
||||||
$catPath = Join-Path $catalogSandbox 'sorted.psd1'
|
$catPath = Join-Path $catalogSandbox 'sorted.psd1'
|
||||||
[System.IO.File]::WriteAllText($catPath, "@{`n FooClolor = @{ Zeta = @{ Path = '$appDir' }; Alpha = @{ Path = '$configDir' } }`n}`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($catPath, "@{`n FooClolor = @{ Zeta = @{ Path = '$appDir' }; Alpha = @{ Path = '$configDir' } }`n}`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
|
|
||||||
$catalog = Get-SoftwareCatalog -Path $catPath -NoCache
|
$catalog = Get-SoftwareCatalog -Path $catPath -NoCache
|
||||||
Assert-Equal 'Multi' $catalog['FooClolor'].Kind
|
Assert-Equal 'Multi' $catalog['FooClolor'].Kind
|
||||||
@@ -687,8 +687,8 @@ Test-Case '名录:Slot 按名字排序(哈希表顺序不可依赖)' {
|
|||||||
Test-Case '名录:Slot 对象字段与契约一致' {
|
Test-Case '名录:Slot 对象字段与契约一致' {
|
||||||
$catPath = Join-Path $catalogSandbox 'fields.psd1'
|
$catPath = Join-Path $catalogSandbox 'fields.psd1'
|
||||||
$filePath = Join-Path $catalogSandbox 'App\settings.json'
|
$filePath = Join-Path $catalogSandbox 'App\settings.json'
|
||||||
Set-Content -LiteralPath $filePath -Value '{}'
|
Set-Content -Encoding UTF8 -LiteralPath $filePath -Value '{}'
|
||||||
[System.IO.File]::WriteAllText($catPath, "@{`n Rich = @{`n Beta = @{ Path = '$filePath'; Encrypt = `$true; Description = 'beta 说明' }`n Alpha = @{ Path = '$configDir'; Exclude = '!*Cache,sub\one'; Include = 'Modules:$appDir' }`n }`n}`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($catPath, "@{`n Rich = @{`n Beta = @{ Path = '$filePath'; Encrypt = `$true; Description = 'beta 说明' }`n Alpha = @{ Path = '$configDir'; Exclude = '!*Cache,sub\one'; Include = 'Modules:$appDir' }`n }`n}`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
|
|
||||||
$catalog = Get-SoftwareCatalog -Path $catPath -NoCache
|
$catalog = Get-SoftwareCatalog -Path $catPath -NoCache
|
||||||
$entry = $catalog['Rich']
|
$entry = $catalog['Rich']
|
||||||
@@ -721,7 +721,7 @@ Test-Case '名录解析:目录带版本后缀时按前缀补全(legendary_2.
|
|||||||
$root = Join-Path $catalogSandbox 'probe'
|
$root = Join-Path $catalogSandbox 'probe'
|
||||||
New-Item -ItemType Directory -Path (Join-Path $root 'legendary_2.0.4') -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $root 'legendary_2.0.4') -Force | Out-Null
|
||||||
$catPath = Join-Path $catalogSandbox 'suffix.psd1'
|
$catPath = Join-Path $catalogSandbox 'suffix.psd1'
|
||||||
[System.IO.File]::WriteAllText($catPath, "@{`n legendary = @{ DefaultConfig = @{ Path = '$root\legendary' } }`n}`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($catPath, "@{`n legendary = @{ DefaultConfig = @{ Path = '$root\legendary' } }`n}`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
|
|
||||||
$catalog = Get-SoftwareCatalog -Path $catPath -NoCache
|
$catalog = Get-SoftwareCatalog -Path $catPath -NoCache
|
||||||
Assert-Equal 'Single' $catalog['legendary'].Kind
|
Assert-Equal 'Single' $catalog['legendary'].Kind
|
||||||
@@ -733,7 +733,7 @@ Test-Case '名录解析:不会把 Legendary 误配成 LegendarySomething' {
|
|||||||
$root = Join-Path $catalogSandbox 'strict'
|
$root = Join-Path $catalogSandbox 'strict'
|
||||||
New-Item -ItemType Directory -Path (Join-Path $root 'LegendarySomething') -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $root 'LegendarySomething') -Force | Out-Null
|
||||||
$catPath = Join-Path $catalogSandbox 'strict.psd1'
|
$catPath = Join-Path $catalogSandbox 'strict.psd1'
|
||||||
[System.IO.File]::WriteAllText($catPath, "@{`n Legendary = @{ DefaultConfig = @{ Path = '$root\Legendary' } }`n}`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($catPath, "@{`n Legendary = @{ DefaultConfig = @{ Path = '$root\Legendary' } }`n}`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
|
|
||||||
$catalog = Get-SoftwareCatalog -Path $catPath -NoCache
|
$catalog = Get-SoftwareCatalog -Path $catPath -NoCache
|
||||||
Assert-Equal 'Unresolved' $catalog['Legendary'].Kind '必须以下一个字符是 _ 或 - 为界'
|
Assert-Equal 'Unresolved' $catalog['Legendary'].Kind '必须以下一个字符是 _ 或 - 为界'
|
||||||
@@ -759,7 +759,7 @@ Test-Case '名录:一个 Slot 补全出多个目录时明确报错(否则会
|
|||||||
New-Item -ItemType Directory -Path (Join-Path $root 'Legendary_1') -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $root 'Legendary_1') -Force | Out-Null
|
||||||
New-Item -ItemType Directory -Path (Join-Path $root 'Legendary_2') -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $root 'Legendary_2') -Force | Out-Null
|
||||||
$catPath = Join-Path $catalogSandbox 'multicand.psd1'
|
$catPath = Join-Path $catalogSandbox 'multicand.psd1'
|
||||||
[System.IO.File]::WriteAllText($catPath, "@{`n Legendary = @{ DefaultConfig = @{ Path = '$root\Legendary' } }`n}`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($catPath, "@{`n Legendary = @{ DefaultConfig = @{ Path = '$root\Legendary' } }`n}`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
|
|
||||||
$catalog = Get-SoftwareCatalog -Path $catPath -NoCache
|
$catalog = Get-SoftwareCatalog -Path $catPath -NoCache
|
||||||
$entry = $catalog['Legendary']
|
$entry = $catalog['Legendary']
|
||||||
@@ -769,7 +769,7 @@ Test-Case '名录:一个 Slot 补全出多个目录时明确报错(否则会
|
|||||||
|
|
||||||
Test-Case '名录:Slot 写法不对 / 缺少 Path 都记成 Error,而不是崩掉' {
|
Test-Case '名录:Slot 写法不对 / 缺少 Path 都记成 Error,而不是崩掉' {
|
||||||
$bad = Join-Path $catalogSandbox 'bad.psd1'
|
$bad = Join-Path $catalogSandbox 'bad.psd1'
|
||||||
[System.IO.File]::WriteAllText($bad, "@{`n A = @{ S = 'C:\x' }`n B = @{ S = @{ Description = 'x' } }`n}`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($bad, "@{`n A = @{ S = 'C:\x' }`n B = @{ S = @{ Description = 'x' } }`n}`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
$catalog = Get-SoftwareCatalog -Path $bad -NoCache
|
$catalog = Get-SoftwareCatalog -Path $bad -NoCache
|
||||||
Assert-Equal 'Invalid' $catalog['A'].Kind
|
Assert-Equal 'Invalid' $catalog['A'].Kind
|
||||||
Assert-True ($catalog['A'].Error -like '*Slot S*')
|
Assert-True ($catalog['A'].Error -like '*Slot S*')
|
||||||
@@ -779,12 +779,12 @@ Test-Case '名录:Slot 写法不对 / 缺少 Path 都记成 Error,而不是
|
|||||||
|
|
||||||
Test-Case '名录:裸字符串 / 数组等旧结构会被 ERROR 跳过(不再当目录用)' {
|
Test-Case '名录:裸字符串 / 数组等旧结构会被 ERROR 跳过(不再当目录用)' {
|
||||||
$legacy = Join-Path $catalogSandbox 'legacy.psd1'
|
$legacy = Join-Path $catalogSandbox 'legacy.psd1'
|
||||||
[System.IO.File]::WriteAllText($legacy, "@{`n A = 'C:\Programs\A'`n B = @('C:\1','C:\2')`n}`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($legacy, "@{`n A = 'C:\Programs\A'`n B = @('C:\1','C:\2')`n}`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
$catalog = Get-SoftwareCatalog -Path $legacy -NoCache
|
$catalog = Get-SoftwareCatalog -Path $legacy -NoCache
|
||||||
Assert-Equal 0 $catalog.Count '旧结构必须被跳过,不能猜成目录'
|
Assert-Equal 0 $catalog.Count '旧结构必须被跳过,不能猜成目录'
|
||||||
|
|
||||||
$dirs = Join-Path $catalogSandbox 'dirs.psd1'
|
$dirs = Join-Path $catalogSandbox 'dirs.psd1'
|
||||||
[System.IO.File]::WriteAllText($dirs, "@{`n C = @{ Dirs = @('C:\1','C:\2') }`n}`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($dirs, "@{`n C = @{ Dirs = @('C:\1','C:\2') }`n}`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
$catalog = Get-SoftwareCatalog -Path $dirs -NoCache
|
$catalog = Get-SoftwareCatalog -Path $dirs -NoCache
|
||||||
Assert-Equal 1 $catalog.Count
|
Assert-Equal 1 $catalog.Count
|
||||||
Assert-Equal 'Invalid' $catalog['C'].Kind
|
Assert-Equal 'Invalid' $catalog['C'].Kind
|
||||||
@@ -800,8 +800,8 @@ Test-Case '名录:%VAR% 与 $( ... ) 子表达式都会被展开' {
|
|||||||
Test-Case '名录:Includes 分文件维护会被合并' {
|
Test-Case '名录:Includes 分文件维护会被合并' {
|
||||||
$extraPath = Join-Path $catalogSandbox 'Extra.psd1'
|
$extraPath = Join-Path $catalogSandbox 'Extra.psd1'
|
||||||
$basePath = Join-Path $catalogSandbox 'Base.psd1'
|
$basePath = Join-Path $catalogSandbox 'Base.psd1'
|
||||||
[System.IO.File]::WriteAllText($extraPath, "@{`n 'extra-app' = @{ D = @{ Path = '$appDir' } }`n}`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($extraPath, "@{`n 'extra-app' = @{ D = @{ Path = '$appDir' } }`n}`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
[System.IO.File]::WriteAllText($basePath, "@{`n Includes = @('Extra.psd1')`n 'base-app' = @{ D = @{ Path = '$configDir' } }`n}`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($basePath, "@{`n Includes = @('Extra.psd1')`n 'base-app' = @{ D = @{ Path = '$configDir' } }`n}`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
|
|
||||||
$catalog = Get-SoftwareCatalog -Path $basePath -NoCache
|
$catalog = Get-SoftwareCatalog -Path $basePath -NoCache
|
||||||
Assert-True $catalog.ContainsKey('base-app')
|
Assert-True $catalog.ContainsKey('base-app')
|
||||||
@@ -810,7 +810,7 @@ Test-Case '名录:Includes 分文件维护会被合并' {
|
|||||||
|
|
||||||
Test-Case '名录:结果按文件指纹缓存,-NoCache 强制重读' {
|
Test-Case '名录:结果按文件指纹缓存,-NoCache 强制重读' {
|
||||||
$catPath = Join-Path $catalogSandbox 'cache.psd1'
|
$catPath = Join-Path $catalogSandbox 'cache.psd1'
|
||||||
[System.IO.File]::WriteAllText($catPath, "@{`n Cached = @{ D = @{ Path = '$appDir' } }`n}`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($catPath, "@{`n Cached = @{ D = @{ Path = '$appDir' } }`n}`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
|
|
||||||
$first = Get-SoftwareCatalog -Path $catPath
|
$first = Get-SoftwareCatalog -Path $catPath
|
||||||
$second = Get-SoftwareCatalog -Path $catPath
|
$second = Get-SoftwareCatalog -Path $catPath
|
||||||
@@ -819,7 +819,7 @@ Test-Case '名录:结果按文件指纹缓存,-NoCache 强制重读' {
|
|||||||
$fresh = Get-SoftwareCatalog -Path $catPath -NoCache
|
$fresh = Get-SoftwareCatalog -Path $catPath -NoCache
|
||||||
Assert-False ([object]::ReferenceEquals($first, $fresh)) '-NoCache 必须重新读'
|
Assert-False ([object]::ReferenceEquals($first, $fresh)) '-NoCache 必须重新读'
|
||||||
|
|
||||||
[System.IO.File]::WriteAllText($catPath, "@{`n Cached = @{ D = @{ Path = '$configDir' } }`n}`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($catPath, "@{`n Cached = @{ D = @{ Path = '$configDir' } }`n}`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
$changed = Get-SoftwareCatalog -Path $catPath
|
$changed = Get-SoftwareCatalog -Path $catPath
|
||||||
Assert-Equal $configDir $changed['Cached'].Slots[0].Resolved '文件变了缓存必须失效'
|
Assert-Equal $configDir $changed['Cached'].Slots[0].Resolved '文件变了缓存必须失效'
|
||||||
}
|
}
|
||||||
@@ -918,7 +918,7 @@ Test-Case '名录里没有该名字:BaseName 退回可读目录名,并给出
|
|||||||
|
|
||||||
Test-Case '名录里的路径不存在时仍给出归档项(恢复要靠它还原回原位)' {
|
Test-Case '名录里的路径不存在时仍给出归档项(恢复要靠它还原回原位)' {
|
||||||
$catPath = Join-Path $resolveSandbox 'gone.psd1'
|
$catPath = Join-Path $resolveSandbox 'gone.psd1'
|
||||||
[System.IO.File]::WriteAllText($catPath, "@{`n 'gone-app' = @{ DefaultData = @{ Path = 'C:\definitely\not\here' } }`n}`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($catPath, "@{`n 'gone-app' = @{ DefaultData = @{ Path = 'C:\definitely\not\here' } }`n}`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
$item = ConvertFrom-BackupListLine -Line 'gone-app'
|
$item = ConvertFrom-BackupListLine -Line 'gone-app'
|
||||||
$resolved = Resolve-BackupEntry -Entry $item -CatalogPath $catPath
|
$resolved = Resolve-BackupEntry -Entry $item -CatalogPath $catPath
|
||||||
Assert-Equal 1 $resolved.Items.Count '恢复端据 Items 还原'
|
Assert-Equal 1 $resolved.Items.Count '恢复端据 Items 还原'
|
||||||
@@ -943,7 +943,7 @@ Test-Case '条目级 :+ 覆盖名录里的 Include(不是叠加)' {
|
|||||||
$incDir = Join-Path $resolveSandbox 'Inc'
|
$incDir = Join-Path $resolveSandbox 'Inc'
|
||||||
New-Item -ItemType Directory -Path $incDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $incDir -Force | Out-Null
|
||||||
$catPath = Join-Path $resolveSandbox 'withinc.psd1'
|
$catPath = Join-Path $resolveSandbox 'withinc.psd1'
|
||||||
[System.IO.File]::WriteAllText($catPath, "@{`n IncApp = @{ DefaultData = @{ Path = '$dirA'; Include = 'CatalogInc:$incDir' } }`n}`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($catPath, "@{`n IncApp = @{ DefaultData = @{ Path = '$dirA'; Include = 'CatalogInc:$incDir' } }`n}`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
|
|
||||||
$plain = Resolve-BackupEntry -Entry (ConvertFrom-BackupListLine -Line 'IncApp') -CatalogPath $catPath
|
$plain = Resolve-BackupEntry -Entry (ConvertFrom-BackupListLine -Line 'IncApp') -CatalogPath $catPath
|
||||||
Assert-Equal 2 $plain.Items.Count
|
Assert-Equal 2 $plain.Items.Count
|
||||||
@@ -988,7 +988,7 @@ Test-Case '方向标记随条目一路传到 Resolve-BackupEntry' {
|
|||||||
|
|
||||||
Test-Case '条目级 :- 覆盖名录里的 Exclude(不是叠加)' {
|
Test-Case '条目级 :- 覆盖名录里的 Exclude(不是叠加)' {
|
||||||
$catPath = Join-Path $resolveSandbox 'withexc.psd1'
|
$catPath = Join-Path $resolveSandbox 'withexc.psd1'
|
||||||
[System.IO.File]::WriteAllText($catPath, "@{`n ExcApp = @{ DefaultData = @{ Path = '$dirA'; Exclude = '!*CatalogCache' } }`n}`n", [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($catPath, "@{`n ExcApp = @{ DefaultData = @{ Path = '$dirA'; Exclude = '!*CatalogCache' } }`n}`n", [System.Text.UTF8Encoding]::new($true))
|
||||||
|
|
||||||
$plain = Resolve-BackupEntry -Entry (ConvertFrom-BackupListLine -Line 'ExcApp') -CatalogPath $catPath
|
$plain = Resolve-BackupEntry -Entry (ConvertFrom-BackupListLine -Line 'ExcApp') -CatalogPath $catPath
|
||||||
Assert-False $plain.HasExcludeOverride
|
Assert-False $plain.HasExcludeOverride
|
||||||
@@ -1018,12 +1018,12 @@ if (-not $sevenZip) {
|
|||||||
foreach ($d in 'Default\Cache', 'Default\Code Cache', 'Default\Extensions', 'component_crx_cache', 'Default\IndexedDB') {
|
foreach ($d in 'Default\Cache', 'Default\Code Cache', 'Default\Extensions', 'component_crx_cache', 'Default\IndexedDB') {
|
||||||
New-Item -ItemType Directory -Path (Join-Path $source $d) -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $source $d) -Force | Out-Null
|
||||||
}
|
}
|
||||||
Set-Content -LiteralPath (Join-Path $source 'keep.txt') 'keep'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $source 'keep.txt') 'keep'
|
||||||
Set-Content -LiteralPath (Join-Path $source 'Default\Cache\c.bin') 'c'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $source 'Default\Cache\c.bin') 'c'
|
||||||
Set-Content -LiteralPath (Join-Path $source 'Default\Code Cache\cc.bin') 'cc'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $source 'Default\Code Cache\cc.bin') 'cc'
|
||||||
Set-Content -LiteralPath (Join-Path $source 'Default\Extensions\e.bin') 'e'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $source 'Default\Extensions\e.bin') 'e'
|
||||||
Set-Content -LiteralPath (Join-Path $source 'component_crx_cache\x.bin') 'x'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $source 'component_crx_cache\x.bin') 'x'
|
||||||
Set-Content -LiteralPath (Join-Path $source 'Default\IndexedDB\i.bin') 'i'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $source 'Default\IndexedDB\i.bin') 'i'
|
||||||
|
|
||||||
$patterns = @('!*Cache', 'component_crx_cache', 'Default\Code Cache', 'Default\Extensions', 'Default\IndexedDB')
|
$patterns = @('!*Cache', 'component_crx_cache', 'Default\Code Cache', 'Default\Extensions', 'Default\IndexedDB')
|
||||||
$archiveItem = New-BaknretArchiveItem -ArchivePath $itemName -RealPath $source -Kind 'path' -Exists $true
|
$archiveItem = New-BaknretArchiveItem -ArchivePath $itemName -RealPath $source -Kind 'path' -Exists $true
|
||||||
@@ -1054,7 +1054,7 @@ if (-not $sevenZip) {
|
|||||||
$source = Join-Path $root $itemName
|
$source = Join-Path $root $itemName
|
||||||
foreach ($d in 'Cache1', 'Cache2', 'Keep', 'sub\Cache3') {
|
foreach ($d in 'Cache1', 'Cache2', 'Keep', 'sub\Cache3') {
|
||||||
New-Item -ItemType Directory -Path (Join-Path $source $d) -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $source $d) -Force | Out-Null
|
||||||
Set-Content -LiteralPath (Join-Path $source "$d\x.bin") 'x'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $source "$d\x.bin") 'x'
|
||||||
}
|
}
|
||||||
|
|
||||||
$archiveItem = New-BaknretArchiveItem -ArchivePath $itemName -RealPath $source -Kind 'slot' -Exists $true
|
$archiveItem = New-BaknretArchiveItem -ArchivePath $itemName -RealPath $source -Kind 'slot' -Exists $true
|
||||||
@@ -1096,8 +1096,8 @@ if (-not $sevenZip) {
|
|||||||
$root = Join-Path $sandbox 'topnames'
|
$root = Join-Path $sandbox 'topnames'
|
||||||
New-Item -ItemType Directory -Path (Join-Path $root 'Alpha') -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $root 'Alpha') -Force | Out-Null
|
||||||
New-Item -ItemType Directory -Path (Join-Path $root 'Beta') -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $root 'Beta') -Force | Out-Null
|
||||||
Set-Content -LiteralPath (Join-Path $root 'Alpha\a.txt') 'a'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $root 'Alpha\a.txt') 'a'
|
||||||
Set-Content -LiteralPath (Join-Path $root 'Beta\b.txt') 'b'
|
Set-Content -Encoding UTF8 -LiteralPath (Join-Path $root 'Beta\b.txt') 'b'
|
||||||
$archive = Join-Path $sandbox 'topnames.7z'
|
$archive = Join-Path $sandbox 'topnames.7z'
|
||||||
$code = Invoke-ExternalCommand -FilePath $sevenZip -ArgumentList @('a', '-t7z', '-mx=1', '-bso0', '-bsp0', $archive, 'Alpha', 'Beta') -WorkingDirectory $root
|
$code = Invoke-ExternalCommand -FilePath $sevenZip -ArgumentList @('a', '-t7z', '-mx=1', '-bso0', '-bsp0', $archive, 'Alpha', 'Beta') -WorkingDirectory $root
|
||||||
Assert-Equal 0 $code
|
Assert-Equal 0 $code
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ $conflicts = @()
|
|||||||
$seenNew = @{}
|
$seenNew = @{}
|
||||||
$entries = @()
|
$entries = @()
|
||||||
|
|
||||||
foreach ($line in (Get-Content -LiteralPath $BackupListPath)) {
|
foreach ($line in (Get-Content -Encoding UTF8 -LiteralPath $BackupListPath)) {
|
||||||
$item = ConvertFrom-BackupListLine -Line $line
|
$item = ConvertFrom-BackupListLine -Line $line
|
||||||
if (-not $item) { continue }
|
if (-not $item) { continue }
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -267,7 +267,7 @@ switch ($Verb) {
|
|||||||
while ($sw.Elapsed.TotalMinutes -lt 30) {
|
while ($sw.Elapsed.TotalMinutes -lt 30) {
|
||||||
if (Test-LabGuestReady) {
|
if (Test-LabGuestReady) {
|
||||||
Write-LabLog ("VM 已就绪(等待 {0} 分钟)" -f [math]::Round($sw.Elapsed.TotalMinutes, 1)) 'STEP'
|
Write-LabLog ("VM 已就绪(等待 {0} 分钟)" -f [math]::Round($sw.Elapsed.TotalMinutes, 1)) 'STEP'
|
||||||
$facts = Invoke-LabCommand -ScriptBlock { Get-Content 'C:\BakNRet-Lab\state\provisioned.json' -Raw }
|
$facts = Invoke-LabCommand -ScriptBlock { Get-Content -Encoding UTF8 'C:\BakNRet-Lab\state\provisioned.json' -Raw }
|
||||||
Write-Host $facts
|
Write-Host $facts
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ function Wait-LabProvision {
|
|||||||
while ($sw.Elapsed.TotalMinutes -lt 30) {
|
while ($sw.Elapsed.TotalMinutes -lt 30) {
|
||||||
if (Test-LabGuestReady) {
|
if (Test-LabGuestReady) {
|
||||||
Write-LabLog "供给完成,耗时 $([math]::Round($sw.Elapsed.TotalMinutes,1)) 分钟" 'STEP'
|
Write-LabLog "供给完成,耗时 $([math]::Round($sw.Elapsed.TotalMinutes,1)) 分钟" 'STEP'
|
||||||
$facts = Invoke-LabCommand -ScriptBlock { Get-Content 'C:\BakNRet-Lab\state\provisioned.json' -Raw }
|
$facts = Invoke-LabCommand -ScriptBlock { Get-Content -Encoding UTF8 'C:\BakNRet-Lab\state\provisioned.json' -Raw }
|
||||||
Write-Host $facts
|
Write-Host $facts
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -340,7 +340,7 @@ $listPath = Join-Path $WorkRoot 'BackupList.txt'
|
|||||||
$entries = @()
|
$entries = @()
|
||||||
if ($vscodeReady) { $entries += $vscodeApp; $entries += $vscodePersist }
|
if ($vscodeReady) { $entries += $vscodeApp; $entries += $vscodePersist }
|
||||||
$entries += $bData
|
$entries += $bData
|
||||||
[System.IO.File]::WriteAllText($listPath, (($entries -join [Environment]::NewLine) + [Environment]::NewLine), [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($listPath, (($entries -join [Environment]::NewLine) + [Environment]::NewLine), [System.Text.UTF8Encoding]::new($true))
|
||||||
|
|
||||||
$configPath = Join-Path $WorkRoot 'BackupConfig.psd1'
|
$configPath = Join-Path $WorkRoot 'BackupConfig.psd1'
|
||||||
$configText = @"
|
$configText = @"
|
||||||
@@ -359,7 +359,7 @@ $configText = @"
|
|||||||
DefaultExcludes = @('!Thumbs.db', '!desktop.ini')
|
DefaultExcludes = @('!Thumbs.db', '!desktop.ini')
|
||||||
}
|
}
|
||||||
"@
|
"@
|
||||||
[System.IO.File]::WriteAllText($configPath, $configText, [System.Text.UTF8Encoding]::new($false))
|
[System.IO.File]::WriteAllText($configPath, $configText, [System.Text.UTF8Encoding]::new($true))
|
||||||
|
|
||||||
Write-Host ''
|
Write-Host ''
|
||||||
Write-Host '[备份] Backup.ps1' -ForegroundColor Yellow
|
Write-Host '[备份] Backup.ps1' -ForegroundColor Yellow
|
||||||
@@ -406,7 +406,7 @@ if ($vscodeReady) {
|
|||||||
|
|
||||||
$settingsOk = $false
|
$settingsOk = $false
|
||||||
if ($settingsPath -and (Test-Path -LiteralPath $settingsPath)) {
|
if ($settingsPath -and (Test-Path -LiteralPath $settingsPath)) {
|
||||||
$settingsOk = (Get-Content -LiteralPath $settingsPath -Raw) -match [regex]::Escape($probe)
|
$settingsOk = (Get-Content -Encoding UTF8 -LiteralPath $settingsPath -Raw) -match [regex]::Escape($probe)
|
||||||
}
|
}
|
||||||
Test-Scenario 'A: 改过的 settings.json 被原样恢复(读得到、内容对)' $settingsOk $settingsPath
|
Test-Scenario 'A: 改过的 settings.json 被原样恢复(读得到、内容对)' $settingsOk $settingsPath
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user