Extensions/Git.Status.UGit.Extension.ps1
<# .SYNOPSIS git status extension .DESCRIPTION Returns git status as an object. .EXAMPLE git status .EXAMPLE git status | Select-Object -ExpandProperty Untracked #> [Management.Automation.Cmdlet("Out","Git")] [ValidatePattern('^git status')] param( ) begin { <# If any of these parameters are used, we will skip processing. #> $SkipIf = 'porcelain' -join '|' if ($gitCommand -match "\s-(?>$SkipIf)") { break } $statusLines = @() } process { $statusLines += "$gitOut" } end { $gitStatusOut = [Ordered]@{ PSTypeName = 'Git.Status' BranchName = '' Status = '' Staged = @() Unstaged = @() Untracked = @() GitRoot = $GitRoot } $inPhase = '' for ($sln = 0; $sln -lt $statusLines.Length; $sln++) { if ($sln -eq 0) { $gitStatusOut.BranchName = @($statusLines[$sln] -split ' ' -ne '')[-1] continue } if ($statusLines[$sln] -like '*not staged for commit:*') { # When on a new branch with no upstream, this comes first. $inPhase = 'Unstaged' continue } if ($statusLines[$sln] -like "Changes to be committed:*") { $inPhase = 'Staged' } if ($statusLines[$sln] -like "Untracked files:*") { $inPhase = 'Untracked' continue } if ($sln -eq 1 -and -not $inPhase) { $gitStatusOut.Status = $statusLines[$sln] continue } if ($statusLines[$sln] -match '^\s+\(') { continue } if ($statusLines[$sln] -match '^\s+' -and $inPhase) { $trimmedLine = $statusLines[$sln].Trim() $changeType = if ( $trimmedLine -match "^([\w\s]+):") { $matches.1 } else { '' } $changePath = $trimmedLine -replace "^[\w\s]+:\s+" if ($inPhase -eq 'untracked') { $gitStatusOut.$inPhase += Get-Item -ErrorAction SilentlyContinue -Path $changePath } else { $gitStatusOut.$inPhase += [PSCustomObject]@{ ChangeType = $changeType -replace '\s' Path = $changePath File = Get-Item -ErrorAction SilentlyContinue -Path $changePath } } } } $gitStatusOut.StatusLines = $statusLines if ($gitStatusOut.BranchName) { [PSCustomObject]$gitStatusOut } else { $statusLines } } |