Public/Restore-File.ps1
|
function Restore-File { <# .SYNOPSIS Restore a single file to its last saved state without touching anything else. .DESCRIPTION Restore-File is the targeted GitEasy restore. It resets one file to its last saved version while leaving every other change in the active working area alone. Use it when you want a precise rollback of one file - for example, a generated file you accidentally edited, or a configuration file you want to revert without abandoning the rest of your work. Each invocation writes a self-contained diagnostic log file. Successful runs log silently; failures throw a plain-English message and point at the log file with the technical detail. .PARAMETER Path Path to the file to restore. Can be relative to the current location or absolute. Must be a tracked file in the active project. .PARAMETER LogPath Override the directory where the diagnostic log for this run is written. .EXAMPLE Restore-File -Path README.md .EXAMPLE Find-CodeChange; Restore-File -Path Public\Save-Work.ps1; Find-CodeChange .NOTES Safety: - Refuses to run during an unfinished merge, rebase, cherry-pick, revert, or bisect. - Refuses to run while there are unfinished conflicts. - Refuses to operate on a file that does not exist or is not tracked. - Run Save-Work -NoPush first if you might want the discarded edits later. Steps: 1. Probe for the project folder root and start a diagnostic log session. 2. Check that no merge, rebase, or other in-progress operation is underway. 3. Confirm the specified file is tracked in the project, not just present on disk. 4. Handle WhatIf and return early if applicable. 5. Restore the file to its last saved state. 6. Return a structured result with the file path and a confirmation message. .LINK Find-CodeChange .LINK Undo-Changes .LINK Save-Work #> [CmdletBinding(SupportsShouldProcess)] [OutputType([PSCustomObject])] param( [Parameter(Mandatory, Position = 0)] [string]$Path, [Parameter()] [string]$LogPath = '' ) $repoRoot = $null try { $rootProbe = Invoke-GEGit -ArgumentList @('rev-parse', '--show-toplevel') -AllowFailure if ($rootProbe.ExitCode -eq 0) { $repoRoot = $rootProbe.Output | Select-Object -First 1 } } catch { $repoRoot = $null } $session = Start-GELogSession -Command 'Restore-File' -Repository ([string]$repoRoot) -LogPath $LogPath $userMessageOnFailure = "Could not restore '$Path'." try { Assert-GESafeSave -Path ([string]$repoRoot) -LogPath $session.Path | Out-Null if (-not $repoRoot) { $rootResult = Invoke-GEGit -ArgumentList @('rev-parse', '--show-toplevel') -LogPath $session.Path $repoRoot = $rootResult.Output | Select-Object -First 1 } $lsResult = Invoke-GEGit -ArgumentList @('ls-files', '--error-unmatch', '--', $Path) -WorkingDirectory $repoRoot -LogPath $session.Path -AllowFailure if ($lsResult.ExitCode -ne 0) { throw "'$Path' is not a saved file in this project. Check the path and try again." } if (-not $PSCmdlet.ShouldProcess($Path, 'Restore to last saved state')) { Complete-GELogSession -Path $session.Path -Outcome 'SUCCESS' -UserMessage 'Skipped (WhatIf).' return } Invoke-GEGit -ArgumentList @('checkout', '--', $Path) -WorkingDirectory $repoRoot -LogPath $session.Path | Out-Null Write-Host "Restored '$Path' to its last saved state." $result = [PSCustomObject]@{ Repository = $repoRoot Path = $Path Message = "'$Path' was restored to its last saved state." } Complete-GELogSession -Path $session.Path -Outcome 'SUCCESS' return $result } catch { $err = $_ $innerMessage = $err.Exception.Message if ($innerMessage -like 'git *') { $finalMsg = $userMessageOnFailure } else { $finalMsg = $innerMessage } Complete-GELogSession -Path $session.Path -Outcome 'FAILURE' -UserMessage $finalMsg -ErrorMessage $innerMessage throw "$finalMsg Details: $($session.Path)" } } |