Last active
September 21, 2020 23:20
-
-
Save pvspain/aa5a249385b1c47613512308bcbdf263 to your computer and use it in GitHub Desktop.
powershell profile incorporating git status
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env pwsh | |
function Prompt { | |
$promptColor, | |
$infoColor, | |
$warnColor, | |
$errorColor, | |
$defaultColor = | |
'Cyan', | |
'Green', | |
'Yellow', | |
'Red', | |
'White' | |
$version = $PSVersionTable.PSVersion.ToString() | |
# Substitute shortened form of $HOME if present | |
# We must double-up Windows path-separator characters '\' (backslash) before passing off for regex evaluation. | |
# Regex library is C-based and '\' (backslash) is the special-quoted-character-prefix. A literal backslash is represented as '\\' | |
$myHome = if ($IsLinux -or $IsMacOS) { $HOME } else {$HOME -replace '\\', '\\' } | |
$location = (Get-Location).Path -replace $myHome, '~' | |
Write-Host "PS v$version $location " -NoNewline -ForegroundColor $promptColor | |
# Get details about current repository | |
# We can't append "--abrev-ref HEAD" as it gets interpreted as additional arguments to "--short" | |
$gitDir, | |
$insideGitDir, | |
$isBareRepo, | |
$insideWorkTree, | |
$localRev, | |
$shortSha = | |
(& git rev-parse ` | |
--git-dir ` | |
--is-inside-git-dir ` | |
--is-bare-repository ` | |
--is-inside-work-tree ` | |
'@' ` | |
--short HEAD 2> $null) | |
# Are we in a git repository? | |
# $gitDir is relative path to '.git' dir for local repository, empty for non-repository | |
if ($gitDir) { | |
# Separator before git info | |
Write-Host '| ' -NoNewline -ForegroundColor $promptColor | |
function Test-DetachedHead { | |
$head = Get-Content "$gitDir\HEAD" | |
-not ($head -match 'ref: ') | |
} | |
# Initialise local vars | |
$fgColor, $next, $local, $remote, $status = $infoColor, @(), @(), @(), @() | |
## Process local repo 'dirty' status... | |
# Check for staged changes | |
$staged = [bool](& git diff --no-ext-diff --staged) | |
# Check for unstaged changes | |
$unstaged = [bool](& git diff --no-ext-diff) | |
# Required actions to migrate workspace state to local repository | |
if ($unstaged) { $next += , 'add' } | |
if ($staged) { $next += , 'commit' } | |
if ($next) { $fgColor = $warnColor } | |
## Process 'local' repo status... | |
if (Test-DetachedHead) { | |
$local = "local:$shortSha (detached)" | |
# Add any tags for current revision... | |
if ($localTags = (&git tag --points-at '@')) { | |
$local += " tags:$localTags" | |
} | |
$fgColor = $errorColor | |
} | |
else { | |
$localBranch = $(& git symbolic-ref --short HEAD) | |
$local = "local:$localBranch" | |
} | |
## Process 'remote' repo status... | |
# Remote status is irrelevant for detached local repo | |
if (-not (Test-DetachedHead)) { | |
$remoteBranch = (& git rev-parse --abbrev-ref '@{u}') | |
$remote = "remote:$remoteBranch" | |
# NOTE: Relies on a recent 'git fetch' operation for fresh remote information | |
$remoteRev = (& git rev-parse '@{u}') | |
$lastCommonRev = (& git merge-base '@' '@{u}') | |
# Check for valid values | |
if (($remoteRev -ne '@u') -and $lastCommonRev) { | |
# NOTE: We are not modifying $fgColor for remote state | |
if ($localRev -eq $remoteRev) { | |
# Local and remote repo committed revisions match. | |
} | |
elseif ($localRev -eq $lastCommonRev) { | |
# Remote repo ahead. Pull required. | |
# NOTE: Leading (,) below converts RHS to an array | |
# - and stops conversion of $next to scalar string | |
$next += , 'pull' | |
} | |
elseif ($remoteRev -eq $lastCommonRev) { | |
# Local repo ahead. Push required. | |
$next += , 'push' | |
} | |
else { | |
# Local and origin repos have diverged - pull then push. | |
$next += 'pull', 'push' | |
} | |
} | |
} | |
## Build displayed 'status'... | |
if ($next) { $status += "next:$($next -join ',')" } | |
if ($local) { $status += $local } # $local will always have content | |
if ($remote) { $status += $remote } | |
Write-Host "git $status" -NoNewline -ForegroundColor $fgColor | |
} | |
Write-Host "`n`$" -NoNewline -ForegroundColor $defaultColor | |
return " " | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment