public/New-PSProfileSnapshot.ps1
|
<# .SYNOPSIS Creates a new snapshot of the current user's profile. .DESCRIPTION Creates a new snapshot of the current user's profile for comparison at next run. Snapshots capture both the profile content and its SHA256 hash, and can include optional metadata for organization and documentation. .PARAMETER Name Optional custom name for the snapshot. If not provided, a timestamp-based name is automatically generated. Examples: "before-major-change", "stable-config", "pre-update" .PARAMETER Notes Optional notes or description for the snapshot. Useful for documenting why the snapshot was created or what it represents. .INPUTS None .OUTPUTS System.Management.Automation.PSCustomObject Returns an object with properties: SnapshotName, GUID, HashFile, BackupFile, MetadataFile .EXAMPLE New-PSProfileSnapshot Creates a snapshot with an auto-generated timestamp-based name: - Microsoft.VSCode_profile.ps1_83580fb6-fc89-4756-8a58-b1f4d3f3b7ff.hash - Microsoft.VSCode_profile.ps1_83580fb6-fc89-4756-8a58-b1f4d3f3b7ff.backup .EXAMPLE New-PSProfileSnapshot -Name "before-major-change" -Notes "Created before updating PowerShell modules" Creates a named snapshot with metadata stored in a JSON file: - Microsoft.VSCode_profile.ps1_83580fb6-fc89-4756-8a58-b1f4d3f3b7ff.metadata .NOTES All snapshots are stored in the same directory as the profile file. Use Get-PSProfileSnapshot to list all available snapshots. #> function New-PSProfileSnapshot { [CmdletBinding()] param( [Parameter(Mandatory = $false)] [string]$Name, [Parameter(Mandatory = $false)] [string]$Notes ) $guid = [guid]::NewGuid() $profileHashFile = "$($profile)_$($guid).hash" $profileBackupFile = "$($profile)_$($guid).backup" $metadataFile = "$($profile)_$($guid).metadata" try { $Hash = Get-FileHash -Path $profile -Algorithm SHA256 -ErrorAction Stop | Select-Object -ExpandProperty Hash } catch { Write-Warning "⚠️ Could not calculate hash for profile." throw $_.Exception.Message } try { $Hash | Out-File -FilePath $profileHashFile -Encoding ASCII -Force -ErrorAction Stop Write-Host "✅ Profile snapshot hash saved successfully to '$profileHashFile'." -ForegroundColor Green } catch { Write-Error "❌ Could not write snapshot hash to file." throw $_.Exception.Message } try { Copy-Item -Path $profile -Destination $profileBackupFile -Force -ErrorAction Stop Write-Host "✅ Profile snapshot saved successfully to '$profileBackupFile'." -ForegroundColor Green } catch { Write-Error "❌ Could not save profile snapshot to '$profileBackupFile'." throw $_.Exception.Message } # If a custom name or notes are provided, create metadata file if ($PSBoundParameters.ContainsKey('Name') -or $PSBoundParameters.ContainsKey('Notes')) { $snapshotName = $Name ?? (Get-Date -Format "yyyy-MM-dd HH:mm:ss") $metadata = @{ Name = $snapshotName GUID = $guid.ToString() CreatedAt = (Get-Date -Format "yyyy-MM-dd HH:mm:ss K") Notes = $Notes ?? "" } try { $metadata | ConvertTo-Json | Out-File -FilePath $metadataFile -Encoding UTF8 -Force -ErrorAction Stop Write-Host "✅ Snapshot metadata saved to '$metadataFile'." -ForegroundColor Green } catch { Write-Warning "⚠️ Could not save snapshot metadata, but snapshot files were created successfully." } } # Get file size in KB format for consistency with Get-PSProfileSnapshot $backupFileSizeKB = "$([math]::Round((Get-Item -Path $profileBackupFile).Length / 1KB, 2)) KB" # Get hash content for consistency with Get-PSProfileSnapshot $hashContent = Get-Content -Path $profileHashFile -ErrorAction Stop return [PSCustomObject]@{ Name = $Name ?? (Get-Date -Format "yyyy-MM-dd HH:mm:ss") GUID = $guid Path = $profileBackupFile Hash = $hashContent FileSize = $backupFileSizeKB CreatedTime = (Get-Item -Path $profileBackupFile).CreationTime Notes = $Notes ?? $null } } |