src/GitUtils.ps1
|
#requires -Version 5.1 # GitUtils.ps1 - Core git utility functions for power-git # Invoke git and return stdout lines, suppressing stderr function Invoke-Git { [CmdletBinding()] param( [Parameter(Mandatory, ValueFromRemainingArguments)] [string[]]$Arguments ) $result = & git @Arguments 2>$null if ($LASTEXITCODE -eq 0) { return $result } return $null } # Invoke git and return raw output (including non-zero exit, for porcelain queries) function Invoke-GitRaw { [CmdletBinding()] param( [Parameter(Mandatory, ValueFromRemainingArguments)] [string[]]$Arguments ) $output = & git @Arguments 2>$null return $output } # Find the root of the git repo (or worktree) for the given path function Get-GitDirectory { [CmdletBinding()] [OutputType([string])] param( [string]$Path = (Get-Location).Path ) # Fast path: ask git directly $gitDir = & git -C $Path rev-parse --git-dir 2>$null if ($LASTEXITCODE -ne 0 -or -not $gitDir) { return $null } # Make absolute if (-not [System.IO.Path]::IsPathRooted($gitDir)) { $gitDir = Join-Path $Path $gitDir } return [System.IO.Path]::GetFullPath($gitDir) } # Return the work-tree root (i.e. the directory containing .git) function Get-GitRoot { [CmdletBinding()] [OutputType([string])] param( [string]$Path = (Get-Location).Path ) $root = & git -C $Path rev-parse --show-toplevel 2>$null if ($LASTEXITCODE -ne 0) { return $null } return $root } # Test whether the current directory is inside a git repo function Test-GitRepository { [CmdletBinding()] [OutputType([bool])] param( [string]$Path = (Get-Location).Path ) $null = & git -C $Path rev-parse --git-dir 2>$null return $LASTEXITCODE -eq 0 } # Return all local branch names function Get-GitLocalBranches { [CmdletBinding()] [OutputType([string[]])] param() $branches = Invoke-Git 'branch' '--format=%(refname:short)' return @($branches) } # Return all remote-tracking refs as "remote/branch" function Get-GitRemoteBranches { [CmdletBinding()] [OutputType([string[]])] param() $refs = Invoke-Git 'branch' '--remote' '--format=%(refname:short)' # Filter out HEAD pointers like "origin/HEAD" return @($refs | Where-Object { $_ -notmatch '/HEAD$' }) } # Return all tag names function Get-GitTags { [CmdletBinding()] [OutputType([string[]])] param() return @(Invoke-Git 'tag' '--sort=-version:refname') } # Return all configured remote names function Get-GitRemotes { [CmdletBinding()] [OutputType([string[]])] param() return @(Invoke-Git 'remote') } # Return stash list entries (ref:message) function Get-GitStashes { [CmdletBinding()] [OutputType([string[]])] param() return @(Invoke-Git 'stash' 'list' '--format=%gd: %s') } # Return the current HEAD commit hash (short) function Get-GitHeadHash { [CmdletBinding()] [OutputType([string])] param([switch]$Long) if ($Long) { return Invoke-Git 'rev-parse' 'HEAD' } return Invoke-Git 'rev-parse' '--short' 'HEAD' } # Return the current branch name (or $null if detached) function Get-GitBranchName { [CmdletBinding()] [OutputType([string])] param() $branch = Invoke-Git 'symbolic-ref' '--short' 'HEAD' return $branch } # Return all files in the index (for path completion in add/checkout/etc.) function Get-GitIndexFiles { [CmdletBinding()] [OutputType([string[]])] param( [string]$Prefix = '' ) $files = Invoke-Git 'ls-files' '--cached' '--others' '--exclude-standard' if ($Prefix) { return @($files | Where-Object { $_ -like "${Prefix}*" }) } return @($files) } # Return files with merge conflicts function Get-GitConflictFiles { [CmdletBinding()] [OutputType([string[]])] param() $files = Invoke-Git 'diff' '--name-only' '--diff-filter=U' return @($files) } # Detect git executable availability function Test-GitAvailable { [CmdletBinding()] [OutputType([bool])] param() $null = Get-Command git -ErrorAction SilentlyContinue return $? } # Return a hashtable of configured merge/diff/log aliases function Get-GitAliases { [CmdletBinding()] [OutputType([hashtable])] param() $lines = Invoke-Git 'config' '--get-regexp' '^alias\.' $aliases = @{} foreach ($line in $lines) { if ($line -match '^alias\.(\S+)\s+(.+)$') { $aliases[$Matches[1]] = $Matches[2] } } return $aliases } # Return the name of the configured upstream branch for the given local branch function Get-GitUpstreamBranch { [CmdletBinding()] [OutputType([string])] param( [string]$Branch = '@' ) return Invoke-Git 'rev-parse' '--abbrev-ref' "${Branch}@{upstream}" } # Return submodule paths relative to repo root function Get-GitSubmodules { [CmdletBinding()] [OutputType([string[]])] param() $paths = Invoke-Git 'submodule' '--quiet' 'foreach' '--recursive' 'echo $displaypath' return @($paths) } # Return recent commits for log-based completions function Get-GitRecentCommits { [CmdletBinding()] [OutputType([string[]])] param([int]$Count = 20) return @(Invoke-Git 'log' "--max-count=$Count" '--format=%H %s') } |