<# .SYNOPSIS Lantul complet de dinaintea si din timpul unui commit: sync text VFP, curatenie, verificari de livrare, stare repo-uri, commit + push. .DESCRIPTION 1. git_sync.ps1 -ProjectRoot - reimprospateaza .vc2/.sc2 din arbore. Iesire nenula -> opreste tot (nu se comite cu text nesincronizat). Se sare cu -FaraSync. 2. curatenie.ps1 -ProjectRoot - sterge artefactele de lucru (neurmarite de git). 3. Verificari de livrare (avertismente, neblocante): changelog neatins, fisiere de runda ramase, binare VFP fara perechea text in modificari. 4. Stare repo proiect si repo COMUN (separat, partajat de toate aplicatiile ROA): git status --short + git diff --stat. 5. Commit + push. Proiectul implicit; COMUN doar cu -Comun explicit (altfel doar raportat). Niciodata push --force. Comite pe ramura curenta, nu creeaza alta. 6. -DryRun: ruleaza pasii 1-4 (curatenia in -DryRun) si se opreste inainte de commit. .PARAMETER ProjectRoot Radacina proiectului (implicit dedus, ca la curatenie.ps1 - doua nivele deasupra acestui script). .PARAMETER Mesaj Mesajul de commit. Obligatoriu la o rulare reala (fara -DryRun). .PARAMETER Comun Comite si impinge si repo-ul COMUN (implicit doar proiectul). .PARAMETER FaraSync Sare peste git_sync.ps1 (util cand nu s-a atins niciun binar VFP). .PARAMETER FaraPush Doar commit local, fara push. .PARAMETER DryRun Nu modifica nimic - arata ce s-ar comite si unde. .EXAMPLE powershell -File COMUN\utile\livrare.ps1 -DryRun .EXAMPLE powershell -File COMUN\utile\livrare.ps1 -Mesaj "achizitie import: rebindare ControlSource" .EXAMPLE powershell -File COMUN\utile\livrare.ps1 -Mesaj "conventie noua in COMUN" -Comun .EXAMPLE powershell -File COMUN\utile\livrare.ps1 -Mesaj "doar .prg, fara binare" -FaraSync -FaraPush #> param( [string]$ProjectRoot, [string]$Mesaj, [switch]$Comun, [switch]$FaraSync, [switch]$FaraPush, [switch]$DryRun ) $ErrorActionPreference = 'Stop' if (-not $ProjectRoot) { $ProjectRoot = Split-Path (Split-Path $PSScriptRoot -Parent) -Parent } $comunPath = Join-Path $ProjectRoot 'COMUN' $gitSync = 'D:\ROA\UTIL\foxbin2prg\git_sync.ps1' $curatenie = Join-Path $PSScriptRoot 'curatenie.ps1' if (-not $DryRun -and -not $Mesaj) { Write-Output 'livrare: -Mesaj este obligatoriu (sau ruleaza cu -DryRun)' exit 1 } Write-Output ('livrare: ProjectRoot=' + $ProjectRoot) # --- pas 1: git_sync --- if ($FaraSync) { Write-Output '[1] git_sync: sarit (-FaraSync)' } else { if (-not (Test-Path $gitSync)) { Write-Output ('[1] git_sync: NU s-a gasit ' + $gitSync) exit 2 } & powershell -ExecutionPolicy Bypass -File $gitSync -ProjectRoot $ProjectRoot if ($LASTEXITCODE -ne 0) { Write-Output ('[1] git_sync: ESUAT (cod ' + $LASTEXITCODE + ') - opresc tot, nu se comite') exit 2 } Write-Output '[1] git_sync: OK' } # --- pas 2: curatenie --- $curArgs = @('-ProjectRoot', $ProjectRoot) if ($DryRun) { $curArgs += '-DryRun' } Write-Output '[2] curatenie:' & powershell -ExecutionPolicy Bypass -File $curatenie @curArgs | ForEach-Object { Write-Output (' ' + $_) } if ($LASTEXITCODE -ne 0) { Write-Output ('[2] curatenie: cod neasteptat ' + $LASTEXITCODE + ' (continui)') } # --- fisiere modificate per repo (dupa curatenie) --- function Get-ChangedFiles($repoPath) { if (-not (Test-Path (Join-Path $repoPath '.git'))) { return @() } $rezultat = New-Object System.Collections.ArrayList foreach ($linie in (& git -C $repoPath status --porcelain --untracked-files=all)) { if (-not $linie) { continue } $cale = $linie.Substring(3) if ($cale -match ' -> ') { $cale = ($cale -split ' -> ')[1] } $cale = $cale.Trim('"') [void]$rezultat.Add($cale) } return $rezultat } $modifProiect = Get-ChangedFiles $ProjectRoot $modifComun = Get-ChangedFiles $comunPath # --- pas 3: verificari de livrare (avertismente, neblocante) --- $avertismente = New-Object System.Collections.ArrayList function Verifica-Livrare($modif, $repoPath, $eticheta) { $codExt = @('.prg', '.vc2', '.sc2', '.ps1') $areCod = $modif | Where-Object { $ext = [System.IO.Path]::GetExtension($_).ToLower(); $codExt -contains $ext } $areChangelog = $modif | Where-Object { $_ -match 'changelog.*\.txt$' } if ($areCod -and -not $areChangelog -and $eticheta -eq 'proiect') { [void]$script:avertismente.Add('changelog neatins (' + $eticheta + ') desi s-a modificat cod') } foreach ($f in $modif) { $ext = [System.IO.Path]::GetExtension($f).ToLower() if ($ext -eq '.vcx') { $pereche = [System.IO.Path]::ChangeExtension($f, '.vc2') } elseif ($ext -eq '.scx') { $pereche = [System.IO.Path]::ChangeExtension($f, '.sc2') } else { continue } if ($modif -notcontains $pereche) { [void]$script:avertismente.Add('binar fara text sincronizat in modificari (' + $eticheta + '): ' + $f) } } $docsPath = Join-Path $repoPath 'docs' if (Test-Path $docsPath) { $ramase = Get-ChildItem -Path $docsPath -Include @('propuneri_*.md', 'handoff*.md', 'runda*.md') -Recurse -ErrorAction SilentlyContinue foreach ($r in $ramase) { [void]$script:avertismente.Add('fisier de runda ramas (' + $eticheta + '): docs\' + $r.Name) } } } Verifica-Livrare $modifProiect $ProjectRoot 'proiect' Verifica-Livrare $modifComun $comunPath 'COMUN' Write-Output '[3] verificari de livrare:' if ($avertismente.Count -eq 0) { Write-Output ' fara avertismente' } else { foreach ($a in $avertismente) { Write-Output (' ATENTIE: ' + $a) } } # --- pas 4: stare repo-uri --- Write-Output '[4] stare repo proiect:' & git -C $ProjectRoot status --short | ForEach-Object { Write-Output (' ' + $_) } & git -C $ProjectRoot diff --stat HEAD | ForEach-Object { Write-Output (' ' + $_) } Write-Output '[4] stare repo COMUN:' if (Test-Path (Join-Path $comunPath '.git')) { & git -C $comunPath status --short | ForEach-Object { Write-Output (' ' + $_) } & git -C $comunPath diff --stat HEAD | ForEach-Object { Write-Output (' ' + $_) } } else { Write-Output ' (fara repo git in COMUN)' } if ($DryRun) { Write-Output '[5] commit/push: sarit (-DryRun)' if ($modifProiect.Count -gt 0) { Write-Output (' ar comite in proiect (' + $modifProiect.Count + ' fisiere)') } else { Write-Output ' proiect: nimic de comis' } if ($modifComun.Count -gt 0) { if ($Comun) { Write-Output (' ar comite in COMUN (' + $modifComun.Count + ' fisiere)') } else { Write-Output (' COMUN are ' + $modifComun.Count + ' fisiere necomise - nu se comite fara -Comun') } } else { Write-Output ' COMUN: nimic de comis' } exit 0 } # --- pas 5: commit + push --- $exitCode = 0 function Comite-Si-Impinge($repoPath, $eticheta, $faraPush) { # mesajele folosesc Write-Host (nu Write-Output): functia e apelata cu rezultatul # capturat intr-o variabila, iar Write-Output ar ajunge in valoarea returnata. if (-not (Test-Path (Join-Path $repoPath '.git'))) { Write-Host ('[5] ' + $eticheta + ': fara repo git, sarit') return 0 } & git -C $repoPath add -A & git -C $repoPath diff --cached --quiet if ($LASTEXITCODE -eq 0) { Write-Host ('[5] ' + $eticheta + ': nimic de comis') return 0 } $ramura = (& git -C $repoPath rev-parse --abbrev-ref HEAD) & git -C $repoPath commit -m $Mesaj | Out-Null if ($LASTEXITCODE -ne 0) { Write-Host ('[5] ' + $eticheta + ': COMMIT ESUAT pe ramura ' + $ramura) return 1 } Write-Host ('[5] ' + $eticheta + ': commit OK pe ramura ' + $ramura) if ($faraPush) { Write-Host ('[5] ' + $eticheta + ': push sarit (-FaraPush)') return 0 } & git -C $repoPath push if ($LASTEXITCODE -ne 0) { Write-Host ('[5] ' + $eticheta + ': PUSH ESUAT') return 1 } Write-Host ('[5] ' + $eticheta + ': push OK') return 0 } $exitCode += (Comite-Si-Impinge $ProjectRoot 'proiect' $FaraPush) if ($Comun) { $exitCode += (Comite-Si-Impinge $comunPath 'COMUN' $FaraPush) } elseif ($modifComun.Count -gt 0) { Write-Output ('[5] COMUN: ' + $modifComun.Count + ' fisiere necomise - nu se comite fara -Comun') } if ($exitCode -gt 0) { exit 3 } Write-Output 'livrare: OK' exit 0