Private/Git.ps1
|
# Git detection by reading files only: no call to git.exe, so that the prompt hook # stays below a millisecond. function Get-TcGitDirectory { <# .SYNOPSIS Returns the path of the .git directory associated with a folder (handles worktrees, where .git is a file containing [gitdir: ...]). #> [CmdletBinding()] param([string] $Path) $candidate = Join-Path $Path '.git' if ([System.IO.Directory]::Exists($candidate)) { return $candidate } if ([System.IO.File]::Exists($candidate)) { try { $content = [System.IO.File]::ReadAllText($candidate) } catch { return $null } $m = [regex]::Match($content, '^\s*gitdir:\s*(.+?)\s*$', 'Multiline') if ($m.Success) { $target = $m.Groups[1].Value if (-not [System.IO.Path]::IsPathRooted($target)) { $target = [System.IO.Path]::GetFullPath((Join-Path $Path $target)) } if ([System.IO.Directory]::Exists($target)) { return $target } } } return $null } function Test-TcGitRoot { [CmdletBinding()] param([string] $Path) return $null -ne (Get-TcGitDirectory -Path $Path) } function Get-TcGitBranch { <# .SYNOPSIS Current branch name read from .git/HEAD. Returns $null when detached or not found. #> [CmdletBinding()] param([string] $Path) $gitDir = Get-TcGitDirectory -Path $Path if (-not $gitDir) { return $null } $head = Join-Path $gitDir 'HEAD' if (-not [System.IO.File]::Exists($head)) { return $null } try { $content = ([System.IO.File]::ReadAllText($head)).Trim() } catch { return $null } if ($content -match '^ref:\s*refs/heads/(.+)$') { return $Matches[1].Trim() } return $null # detached HEAD } |