# maint_doc_oneoff.ps1 # But : cr?er/mettre ? jour un fichier TXT de gouvernance avec backup obligatoire, # aper?u des actions (preview), confirmation, ex?cution, archivage et log. # Environnement : Windows PowerShell (sans droits admin), ASCII par d?faut. # Usage : coller tel quel dans la console, ajuster les variables bloc [CONFIG], puis Entr?e. # ========================= # [CONFIG] A ADAPTER # ========================= $TargetPath = "\\DS-918\chatgpt\ChatGPT-Gouvernance-Projets\_registry\latest_cycle.txt" $ArchiveDir = "\\DS-918\chatgpt\ChatGPT-Gouvernance-Projets\_registry\_archives\2025-10-15_SOURCE-OF-TRUTH" $OldVersionsDir = "\\DS-918\chatgpt\ChatGPT-Gouvernance-Projets\_registry\_old_versions" $RegistryLogPath = "C:\Logs_Gouvernance\registry_activity.log" # exig? pour ex?cution $FileEncoding = "ascii" # "ascii" (pr?f?r?) ou "utf8NoBOM" # Contenu du fichier cible (ASCII recommand?) $Content = @" =========================================================== LATEST CYCLE ? CHATGPT-GOUVERNANCE-PROJETS =========================================================== Cycle : SOURCE-OF-TRUTH ? 2025-10-15 Commit final : F92B13D7E55C8A79E3F4D3A52BC71F490CA928AB Snapshot : snapshot_2025-10-15_fusion_history.json Rapport : RAPPORT_COHERENCE_XREF_2025-10-15.txt =========================================================== "@ # D?placement auto d?une ?ventuelle ancienne version du fichier vers _old_versions (True/False) $MoveOldToOldVersions = $true # ========================= # [FONCTIONS] # ========================= function New-ParentDirectory { param([string]$Path) $dir = Split-Path -Path $Path -Parent if (-not [string]::IsNullOrWhiteSpace($dir) -and -not (Test-Path -LiteralPath $dir)) { New-Item -ItemType Directory -LiteralPath $dir | Out-Null } } function Get-Timestamp { (Get-Date).ToString("yyyy-MM-dd_HH-mm-ss") } function Get-FileSha1 { param([string]$Path) if (-not (Test-Path -LiteralPath $Path)) { return $null } $sha1 = [System.Security.Cryptography.SHA1]::Create() $fs = [System.IO.File]::OpenRead($Path) try { $hash = $sha1.ComputeHash($fs) ($hash | ForEach-Object { $_.ToString("x2") }) -join "" } finally { $fs.Dispose() $sha1.Dispose() } } function Write-TextFile { param( [string]$Path, [string]$Text, [ValidateSet("ascii","utf8NoBOM")][string]$Encoding = "ascii" ) New-ParentDirectory -Path $Path if ($Encoding -eq "ascii") { [System.IO.File]::WriteAllText($Path, $Text, [System.Text.Encoding]::ASCII) } else { $utf8NoBom = New-Object System.Text.UTF8Encoding($false) [System.IO.File]::WriteAllText($Path, $Text, $utf8NoBom) } } function Append-Log { param([string]$LogPath, [string]$Line) $dir = Split-Path -Parent $LogPath if (-not (Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null } $ts = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss") Add-Content -Path $LogPath -Value "$ts | $Line" -Encoding ASCII } # ========================= # [PREVIEW] # ========================= $ts = Get-Timestamp $preview = @() if ([string]::IsNullOrWhiteSpace($RegistryLogPath)) { $preview += "[ERROR] RegistryLogPath est vide (obligatoire)." } $existing = $null $existingSha1 = $null if (Test-Path -LiteralPath $TargetPath) { $existing = $TargetPath $existingSha1 = Get-FileSha1 -Path $TargetPath } $backupPath = $null if ($existing) { $backupPath = "{0}.{1}.bak" -f $TargetPath, $ts $preview += "[INFO] Fichier cible existe : $TargetPath" $preview += "[INFO] SHA1 existant : $existingSha1" $preview += "[PLAN] Cr?ation d?un backup : $backupPath" if ($MoveOldToOldVersions) { $preview += "[PLAN] Apr?s ?criture, d?placement de l?ancienne version vers : $OldVersionsDir" } } else { $preview += "[INFO] Fichier cible inexistant : $TargetPath (cr?ation)" } $preview += "[PLAN] Ecriture du fichier (encodage=$FileEncoding)" $preview += "[PLAN] Journalisation append dans : $RegistryLogPath" "[PREVIEW] Op?rations pr?vues :" $preview | ForEach-Object { $_ } # ========================= # [CONFIRMATION] # ========================= $confirm = Read-Host "Confirmer l?ex?cution ? (O/N)" if ($confirm -notin @('O','o','Y','y')) { "[ABORT] Op?rations annul?es par l?utilisateur." return } if ([string]::IsNullOrWhiteSpace($RegistryLogPath)) { "[ERROR] RegistryLogPath non d?fini. Abandon." return } # ========================= # [EXECUTION] # ========================= try { # 1) Backup si le fichier existe if ($existing) { Copy-Item -LiteralPath $TargetPath -Destination $backupPath -Force } # 2) Ecriture du nouveau contenu Write-TextFile -Path $TargetPath -Text $Content -Encoding $FileEncoding # 3) D?placement de l?ancienne version vers _old_versions si demand? if ($existing -and $MoveOldToOldVersions) { New-ParentDirectory -Path $OldVersionsDir $base = Split-Path -Leaf $TargetPath $oldName = Join-Path $OldVersionsDir ("{0}.old.{1}.txt" -f $base, $ts) Move-Item -LiteralPath $backupPath -Destination $oldName -Force $backupPath = $oldName } # 4) SHA1 final $newSha1 = Get-FileSha1 -Path $TargetPath # 5) Log append $line = "UPDATE | target=$TargetPath | sha1=$newSha1 | backup=$backupPath | enc=$FileEncoding" Append-Log -LogPath $RegistryLogPath -Line $line "[OK] Mise ? jour effectu?e." "[OK] Fichier : $TargetPath" if ($backupPath) { "[OK] Ancienne version : $backupPath" } "[OK] SHA1 nouveau : $newSha1" "[OK] Log : $RegistryLogPath" } catch { "[ERROR] " + $_.Exception.Message exit 1 }