functions/Invoke-GitExpression.ps1
function Invoke-GitExpression { <# .SYNOPSIS Runs the provided git command on the local computer. .DESCRIPTION Runs the provided git command on the local computer. Both git output streams (success (1) and error (2)) are redirected to the Powershell success (1) output stream. This provides behavior consistent with other Powershell commands, and means that piping to commands such as Out-Null will behave as expected. The output from either (or both) git streams can be suppressed with optional switches. The function will also accept non-git commands, but the output from non-git commands will be returned as strings. .PARAMETER Command The git command to be run. .PARAMETER SuppressGitSuccessStream When true, the output from the git success (1) stream will be suppressed. .PARAMETER SuppressGitErrorStream When true, the output from the git error (2) stream will be suppressed. .EXAMPLE ## Native git command vs Invoke-GitExpression - output to console ## C:\PowdrgitExamples\MyToolbox> git checkout main Already on 'main' Your branch is ahead of 'origin/main' by 3 commits. (use "git push" to publish your local commits) C:\PowdrgitExamples\MyToolbox> # Although not obvious, the first line of the above output from the native git command is from the error stream, and the second and third are from the success stream. C:\PowdrgitExamples\MyToolbox> Invoke-GitExpression -Command 'git checkout main' Already on 'main' Your branch is ahead of 'origin/main' by 3 commits. (use "git push" to publish your local commits) C:\PowdrgitExamples\MyToolbox> # The same results appear in the console. Also not obvious, but this time all lines of output are coming from Powershell's success stream. .EXAMPLE ## Native git command vs Invoke-GitExpression - output to Out-Null ## C:\PowdrgitExamples\MyToolbox> git checkout main | Out-Null Already on 'main' C:\PowdrgitExamples\MyToolbox> # Piping to Out-Null usually results in nothing returned to the console. However, here we see a message returned, coming from git's error stream. C:\PowdrgitExamples\MyToolbox> Invoke-GitExpression -Command 'git checkout main' | Out-Null C:\PowdrgitExamples\MyToolbox> # This time, all output is suppressed, as expected. .EXAMPLE ## Invoke-GitExpression - suppressing output ## C:\PowdrgitExamples\MyToolbox> Invoke-GitExpression -Command 'git checkout main' -SuppressGitErrorStream Your branch is ahead of 'origin/main' by 3 commits. (use "git push" to publish your local commits) C:\PowdrgitExamples\MyToolbox> # The message coming from git's error stream has been omitted. C:\PowdrgitExamples\MyToolbox> Invoke-GitExpression -Command 'git checkout main' -SuppressGitSuccessStream Already on 'main' C:\PowdrgitExamples\MyToolbox> # The message coming from git's success stream has been omitted. C:\PowdrgitExamples\MyToolbox> Invoke-GitExpression -Command 'git checkout main' -SuppressGitSuccessStream -SuppressGitErrorStream C:\PowdrgitExamples\MyToolbox> # Using both switches suppresses all output, equivalent to piping to Out-Null. .INPUTS [System.String] Accepts string objects via the Command parameter. .OUTPUTS [System.String] Returns String objects. .NOTES Author : nmbell .LINK Set-GitBranch .LINK Invoke-GitClone .LINK about_powdrgit .LINK https://github.com/nmbell/powdrgit/blob/main/help/about_powdrgit.md #> # Function alias [Alias('ige')] # Use cmdlet binding [CmdletBinding( HelpURI = 'https://github.com/nmbell/powdrgit/blob/main/help/Invoke-GitExpression.md' )] # Declare output type [OutputType([System.String])] # Declare parameters Param ( [Parameter( Mandatory = $true , HelpMessage = 'Enter the git command to be run. Multiple commands can be separated with a semicolon ";".' , Position = 0 , ValueFromPipeline = $true , ValueFromPipelineByPropertyName = $true )] [ValidateNotNullOrEmpty()] [String] $Command , [Switch] $SuppressGitSuccessStream , [Switch] $SuppressGitErrorStream ) BEGIN { $bk = 'B' # Common BEGIN: Set-StrictMode -Version 3.0 $thisFunctionName = $MyInvocation.MyCommand $start = Get-Date $indent = ($Powdrgit.DebugIndentChar[0]+' ')*($PowdrgitCallDepth++) $PSDefaultParameterValues += @{ '*:Verbose' = $(If ($DebugPreference -notin 'Ignore','SilentlyContinue') { $DebugPreference } Else { $VerbosePreference }) } # turn on Verbose with Debug Write-Debug " $(ts)$indent[$thisFunctionName][$bk]Start: $($start.ToString('yyyy-MM-dd HH:mm:ss.fff'))" # Function BEGIN: } PROCESS { $bk = 'P' # Force the command to capture both streams $gitCommand = $Command+' 2>&1' # Run the command Write-Verbose "$(ts)$indent[$thisFunctionName][$bk]$gitCommand" Invoke-Expression -Command $gitCommand -ErrorAction Ignore ` | ForEach-Object { If ($_.GetType().Name -eq 'ErrorRecord' ) { If (!$SuppressGitErrorStream ) { $_.Exception.Message.ToString()}; Write-Debug " $(ts)$indent[$thisFunctionName][$bk]$($_.Exception.Message.ToString())" } If ($_.GetType().Name -eq 'String' ) { If (!$SuppressGitSuccessStream) { $_ }; Write-Debug " $(ts)$indent[$thisFunctionName][$bk]$_" } If ($_.GetType().Name -notin 'ErrorRecord','String') { If (!$SuppressGitSuccessStream) { $_.ToString() }; Write-Debug " $(ts)$indent[$thisFunctionName][$bk]$($_.ToString())" } } } END { $bk = 'E' # Function END: # Common END: $end = Get-Date $duration = New-TimeSpan -Start $start -End $end Write-Debug " $(ts)$indent[$thisFunctionName][$bk]Finish: $($end.ToString('yyyy-MM-dd HH:mm:ss.fff')) ($($duration.ToString('d\d\ hh\:mm\:ss\.fff')))" $PowdrgitCallDepth-- } } |