fix: preserve legacy text across trans helpers

This commit is contained in:
Codex
2026-07-10 19:41:44 +02:00
parent d07830dd17
commit 9f8e325ea5
8 changed files with 253 additions and 64 deletions
+36 -1
View File
@@ -860,7 +860,7 @@ function windowsApplyPatchFsScript(basePath: string | null, operation: WindowsAp
const arg1 = args[1] ?? "";
const arg2 = args[2] ?? "";
const arg3 = args[3] ?? "";
return [
const scriptParts = [
"$ErrorActionPreference = 'Stop';",
"$ProgressPreference = 'SilentlyContinue';",
"[Console]::InputEncoding = [System.Text.UTF8Encoding]::new();",
@@ -895,6 +895,41 @@ function windowsApplyPatchFsScript(basePath: string | null, operation: WindowsAp
" 'delete' { Remove-Item -LiteralPath $target -Force -ErrorAction SilentlyContinue; break }",
" default { Fail ('unsupported apply-patch fs op: ' + $operation) 2 }",
"}",
];
return scriptParts
.map((line) => line.startsWith(" 'apply-replacements-bulk-stdin' ") ? windowsBulkReplacementScript() : line)
.join(" ");
}
function windowsBulkReplacementScript(): string {
return [
" 'apply-replacements-bulk-stdin' {",
" $expectedCount = [Int32]$targetArg;",
" $records = @([Console]::In.ReadToEnd() -split \"`r?`n\" | Where-Object { -not [string]::IsNullOrWhiteSpace($_) });",
" if ($records.Count -ne $expectedCount) { Fail ('bulk replacement record count mismatch: expected=' + $expectedCount + ' actual=' + $records.Count) 23 };",
" $plans = New-Object System.Collections.Generic.List[object];",
" foreach ($record in $records) {",
" $fields = $record -split '\\s+'; if ($fields.Count -ne 7) { Fail 'bulk replacement malformed record' 23 };",
" $targetRelative = Decode-Utf8 $fields[0]; $resolved = Resolve-UnideskPath $targetRelative;",
" $originalBytes = [Int64]$fields[1]; $originalSha256 = $fields[2]; $finalBytes = [Int64]$fields[3]; $finalSha256 = $fields[4]; $encodingStyle = $fields[5]; $replacementsText = $fields[6];",
" if (-not (Test-Path -LiteralPath $resolved -PathType Leaf)) { Fail ('file not found: ' + $resolved) 1 };",
" $source = [System.IO.File]::ReadAllBytes($resolved); $actualOriginalBytes = [Int64]$source.Length; $actualOriginalSha256 = Get-Sha256Bytes $source;",
" if ($actualOriginalBytes -ne $originalBytes) { Fail ('bulk replacement original integrity mismatch for ' + $resolved) 23 };",
" if (-not [string]::Equals($actualOriginalSha256, $originalSha256, [StringComparison]::OrdinalIgnoreCase)) { Fail ('bulk replacement original integrity mismatch for ' + $resolved) 23 };",
" $textEncoding = if ($encodingStyle -eq 'legacy-single-byte') { [System.Text.Encoding]::GetEncoding(28591) } else { [System.Text.UTF8Encoding]::new($false, $true) };",
" try { $sourceText = $textEncoding.GetString($source) } catch { Fail ('bulk replacement source decode failed encoding=' + $encodingStyle + ' for ' + $resolved) 25 };",
" $lines = New-Object System.Collections.Generic.List[string]; foreach ($line in ($sourceText -split \"`n\", -1)) { $lines.Add($line) | Out-Null }; if ($lines.Count -gt 0 -and $lines[$lines.Count - 1] -eq '') { $lines.RemoveAt($lines.Count - 1) };",
" $replacements = New-Object System.Collections.Generic.List[object];",
" if (-not [string]::IsNullOrEmpty($replacementsText)) { foreach ($item in ($replacementsText -split ';')) { if ([string]::IsNullOrWhiteSpace($item)) { continue }; $parts = $item -split ',', 3; if ($parts.Count -ne 3) { Fail 'bulk replacement malformed replacement' 23 }; $newText = Decode-Utf8 $parts[2]; $newLines = New-Object System.Collections.Generic.List[string]; foreach ($line in ($newText -split \"`n\", -1)) { $newLines.Add($line) | Out-Null }; if ($newLines.Count -gt 0 -and $newLines[$newLines.Count - 1] -eq '') { $newLines.RemoveAt($newLines.Count - 1) }; $replacements.Add([pscustomobject]@{ start = [Int32]$parts[0]; oldLength = [Int32]$parts[1]; newLines = [string[]]$newLines }) | Out-Null } };",
" foreach ($replacement in @($replacements | Sort-Object -Property start -Descending)) { if ($replacement.start -lt 0 -or $replacement.oldLength -lt 0 -or ($replacement.start + $replacement.oldLength) -gt $lines.Count) { Fail ('bulk replacement out of bounds for ' + $resolved) 23 }; if ($replacement.oldLength -gt 0) { $lines.RemoveRange($replacement.start, $replacement.oldLength) }; if ($replacement.newLines.Count -gt 0) { $lines.InsertRange($replacement.start, [string[]]$replacement.newLines) } };",
" $outputText = if ($lines.Count -eq 0) { '' } else { ([string]::Join(\"`n\", [string[]]$lines) + \"`n\") };",
" try { $outputBytes = $textEncoding.GetBytes($outputText) } catch { Fail ('bulk replacement final encode failed encoding=' + $encodingStyle + ' for ' + $resolved) 25 };",
" if ($outputBytes.Length -ne $finalBytes -or (Get-Sha256Bytes $outputBytes) -ne $finalSha256) { Fail ('bulk replacement final integrity mismatch for ' + $resolved) 23 };",
" $tmp = [System.IO.Path]::Combine([System.IO.Path]::GetDirectoryName($resolved), ('.' + [System.IO.Path]::GetFileName($resolved) + '.unidesk-v2-bulk-' + [guid]::NewGuid().ToString('N') + '.tmp')); [System.IO.File]::WriteAllBytes($tmp, $outputBytes); $plans.Add([pscustomobject]@{ target = $resolved; tmp = $tmp; sha256 = $finalSha256 }) | Out-Null;",
" };",
" foreach ($plan in $plans) { Ensure-Parent $plan.target; Move-Item -LiteralPath $plan.tmp -Destination $plan.target -Force; if ((Get-Sha256 $plan.target) -ne $plan.sha256) { Fail ('bulk replacement final sha256 mismatch for ' + $plan.target) 25 } };",
" break",
" }",
].join(" ");
}