Muta roa_sync.ps1 (+ testul) in COMUN\scripts - aici ramane doar stub

Scriptul de sesiune se distribuie de-acum prin svn update (COMUN e prezent in
toate proiectele ROA), nu prin pull manual pe clona foxbin2prg. Stub-ul
deleaga la <ProjectRoot>\COMUN\scripts\roa_sync.ps1 (cu svn update prealabil
daca fisierul lipseste inca), pentru lansatoarele roa_sync.bat neactualizate.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AvccPZXr4A9ihcTtExNoJT
This commit is contained in:
2026-07-27 11:58:55 +03:00
parent 51cab198c4
commit 234f6a5e7f
2 changed files with 16 additions and 542 deletions

View File

@@ -1,45 +1,12 @@
<#
.SYNOPSIS
Sincronizare de inceput de sesiune pentru un proiect ROA (flux SVN + git text FoxBin2Prg).
STUB de compatibilitate: roa_sync.ps1 s-a MUTAT in COMUN\scripts\roa_sync.ps1
(se distribuie automat prin svn update, ca restul COMUN).
.DESCRIPTION
Pasii:
1. svn update pe ProjectRoot (include externalul COMUN\). Esec / conflicte -> stop, exit nenul.
2. git_sync.ps1 -ProjectRoot <ProjectRoot> (improspateaza textele .??2, inclusiv COMUN).
Esec (exit nenul) -> avertizare, fara commit-uri de sync, exit nenul.
3. Repo proiect (ProjectRoot\.git): pe main comite "sync SVN r<REV>" daca sunt schimbari,
apoi reconciliaza cu origin si face push conditionat (vezi mai jos).
4. La fel repo COMUN (ProjectRoot\COMUN\.git), cu revizia din svn info pe folderul COMUN.
5. Inchide branch-urile claude/* terminate (git diff main..branch gol) in ambele repo-uri.
6. Sumar final (commit / reconciliere / push per repo + avertismente).
Reconcilierea cu origin (pasii 3-4, DUPA commit-ul local de sync - commit-ul intai face
tree-ul curat si aduce sub urmarire fisierele noi, deci nu mai apar blocajele clasice de
pull peste modificari necomise / fisiere netracked):
- git fetch origin; fara remote origin sau fetch esuat (offline) -> avertisment si
comportamentul vechi (doar commit local), exit 0.
- doar in urma fata de origin/main -> git merge --ff-only origin/main.
- divergenta -> git rebase origin/main. Commit-urile de sync al caror continut e deja
identic pe origin (alta masina a rulat acelasi svn update + sync + push inaintea
noastra) devin goale la rebase si sunt aruncate automat - NU e conflict si nu cere
interventie manuala.
- conflict REAL la rebase -> git rebase --abort, avertisment, exit nenul la final.
- push origin main DOAR daca toate commit-urile ahead de origin/main sunt commit-uri de
sync ("sync SVN[ r<rev>]" - continut oglindit din SVN, sursa de adevar). Orice commit
non-sync nepushed blocheaza push-ul automat (avertisment; push manual dupa review).
- push respins (push simultan de pe alta masina) -> reia fetch + reconciliere + push,
maxim 3 incercari, apoi avertisment (se reconciliaza la urmatoarea rulare).
Exit: nenul la esec svn/git_sync sau conflict real cu origin; avertismentele (offline,
push sarit din cauza commit-urilor non-sync, push esuat) lasa exit 0 si apar in sumar.
.PARAMETER ProjectRoot
Radacina proiectului. Implicit: directorul curent, daca are .git si un .pjx.
.PARAMETER GitOnly
Sare peste pasii SVN (1) si regenerarea textelor (2): doar commit + reconciliere + push +
inchidere branch-uri. Pentru reconciliere rapida cu origin sau pentru teste
(test_roa_sync.ps1) - nu cere working copy SVN si nici FoxBin2Prg.
Deleaga la copia proiectului: <ProjectRoot>\COMUN\scripts\roa_sync.ps1. Daca lipseste
(working copy neactualizat inca), face intai svn update pe proiect ca sa o aduca.
Actualizeaza lansatoarele (roa_sync.bat) sa cheme direct COMUN\scripts\roa_sync.ps1.
#>
[CmdletBinding()]
param(
@@ -49,7 +16,6 @@ param(
$ErrorActionPreference = 'Stop'
# --- deduce ProjectRoot din directorul curent daca nu e dat ---
if (-not $ProjectRoot) {
$cwd = (Get-Location).Path
$hasGit = Test-Path -LiteralPath (Join-Path $cwd '.git')
@@ -61,272 +27,19 @@ if (-not $ProjectRoot) {
exit 1
}
}
if (-not (Test-Path -LiteralPath $ProjectRoot -PathType Container)) {
Write-Host "EROARE: ProjectRoot nu exista: $ProjectRoot"
exit 1
}
$ProjectRoot = (Get-Item -LiteralPath $ProjectRoot).FullName
$comunRoot = Join-Path $ProjectRoot 'COMUN'
$gitSync = Join-Path $PSScriptRoot 'git_sync.ps1'
Write-Host "=== roa_sync: ProjectRoot=$ProjectRoot$(if($GitOnly){' (-GitOnly)'}) ==="
# --- helper: revizia SVN a unui folder ---
function Get-SvnRev([string]$path) {
# EAP local Continue: sub Stop, redirectarea 2>$null a stderr-ului nativ arunca in PS 5.1
$ErrorActionPreference = 'Continue'
$rev = (& svn info --show-item revision $path 2>$null | Out-String).Trim()
if ($LASTEXITCODE -ne 0 -or -not $rev) { return '' }
return $rev
}
# =========================== 1. svn update ===========================
$rev = ''
Write-Host ''
if ($GitOnly) {
Write-Host "--- 1. svn update: sarit (-GitOnly) ---"
} else {
Write-Host "--- 1. svn update ---"
$svnOut = & svn update $ProjectRoot
$svnExit = $LASTEXITCODE
$svnOut | ForEach-Object { Write-Host " $_" }
if ($svnExit -ne 0) {
Write-Host "EROARE: svn update a esuat (exit $svnExit). Ma opresc."
exit 1
}
# svn poate iesi 0 dar raporta conflicte in sumar
if ($svnOut | Where-Object { $_ -match 'Summary of conflicts|conflict' }) {
Write-Host "EROARE: svn update raporteaza conflicte. Rezolva-le manual, apoi reia. Ma opresc."
exit 1
}
$rev = Get-SvnRev $ProjectRoot
Write-Host " Revizie SVN ProjectRoot: $(if($rev){$rev}else{'necunoscuta'})"
}
# =========================== 2. git_sync ===========================
Write-Host ''
if ($GitOnly) {
Write-Host "--- 2. git_sync: sarit (-GitOnly) ---"
} else {
Write-Host "--- 2. git_sync (texte .??2) ---"
if (-not (Test-Path -LiteralPath $gitSync)) {
Write-Host "EROARE: nu gasesc git_sync.ps1 la $gitSync. Ma opresc."
exit 1
}
& powershell -ExecutionPolicy Bypass -NoProfile -File $gitSync -ProjectRoot $ProjectRoot
$syncExit = $LASTEXITCODE
if ($syncExit -ne 0) {
Write-Host ''
Write-Host "AVERTISMENT: git_sync a raportat esecuri (exit $syncExit). NU fac commit-uri de sync. Ma opresc."
$target = Join-Path $ProjectRoot 'COMUN\scripts\roa_sync.ps1'
if (-not (Test-Path -LiteralPath $target)) {
Write-Host "roa_sync.ps1 s-a mutat in COMUN\scripts si lipseste inca din working copy - rulez svn update ca sa il aduc."
& svn update $ProjectRoot
if (-not (Test-Path -LiteralPath $target)) {
Write-Host "EROARE: $target lipseste si dupa svn update. Verifica externalul COMUN."
exit 1
}
}
# =========================== 3-4. commit sync + reconciliere origin per repo ===========================
# Pe main comite schimbarile ca "sync SVN r<rev>", apoi fetch + ff/rebase fata de origin/main
# (sync-urile cu continut deja identic pe origin devin goale la rebase si dispar) si push
# DOAR daca tot ahead-ul e din commit-uri de sync. Intoarce starea pasilor.
function Sync-Repo {
param([string]$RepoDir, [string]$Rev, [string]$Label)
# EAP local Continue: git scrie normal pe stderr (fetch/push/rebase), iar sub Stop
# redirectarea 2>$null ar arunca NativeCommandError in PS 5.1; verificam $LASTEXITCODE.
$ErrorActionPreference = 'Continue'
$r = [PSCustomObject]@{ Commit='nimic'; Origin='-'; Push='-'; Warnings=@() }
if (-not (Test-Path -LiteralPath (Join-Path $RepoDir '.git'))) {
Write-Host " ${Label}: fara repo git ($RepoDir) - sar peste."
$r.Commit = 'fara-repo'
return $r
}
$branch = (& git -C $RepoDir rev-parse --abbrev-ref HEAD).Trim()
if ($branch -ne 'main') {
# tree curat = putem trece pe main; altfel nu atingem branch-ul
$dirty = @(& git -C $RepoDir status --porcelain).Count -gt 0
if ($dirty) {
Write-Host " ${Label}: esti pe '$branch'; sync-ul se face pe main. Ai modificari necomise - sar peste."
$r.Commit = 'skip-branch'
return $r
}
Write-Host " ${Label}: pe '$branch' cu tree curat - fac checkout main."
& git -C $RepoDir checkout main | Out-Null
if ($LASTEXITCODE -ne 0) {
Write-Host " ${Label}: checkout main a esuat - sar peste."
$r.Commit = 'skip-branch'
return $r
}
}
& git -C $RepoDir add -A | Out-Null
$staged = @(& git -C $RepoDir status --porcelain).Count -gt 0
if ($staged) {
$msg = if ($Rev) { "sync SVN r$Rev" } else { "sync SVN" }
& git -C $RepoDir commit -m $msg | Out-Null
if ($LASTEXITCODE -ne 0) {
Write-Host " ${Label}: commit a esuat - sar peste reconciliere."
$r.Commit = 'esec-commit'
$r.Warnings += "${Label}: commit de sync esuat"
return $r
}
Write-Host " ${Label}: commit '$msg'."
$r.Commit = 'commit'
} else {
Write-Host " ${Label}: nimic de comis."
}
# --- reconciliere cu origin (dupa commit: tree curat, fisierele noi sunt deja urmarite) ---
$originUrl = (& git -C $RepoDir remote get-url origin 2>$null | Out-String).Trim()
if ($LASTEXITCODE -ne 0 -or -not $originUrl) {
Write-Host " ${Label}: fara remote origin - repo doar local, sar peste reconciliere."
$r.Origin = 'fara-origin'
return $r
}
& git -C $RepoDir fetch origin 2>$null | Out-Null
if ($LASTEXITCODE -ne 0) {
Write-Host " ${Label}: AVERTISMENT: git fetch origin a esuat (offline / gitea inaccesibil?); reconcilierea ramane pe urmatoarea rulare."
$r.Origin = 'fetch-esuat'
$r.Warnings += "${Label}: fetch origin esuat - reconciliere amanata"
return $r
}
& git -C $RepoDir rev-parse --verify --quiet origin/main 2>$null | Out-Null
if ($LASTEXITCODE -ne 0) {
Write-Host " ${Label}: origin nu are inca main - sar peste reconciliere."
$r.Origin = 'fara-origin-main'
return $r
}
for ($attempt = 1; $attempt -le 3; $attempt++) {
$behind = [int]((& git -C $RepoDir rev-list --count main..origin/main | Out-String).Trim())
$ahead = [int]((& git -C $RepoDir rev-list --count origin/main..main | Out-String).Trim())
if ($behind -gt 0 -and $ahead -eq 0) {
& git -C $RepoDir merge --ff-only origin/main 2>$null | Out-Null
if ($LASTEXITCODE -ne 0) {
Write-Host " ${Label}: AVERTISMENT: fast-forward la origin/main a esuat neasteptat - verifica manual."
$r.Origin = 'conflict'
$r.Warnings += "${Label}: fast-forward esuat - verifica manual repo-ul"
return $r
}
Write-Host " ${Label}: adus la zi cu origin/main (fast-forward, $behind commit-uri)."
$r.Origin = 'ff'
} elseif ($behind -gt 0 -and $ahead -gt 0) {
Write-Host " ${Label}: local si origin au divergat (ahead $ahead / behind $behind) - rebase pe origin/main."
& git -C $RepoDir rebase --empty=drop origin/main 2>$null | Out-Null
if ($LASTEXITCODE -ne 0) {
& git -C $RepoDir rebase --abort 2>$null | Out-Null
Write-Host " ${Label}: CONFLICT real la rebase pe origin/main - rebase anulat. Rezolva manual: git -C $RepoDir rebase origin/main"
$r.Origin = 'conflict'
$r.Warnings += "${Label}: conflict real cu origin/main - reconciliere manuala necesara"
return $r
}
$r.Origin = 'rebase'
} elseif ($r.Origin -eq '-') {
$r.Origin = if ($ahead -gt 0) { 'doar-ahead' } else { 'la-zi' }
}
# --- push doar daca tot ahead-ul e din commit-uri de sync ---
$aheadMsgs = @(& git -C $RepoDir log --format=%s origin/main..main) | Where-Object { $_ -and $_.Trim() }
if ($aheadMsgs.Count -eq 0) {
Write-Host " ${Label}: la zi cu origin/main; nimic de impins."
$r.Push = 'nimic'
return $r
}
$nonSync = @($aheadMsgs | Where-Object { $_ -notmatch '^sync SVN( r\S+)?$' })
if ($nonSync.Count -gt 0) {
Write-Host " ${Label}: AVERTISMENT: ahead de origin include commit-uri non-sync - NU fac push automat (push manual dupa review):"
$nonSync | Select-Object -First 5 | ForEach-Object { Write-Host " - $_" }
$r.Push = 'sarit-non-sync'
$r.Warnings += "${Label}: push sarit - exista commit-uri non-sync nepushed"
return $r
}
& git -C $RepoDir push origin main 2>$null | Out-Null
if ($LASTEXITCODE -eq 0) {
Write-Host " ${Label}: push origin main ($($aheadMsgs.Count) commit-uri de sync)."
$r.Push = 'push'
return $r
}
if ($attempt -lt 3) {
Write-Host " ${Label}: push respins (probabil push simultan de pe alta masina) - refetch si reiau (incercarea $($attempt+1))."
& git -C $RepoDir fetch origin 2>$null | Out-Null
if ($LASTEXITCODE -ne 0) {
Write-Host " ${Label}: AVERTISMENT: refetch esuat dupa push respins."
$r.Push = 'esec'
$r.Warnings += "${Label}: push esuat si refetch esuat - reconciliere la urmatoarea rulare"
return $r
}
}
}
Write-Host " ${Label}: AVERTISMENT: push respins de 3 ori - renunt; se reconciliaza la urmatoarea rulare."
$r.Push = 'esec'
$r.Warnings += "${Label}: push esuat dupa 3 incercari"
return $r
}
Write-Host ''
Write-Host "--- 3. sync repo proiect ---"
$resProj = Sync-Repo -RepoDir $ProjectRoot -Rev $rev -Label 'proiect'
Write-Host ''
Write-Host "--- 4. sync repo COMUN ---"
$revComun = ''
$resComun = [PSCustomObject]@{ Commit='nimic'; Origin='-'; Push='-'; Warnings=@() }
if (Test-Path -LiteralPath $comunRoot -PathType Container) {
if (-not $GitOnly) { $revComun = Get-SvnRev $comunRoot }
$resComun = Sync-Repo -RepoDir $comunRoot -Rev $revComun -Label 'COMUN'
} else {
Write-Host " COMUN: folderul nu exista ($comunRoot) - sar peste."
}
# =========================== 5. inchidere branch-uri claude/* ===========================
# Inchide branch-urile claude/* al caror diff fata de main e gol (munca lor a intrat prin sync).
function Close-ClaudeBranches {
param([string]$RepoDir, [string]$Label)
$closed = @(); $active = @()
if (-not (Test-Path -LiteralPath (Join-Path $RepoDir '.git'))) { return @{ Closed=$closed; Active=$active } }
$branches = @(& git -C $RepoDir for-each-ref --format='%(refname:short)' refs/heads/claude 2>$null) |
Where-Object { $_ -and $_.Trim() } | ForEach-Object { $_.Trim() }
foreach ($b in $branches) {
$diff = @(& git -C $RepoDir diff --name-only main..$b 2>$null) | Where-Object { $_ -and $_.Trim() }
if ($diff.Count -eq 0) {
& git -C $RepoDir branch -D $b | Out-Null
if ($LASTEXITCODE -eq 0) { $closed += $b; Write-Host " ${Label}: inchis $b" }
else { Write-Host " ${Label}: nu am putut sterge $b" }
} else {
$active += $b
Write-Host " ${Label}: activ $b ($($diff.Count) fisiere diferite)"
}
}
return @{ Closed=$closed; Active=$active }
}
Write-Host ''
Write-Host "--- 5. inchidere branch-uri claude/* ---"
$brProj = Close-ClaudeBranches -RepoDir $ProjectRoot -Label 'proiect'
$brComun = @{ Closed=@(); Active=@() }
if (Test-Path -LiteralPath $comunRoot -PathType Container) {
$brComun = Close-ClaudeBranches -RepoDir $comunRoot -Label 'COMUN'
}
# =========================== 6. sumar ===========================
$commits = @()
if ($resProj.Commit -eq 'commit') { $commits += "proiect: sync SVN$(if($rev){" r$rev"})" }
if ($resComun.Commit -eq 'commit') { $commits += "COMUN: sync SVN$(if($revComun){" r$revComun"})" }
$closedAll = @($brProj.Closed + $brComun.Closed)
$activeAll = @($brProj.Active + $brComun.Active)
$warnAll = @($resProj.Warnings + $resComun.Warnings)
Write-Host ''
Write-Host "===================== SUMAR ====================="
Write-Host "Revizie SVN: proiect=$(if($rev){$rev}else{'?'})$(if($revComun){" COMUN=$revComun"})"
if ($commits.Count -gt 0) {
Write-Host "Commit-uri de sync:"
$commits | ForEach-Object { Write-Host " $_" }
} else {
Write-Host "Commit-uri de sync: nimic de sincronizat"
}
Write-Host "Origin: proiect=$($resProj.Origin)/push=$($resProj.Push) COMUN=$($resComun.Origin)/push=$($resComun.Push)"
Write-Host "Branch-uri inchise: $(if($closedAll.Count){$closedAll -join ', '}else{'niciunul'})"
Write-Host "Branch-uri active: $(if($activeAll.Count){$activeAll -join ', '}else{'niciunul'})"
if ($warnAll.Count -gt 0) {
Write-Host "AVERTISMENTE:"
$warnAll | ForEach-Object { Write-Host " $_" }
}
Write-Host "================================================"
if (($resProj.Origin -eq 'conflict') -or ($resComun.Origin -eq 'conflict')) { exit 1 }
exit 0
Write-Host "NOTA: roa_sync.ps1 s-a mutat in COMUN\scripts\. Actualizeaza lansatorul sa cheme direct: $target"
$extra = @()
if ($GitOnly) { $extra += '-GitOnly' }
& powershell -ExecutionPolicy Bypass -NoProfile -File $target -ProjectRoot $ProjectRoot @extra
exit $LASTEXITCODE