Files
foxbin2prg/vfp_filemap.ps1
Marius Mutu a05687a38f Flux git-text in-arbore: git_sync.ps1 + teste, txt2vcx in-place, filemap pjx/dbf
- git_sync.ps1 nou: conversie recursiva bin->text in arbore (staging temp,
  incremental, orfani, RoundtripExempt, DbfList cu date, anti-dialog cfg)
- vfp_filemap.ps1: mapari .pjx->.pj2 si .dbf->.db2
- txt2vcx.ps1: CacheRoot implicit = ProjectRoot (text in-arbore) + cfg anti-dialog in staging
- test_roundtrip.ps1: parametrizat per proiect, restaurare din backup temp (nu git checkout)
- test_git_sync.ps1 nou: incremental, orfani, esec partial, protectie binar, scutire roundtrip
- CLAUDE.md: fluxul nou documentat

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 11:04:23 +03:00

82 lines
3.5 KiB
PowerShell

<#
.SYNOPSIS
Harta comuna bin<->memo<->text pentru conversiile VFP (FoxBin2Prg), dot-sourced de
vcx2txt.ps1 (Bin2Prg) si txt2vcx.ps1 (Prg2Bin), ca sa nu existe doua copii ale hartii.
.DESCRIPTION
Defineste $script:VfpFileMap: extensie-binar (lowercase, cu punct) -> @(extensie-memo, extensie-text).
Si o functie inversa Get-VfpBinExtensionForTextExtension pentru txt2vcx.ps1 (text -> binar).
#>
$script:VfpFileMap = @{
'.vcx' = @('.vct', '.vc2'); '.scx' = @('.sct', '.sc2'); '.frx' = @('.frt', '.fr2')
'.lbx' = @('.lbt', '.lb2'); '.mnx' = @('.mnt', '.mn2'); '.dbc' = @('.dct', '.dc2')
'.pjx' = @('.pjt', '.pj2'); '.dbf' = @('.fpt', '.db2')
}
function Get-VfpBinExtensionForTextExtension {
<#
.SYNOPSIS
Data o extensie text (.vc2, .sc2, ...), intoarce @(extensie-binar, extensie-memo), sau $null daca nu e cunoscuta.
#>
param([Parameter(Mandatory)][string]$TextExtension)
$t = $TextExtension.ToLower()
foreach ($binExt in $script:VfpFileMap.Keys) {
if ($script:VfpFileMap[$binExt][1] -eq $t) {
return @($binExt, $script:VfpFileMap[$binExt][0])
}
}
return $null
}
function Invoke-FoxBin2PrgSafe {
<#
.SYNOPSIS
Ruleaza FoxBin2Prg.EXE cu un watchdog de timp, ca sa nu ramana blocat la infinit.
.DESCRIPTION
FoxBin2Prg.EXE poate afisa un MessageBox MODAL nativ al motorului VFP (nu al
propriului sau error-handler) cand recompilarea textului esueaza (ex. text
stricat, ENDPROC lipsa) - vazut concret: "Error 1098, Procedure not closed...".
Parametrul cDontShowErrors='1' NU suprima acest dialog (acela controleaza doar
raportarea de erori proprie a FoxBin2Prg, nu eroarea nativa de compilare VFP).
Fara acest watchdog, un rulaj automat/CI ar ramane agatat la infinit asteptand
un om sa apese OK. Orice timeout se trateaza ca ESEC pentru fisierul respectiv.
.PARAMETER ExePath
Calea catre FoxBin2Prg.EXE.
.PARAMETER ExeArgs
Lista de argumente pozitionale, in ordinea folosita de FoxBin2Prg (inclusiv
string-urile goale intre ele, ca in apelul cu "&").
.PARAMETER TimeoutSeconds
Cat asteapta procesul sa termine normal inainte sa-l omoare (implicit 60s -
conversiile uzuale dureaza sub o secunda; un timeout mare inseamna aproape
sigur un dialog modal blocat).
.OUTPUTS
PSCustomObject cu TimedOut (bool) si ExitCode (int; -1 daca a fost omorat la timeout).
#>
param(
[Parameter(Mandatory)][string]$ExePath,
[Parameter(Mandatory)][AllowEmptyCollection()][AllowEmptyString()][string[]]$ExeArgs,
[int]$TimeoutSeconds = 60
)
$psi = New-Object System.Diagnostics.ProcessStartInfo
$psi.FileName = $ExePath
$psi.Arguments = ($ExeArgs | ForEach-Object { '"' + ($_ -replace '"', '\"') + '"' }) -join ' '
$psi.UseShellExecute = $false
$proc = [System.Diagnostics.Process]::Start($psi)
$finished = $proc.WaitForExit($TimeoutSeconds * 1000)
if (-not $finished) {
Write-Warning "Invoke-FoxBin2PrgSafe: TIMEOUT dupa $TimeoutSeconds s (probabil MessageBox modal blocat) - omor procesul (PID $($proc.Id)) si eventualele lui ferestre/copii."
try { & taskkill /PID $proc.Id /T /F 2>&1 | Out-Null } catch {}
try { if (-not $proc.HasExited) { $proc.Kill() } } catch {}
Start-Sleep -Milliseconds 300
return [PSCustomObject]@{ TimedOut = $true; ExitCode = -1 }
}
return [PSCustomObject]@{ TimedOut = $false; ExitCode = $proc.ExitCode }
}