GitPrompt.ps1

<#PSScriptInfo
 
.VERSION 0.1.1
 
.GUID 7546af34-156c-4109-b38c-0fb64e3fe385
 
.AUTHOR Kirill Lappo<dnaplayer@hotmail.com>
 
.COMPANYNAME Kira Lappo
 
.COPYRIGHT (c) 2019 Kirill Lappo. All rights reserved.
 
.TAGS git prompt ps-prompt git-prompt
 
.LICENSEURI https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html
 
.PROJECTURI https://github.com/Kira-Lappo/git-prompt
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 0.1.0 - Initial release, testing purposes.
 
 .DESCRIPTION Allows you to bring a Git status to PowerShell prompt.
 Gracies to Mark Kembling
 https://markembling.info/2009/09/my-ideal-powershell-prompt-with-git-integration
 https://gist.github.com/markembling/180853
 Also thanks to git-prompt.sh creators
 https://github.com/git/git/blob/master/contrib/completion/git-prompt.sh
#>


$STATUS_VALUE     = "__status"

function Get-GitStatus{
param(
    [String]
    [PARAMETER(Position=0,HelpMessage = "Git Status value")]
    $Format = $STATUS_VALUE)

    $directory = $pwd.Path;

    if (!(Test-DirectoryIsUnderGit -DirectoryPath $directory)){
        return "";
    }

    $status = Get-GitRepoStatus -DirectoryPath $directory
    $status = $Format.Replace($STATUS_VALUE, $status)

    return $status
}

function Test-DirectoryIsUnderGit {
    param (
        [string] $DirectoryPath
    )

    if (Test-Path "$DirectoryPath/.git") {
        return $TRUE
    }

    $parentDirectory = (Get-Item .).parent
    while ($parentDirectory) {
        $gitDirectory = "$($parentDirectory.fullname)/.git"
        if (Test-Path $gitDirectory) {
            return $TRUE
        }

        $parentDirectory = $parentDirectory.parent
    }

    return $FALSE
}

function Get-GitRepoStatus {
    param (
        [string] $DirectoryPath
    )

    $result = Get-GitCurrentBranchName $DirectoryPath

    if (!$env:GIT_PS_SHOWDIRTYSTATE){
        return $result;
    }

    $result += Get-GitStageState $DirectoryPath
    $result += Get-GitBranchSyncStatus $DirectoryPath

    return $result
}

function Get-GitCurrentBranchName{
    return $(git describe --contains --all HEAD)
}

function Get-GitStageState {
    param (
        [string] $DirectoryPath
    )

    $state = "";

    if ($(git diff --name-only)){
        $state += "*";
    }

    if ($(git diff --name-only --staged)){
        $state += "+";
    }

    if (![string]::IsNullOrWhiteSpace($state)){
        return " $state"
    }

    return $state
}

function Get-GitBranchSyncStatus {
    param (
        [string] $DirectoryPath
    )

    $branchName = "HEAD"
    $upstreamName = "@{upstream}"

    $ahead = (git rev-list --left-only "$branchName...$upstreamName" | Measure-Object).Count
    $behind = (git rev-list --right-only "$branchName...$upstreamName" | Measure-Object).Count

    if ($ahead -gt 0){
        $syncState += "up$($ahead)"
    }

    if ($behind -gt 0){
        $syncState += "down$($behind)"
    }

    if (![string]::IsNullOrWhiteSpace($syncState)){
        return " $syncState"
    }

    return $syncState;
}