# deposit_tree_lot2_blocking_fix_v1.0.ps1 # Objet : Déposer un lot (arborescence) depuis C:\GovDrop\incoming\lot2\* vers \\..._registry\ # SAFE-CREATE : Ensure-Parent -> copie __tmp_tree -> Move-Item atomique -> .bak -> triple SHA # PS 5.1 strict, UTF-8 BOM. param( [string]$Root="\\DS-918\chatgpt\ChatGPT-Gouvernance-Projets\_registry", [string]$InDir="C:\GovDrop\incoming\lot2", [switch]$Preview, [switch]$Execute ) if($Preview -and $Execute){ Write-Host "[NOK] -Preview et -Execute exclusifs."; exit 1 } if(-not $Preview -and -not $Execute){ $Preview = $true } function NowIso(){ (Get-Date).ToString("yyyyMMdd_HHmmss") } function Ensure-Parent([string]$p){ $parent=[IO.Path]::GetDirectoryName($p) if(-not [string]::IsNullOrWhiteSpace($parent)){ [void][IO.Directory]::CreateDirectory($parent) } } function Sha([string]$p){ if(Test-Path -LiteralPath $p){ (Get-FileHash -LiteralPath $p -Algorithm SHA256).Hash } else { "" } } if(-not (Test-Path -LiteralPath $InDir)){ Write-Host ("[NOK] InDir introuvable : {0}" -f $InDir); exit 2 } $ts = NowIso # Liste de tous les fichiers sous InDir $files = Get-ChildItem -LiteralPath $InDir -Recurse -File -ErrorAction SilentlyContinue | Sort-Object FullName $plan = @() foreach($f in $files){ $rel = $f.FullName.Substring($InDir.Length).TrimStart('\','/') $dst = Join-Path -Path $Root -ChildPath $rel $tmp = Join-Path -Path (Join-Path -Path $Root -ChildPath "__tmp_tree") -ChildPath $rel $plan += [pscustomobject]@{ Src=$f.FullName; Rel=$rel; Tmp=$tmp; Dst=$dst } } Write-Host ("== PREVIEW DEPOT TREE :: {0} fichier(s) ==" -f $plan.Count) foreach($p in $plan){ Write-Host ("DEPOT {0} -> {1}" -f $p.Src, $p.Dst) } if($Preview){ Write-Host "[INFO] Preview : aucune écriture." Write-Host ("Pour exécuter :`n powershell -NoProfile -ExecutionPolicy Bypass -File `"{0}`" -Execute" -f $MyInvocation.MyCommand.Definition) exit 0 } if($Execute){ $ok=0; $errors=0 foreach($p in $plan){ try{ Ensure-Parent $p.Tmp Copy-Item -LiteralPath $p.Src -Destination $p.Tmp -Force $shaLocal = Sha $p.Src $shaTmp = Sha $p.Tmp if($shaLocal -ne $shaTmp){ Write-Host ("[NOK] SHA local/tmp diff -> {0}" -f $p.Rel); $errors++; continue } if(Test-Path -LiteralPath $p.Dst){ $bak = $p.Dst + "." + $ts + ".bak" Rename-Item -LiteralPath $p.Dst -NewName (Split-Path -Leaf $bak) -Force } Ensure-Parent $p.Dst Move-Item -LiteralPath $p.Tmp -Destination $p.Dst -Force $shaFinal = Sha $p.Dst if($shaFinal -ne $shaLocal){ Write-Host ("[NOK] SHA final diff -> {0}" -f $p.Rel); $errors++ } else { $ok++ } }catch{ $errors++ Write-Host ("[NOK] {0} -> {1} :: {2}" -f $p.Src, $p.Dst, $_.Exception.Message) } } Write-Host ("== RESULTAT == OK={0} Errors={1}" -f $ok, $errors) exit ([int]([bool]($errors -gt 0))) }