Files
BakNRet/Edit-Config.ps1
Shuery effc38fdd3 feat(tui): 名录编辑器循环 + 挂进 Edit-Config(第三轮第二块·完成)
装配:Get-BakNRetCatalogField → 菜单选字段 → Read-BakNRetLine → Set-BakNRetCatalogField → Save-BakNRetConfigFile(校验通过才原子替换 + 时间戳备份)。

菜单里**只列可编辑的字段**(单行的 Encrypt / Description):把只读的 Path / Exclude 也列出来再拒绝,会让每个只读项浪费用户一次回车。

校验用模块自己的 Import-BaknretDataFile:这份名录有 $( ) 动态表达式与跨行拼接,普通数据文件读取器读不了 —— 而正是它保证"改完整份文件还能被程序读回来"(值能读回来才算改成功)。定位用 (软件名, Slot, 字段名) 三元组,因为同一软件可以有多个 Slot。

Edit-Config 的三个界面(清单 / 设置 / 名录)至此全部完成。

判据 9 条:改一个值后只动一行、注释行数不变、改完能读回新值、留下时间戳备份且备份里是原文;取消时不写盘也不产生备份。

验收:test.ps1 9/9 全绿(5.1 与 7);真实清单只读冒烟 4/4。
2026-09-27 21:30:14 +08:00

