清单上最常改的就是方向,而它**能在文本层精确完成**:加/去一个行首标记即可,不需要把整行拆成字段再拼回去。后者要在 Overrides / Flags / 引号 / 转义之间做逆向,任何一处不精确都会把用户的清单改花 —— 外科式改写的底线是"只动我要动的那一处"(ADR-0013)。 **保留用户的写法风格**:仓库的真实清单里同时存在贴着写(+WindowsTerminal)与留空格(+ WindowsTerminal)两种,统一成一种意味着顺带改动了本不该碰的行。这就是"改一个字段却多出几十行 diff"的来源。断言里两种风格都钉住了。 注释行没有方向可改,直接抛错:静默返回原样会制造"改了但没变"。 判据 12 条,其中往返那条最强:**把一行设成它当前的方向,必须原样返回**(含带注释与修饰符的行)。 验收:test.ps1 9/9 全绿(5.1 与 7)。
48 lines
2.1 KiB
PowerShell
48 lines
2.1 KiB
PowerShell
function Set-BakNRetBackupListDirection {
|
||
<#
|
||
.SYNOPSIS
|
||
改一行的方向(both / backup / restore),其余部分逐字节保持。
|
||
|
||
.DESCRIPTION
|
||
为什么先只做"方向"这一种编辑:它是清单上最常改的东西,而且**能在文本层精确完成** ——
|
||
加/去一个行首标记就行。要改别的字段就得把整行拆成字段再拼回去,而"拼回去"要在
|
||
`Overrides` / `Flags` / 引号 / 转义之间做逆向,任何一处不精确都会把用户的清单改花。
|
||
外科式改写的底线是"只动我要动的那一处"(ADR-0013)。
|
||
|
||
**保留用户的写法风格**:仓库的真实清单里同时存在贴着写(`+WindowsTerminal`)与留空格
|
||
(`+ WindowsTerminal`)两种。原样保留风格比统一成一种更安全 —— 统一意味着顺带改动了
|
||
那些我本来不该碰的行,而那正是"改一个字段却多出几十行 diff"的来源。
|
||
|
||
注释行与空行**没有方向可改**,所以直接抛错:静默返回原样会制造"改了但没变"。
|
||
#>
|
||
param(
|
||
[Parameter(Mandatory = $true)][AllowEmptyString()][string]$Raw,
|
||
[Parameter(Mandatory = $true)][ValidateSet('both', 'backup', 'restore')][string]$Direction
|
||
)
|
||
|
||
$record = ConvertFrom-BackupListLine -Line $Raw
|
||
if (-not $record) { throw '这一行不是条目(注释或空行),没有方向可改。' }
|
||
|
||
# 拆出:行首缩进 + 原有标记的写法风格 + 标记之后的正文
|
||
$indent = ''
|
||
$rest = $Raw
|
||
if ($rest -match '^(\s+)(.+)$') {
|
||
$indent = $Matches[1]
|
||
$rest = $Matches[2]
|
||
}
|
||
|
||
$spaced = $false
|
||
$body = $rest
|
||
if ($body.Length -gt 0 -and ($body[0] -eq '+' -or $body[0] -eq '-')) {
|
||
$spaced = ($body.Length -gt 1 -and $body[1] -eq ' ')
|
||
$body = $body.Substring(1)
|
||
if ($spaced) { $body = $body.Substring(1) }
|
||
}
|
||
|
||
if ($Direction -eq 'both') { return $indent + $body }
|
||
|
||
$marker = if ($Direction -eq 'backup') { '+' } else { '-' }
|
||
if ($spaced) { return $indent + $marker + ' ' + $body }
|
||
return $indent + $marker + $body
|
||
}
|