127 lines
5.7 KiB
PowerShell
Raw Permalink 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
配置管理入口:改清单 / 改设置 / 改名录。
.DESCRIPTION
三个界面共用一个底色(ADR-0013):**外科式改写**(只动被编辑的那一处,注释与其它行一字节不动)、
**校验通过才落盘**(先写临时文件、用模块自己的读取器验、过了才原子替换)、**保存前留时间戳备份**
(logs\config-backups\)。
目前只有**清单**界面做完了;设置(BackupConfig.psd1)与名录(SoftwareCatalog.psd1)分别是
第二轮与第三轮的工作 —— 现在选它们会明确说"还没做"并返回非零,而不是假装成功。
进不了交互界面时明确失败(退出码 2)而不是挂起:TUI 的异常不该改退出码,但"根本没法交互"
是个必须让调用方知道的状态。
.EXAMPLE
.\Edit-Config.ps1 -Target List
.EXAMPLE
.\Edit-Config.ps1 -Target List -ListPath .\BackupList.txt -InputScript @('Enter','Down','Enter')
#>
[CmdletBinding()]
param(
[ValidateSet('List', 'Settings', 'Catalog')][string]$Target,
[string]$ListPath,
[string[]]$InputScript
)
$ErrorActionPreference = 'Stop'
$savedVerbosePreference = $VerbosePreference
$VerbosePreference = 'SilentlyContinue'
Import-Module (Join-Path $PSScriptRoot 'BakNRet\BakNRet.psd1') -Force
$VerbosePreference = $savedVerbosePreference
if (-not $ListPath) { $ListPath = Join-Path $PSScriptRoot 'BackupList.txt' }
function Invoke-BakNRetListEditorEntry {
param([string]$Path, [string[]]$Script)
$driver = New-BakNRetInputDriver -Script $Script -NonInteractive:$([bool]$Script)
$result = Invoke-BakNRetBackupListEditor -Path $Path -Driver $driver
if ($result.Saved) {
Write-Host ("已保存:{0}" -f $Path) -ForegroundColor Green
Write-Host ("原文件备份:{0}" -f $result.BackupPath) -ForegroundColor DarkGray
return 0
}
if ($result.Error) {
Write-Host $result.Error -ForegroundColor Yellow
return 1
}
Write-Host '没有改动。' -ForegroundColor DarkGray
return 0
}
if ($Target -eq 'List') {
exit (Invoke-BakNRetListEditorEntry -Path $ListPath -Script $InputScript)
}
if ($Target -eq 'Settings') {
$configPath = Join-Path $PSScriptRoot 'BackupConfig.psd1'
$driver = New-BakNRetInputDriver -Script $InputScript -NonInteractive:$([bool]$InputScript)
$saved = Invoke-BakNRetConfigEditor -Path $configPath -Driver $driver
if ($saved.Saved) { Write-Host ("已保存:{0}" -f $configPath) -ForegroundColor Green; Write-Host ("原文件备份:{0}" -f $saved.BackupPath) -ForegroundColor DarkGray; exit 0 }
if ($saved.Error) { Write-Host $saved.Error -ForegroundColor Yellow; exit 1 }
Write-Host '没有改动。' -ForegroundColor DarkGray
exit 0
}
if ($Target -eq 'Catalog') {
$catalogPath = Join-Path $PSScriptRoot 'SoftwareCatalog.psd1'
$driver = New-BakNRetInputDriver -Script $InputScript -NonInteractive:$([bool]$InputScript)
$saved = Invoke-BakNRetCatalogEditor -Path $catalogPath -Driver $driver
if ($saved.Saved) { Write-Host ("已保存:{0}" -f $catalogPath) -ForegroundColor Green; Write-Host ("原文件备份:{0}" -f $saved.BackupPath) -ForegroundColor DarkGray; exit 0 }
if ($saved.Error) { Write-Host $saved.Error -ForegroundColor Yellow; exit 1 }
Write-Host '没有改动。' -ForegroundColor DarkGray
exit 0
}
if ($Target) {
Write-Host ("{0} 的编辑器还没做:清单 / 设置 / 名录三个界面都已完成。" -f $Target) -ForegroundColor Yellow
exit 1
}
# 不带 -Target:进配置菜单
if ([Console]::IsOutputRedirected -and -not $InputScript) {
Write-Host '没有可用的控制台,也没有给出 -InputScript:无法进入交互界面。' -ForegroundColor Red
Write-Host '要非交互执行,请指定目标,例如:-Target List' -ForegroundColor Red
exit 2
}
$driver = New-BakNRetInputDriver -Script $InputScript -NonInteractive:$([bool]$InputScript)
$items = @(
[pscustomobject]@{ Key = 'List'; Text = '清单 BackupList.txt —— 改方向,改完校验' }
[pscustomobject]@{ Key = 'Settings'; Text = '设置 BackupConfig.psd1 —— 还没做(第二轮)' }
[pscustomobject]@{ Key = 'Catalog'; Text = '名录 SoftwareCatalog.psd1 —— 还没做(第三轮)' }
)
$picked = Invoke-BakNRetMenu -Title '配置' -Items $items -Driver $driver -MultiSelect $false -Hint '↑↓ 选择 回车 进入 Esc 返回'
if ($picked.Action -ne 'confirm') { exit 0 }
if ($picked.Chosen.Key -eq 'List') {
exit (Invoke-BakNRetListEditorEntry -Path $ListPath -Script $InputScript)
}
if ($picked.Chosen.Key -eq 'Settings') {
$configPath = Join-Path $PSScriptRoot 'BackupConfig.psd1'
$driver2 = New-BakNRetInputDriver -Script $InputScript -NonInteractive:$([bool]$InputScript)
$saved2 = Invoke-BakNRetConfigEditor -Path $configPath -Driver $driver2
if ($saved2.Saved) { Write-Host ("已保存:{0}" -f $configPath) -ForegroundColor Green; exit 0 }
if ($saved2.Error) { Write-Host $saved2.Error -ForegroundColor Yellow; exit 1 }
Write-Host '没有改动。' -ForegroundColor DarkGray
exit 0
}
if ($picked.Chosen.Key -eq 'Catalog') {
$catalogPath = Join-Path $PSScriptRoot 'SoftwareCatalog.psd1'
$driver3 = New-BakNRetInputDriver -Script $InputScript -NonInteractive:$([bool]$InputScript)
$saved3 = Invoke-BakNRetCatalogEditor -Path $catalogPath -Driver $driver3
if ($saved3.Saved) { Write-Host ("已保存:{0}" -f $catalogPath) -ForegroundColor Green; exit 0 }
if ($saved3.Error) { Write-Host $saved3.Error -ForegroundColor Yellow; exit 1 }
Write-Host '没有改动。' -ForegroundColor DarkGray
exit 0
}
Write-Host ("未知的目标:{0}" -f $picked.Chosen.Key) -ForegroundColor Yellow
exit 1