Showing preview only (374K chars total). Download the full file or copy to clipboard to get everything.
Repository: dahlbyk/posh-git
Branch: master
Commit: bbc5ac380018
Files: 52
Total size: 357.0 KB
Directory structure:
gitextract_xoqawrl5/
├── .editorconfig
├── .git-blame-ignore-revs
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ └── workflows/
│ ├── powershell.yml
│ └── pwsh.yml
├── .gitignore
├── .vscode/
│ ├── extensions.json
│ ├── launch.json
│ ├── settings.json
│ └── tasks.json
├── CHANGELOG.md
├── ISSUE_TEMPLATE.md
├── LICENSE.txt
├── PSScriptAnalyzerSettings.psd1
├── README.md
├── chocolatey/
│ ├── packAndLocalInstall.ps1
│ ├── poshgit.nuspec
│ ├── tests/
│ │ └── InstallChocolatey.Tests.ps1
│ └── tools/
│ ├── chocolateyInstall.ps1
│ └── chocolateyUninstall.ps1
├── install.ps1
├── profile.example.ps1
├── src/
│ ├── AnsiUtils.ps1
│ ├── CheckRequirements.ps1
│ ├── ConsoleMode.ps1
│ ├── GitParamTabExpansion.ps1
│ ├── GitPrompt.ps1
│ ├── GitTabExpansion.ps1
│ ├── GitUtils.ps1
│ ├── PoshGitTypes.ps1
│ ├── TortoiseGit.ps1
│ ├── Utils.ps1
│ ├── WindowTitle.ps1
│ ├── en-US/
│ │ └── about_posh-git.help.txt
│ ├── posh-git.psd1
│ └── posh-git.psm1
└── test/
├── Ansi.Tests.ps1
├── CheckRequirements.Tests.ps1
├── DefaultPrompt.Tests.ps1
├── Get-GitBranch.Tests.ps1
├── Get-GitDirectory.Tests.ps1
├── Get-GitStatus.Tests.ps1
├── GitParamTabExpansion.Tests.ps1
├── GitParamTabExpansionVsts.Tests.ps1
├── GitPrompt.Tests.ps1
├── GitProxyFunctionExpansion.Tests.ps1
├── ModuleManifest.Tests.ps1
├── Shared.ps1
├── TabExpansion.Tests.ps1
├── Utils.Tests.ps1
└── git-help.txt
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
# To use this file you must have EditorConfig installed for your editor.
# For Visual Studio Code, install the extension: "EditorConfig for VS Code"
# https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig
root = true
[*]
indent_style = space
indent_size = 4
insert_final_newline = true
[*.{ps1,psd1,psm1}]
trim_trailing_whitespace = true
================================================
FILE: .git-blame-ignore-revs
================================================
# Normalize line endings
4256c20d7fa3514651df10f4dbc38bcd8fa012e3
================================================
FILE: .gitattributes
================================================
# Enable LF normalization for all files
* text=auto
================================================
FILE: .github/FUNDING.yml
================================================
github: [dahlbyk, rkeithhill]
================================================
FILE: .github/workflows/powershell.yml
================================================
name: Windows PowerShell
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
strategy:
fail-fast: false
matrix:
os: ['windows-latest']
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- name: install dependencies
shell: powershell
run: |
"Git version: $(git --version)"
"PSVersion: $($PSVersionTable.PSVersion)"
"Host name: $($Host.Name)"
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
Install-Module Pester -MinimumVersion 5.0.0 -MaximumVersion 5.99.99 -Scope CurrentUser -Force
"Pester: $(Get-Module Pester | % Version)"
- name: run tests
shell: powershell
run: |
Import-Module Pester -PassThru
$ErrorActionPreference = 'Continue'
$res = Invoke-Pester -Path test -Output Detailed -PassThru -ErrorAction SilentlyContinue
if (!$res -or ($res.FailedCount -gt 0)) {
$Error | Format-List * -Force
exit 1
}
================================================
FILE: .github/workflows/pwsh.yml
================================================
name: PowerShell Core
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
strategy:
fail-fast: false
matrix:
os: ['windows-latest', 'macos-latest', 'ubuntu-latest']
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- name: install dependencies
shell: pwsh
run: |
"Git version: $(git --version)"
"PSVersion: $($PSVersionTable.PSVersion)"
"Host name: $($Host.Name)"
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
Install-Module Pester -MinimumVersion 5.0.0 -MaximumVersion 5.99.99 -Scope CurrentUser -Force
"Pester: $(Get-Module Pester | % Version)"
- name: run tests
shell: pwsh
run: |
Import-Module Pester -PassThru
$ErrorActionPreference = 'Continue'
$res = Invoke-Pester -Path test -Output Detailed -PassThru -ErrorAction SilentlyContinue
if (!$res -or ($res.FailedCount -gt 0)) {
$Error | Format-List * -Force
exit 1
}
================================================
FILE: .gitignore
================================================
VERSION
*.log
*.nupkg
obj
.history
================================================
FILE: .vscode/extensions.json
================================================
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"EditorConfig.EditorConfig",
"ms-vscode.PowerShell",
"DavidAnson.vscode-markdownlint"
]
}
================================================
FILE: .vscode/launch.json
================================================
{
"version": "0.2.0",
"configurations": [
{
"type": "PowerShell",
"request": "launch",
"name": "PowerShell Interactive Session",
"cwd": "${workspaceRoot}"
},
{
"type": "PowerShell",
"request": "launch",
"name": "PowerShell Pester Tests",
"script": "Invoke-Pester",
"args": [],
"cwd": "${workspaceRoot}/test"
},
{
"type": "PowerShell",
"request": "launch",
"name": "PowerShell Launch (current file)",
"script": "${file}",
"args": [],
"cwd": "${file}"
},
{
"type": "PowerShell",
"request": "attach",
"name": "PowerShell Attach to Host Process",
"processId": "${command:PickPSHostProcess}",
"runspaceId": 1
}
]
}
================================================
FILE: .vscode/settings.json
================================================
{
"editor.insertSpaces": true,
"editor.rulers": [
120
],
"editor.tabSize": 4,
"files.insertFinalNewline": true,
"files.trimTrailingWhitespace": true,
"powershell.codeFormatting.preset": "Stroustrup",
"powershell.scriptAnalysis.settingsPath": "PSScriptAnalyzerSettings.psd1",
"markdownlint.config": {
"MD013": false,
"MD024": false,
"MD029": false,
"MD033": {
"allowed_elements": [
"kbd"
]
},
"MD034": false,
"MD038": false
}
}
================================================
FILE: .vscode/tasks.json
================================================
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"windows": {
"options": {
"shell": {
"executable": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
"args": [ "-NoProfile", "-ExecutionPolicy", "Bypass", "-Command" ]
}
}
},
"linux": {
"options": {
"shell": {
"executable": "/usr/bin/pwsh",
"args": [ "-NoProfile", "-Command" ]
}
}
},
"osx": {
"options": {
"shell": {
"executable": "/usr/local/bin/pwsh",
"args": [ "-NoProfile", "-Command" ]
}
}
},
// Associate with test task runner
"tasks": [
{
"label": "Test",
"type": "shell",
"command": "Import-Module Pester -MinimumVersion 5.0.0; $c = [PesterConfiguration]::Default; $c.Run.Path = 'test'; $c.Output.Verbosity = 'Detailed'; Invoke-Pester -Configuration $c",
"group": {
"kind": "test",
"isDefault": true
},
"problemMatcher": [
"$pester"
]
},
{
"label": "TestCurrentFile",
"type": "shell",
"command": "Clear-Host; Import-Module Pester -MinimumVersion 5.0.0; $c = [PesterConfiguration]::Default; $c.Run.Path = '${file}'; $c.Output.Verbosity = 'Detailed'; Invoke-Pester -Configuration $c",
"group": {
"kind": "test",
"isDefault": false
},
"problemMatcher": [
"$pester"
]
}
]
}
================================================
FILE: CHANGELOG.md
================================================
# posh-git Release History
## 1.1.0 - March 31, 2022
### Added
- `Remove-PoshGitFromProfile`
([git-for-windows/build-extra#401](https://github.com/git-for-windows/build-extra/pull/401))
([PR #877](https://github.com/dahlbyk/posh-git/pull/877))
Thanks @dscho
### Fixed
- Fix branch status when cherry-picking, merging, reverting
([#818](https://github.com/dahlbyk/posh-git/issues/818))
([PR #828](https://github.com/dahlbyk/posh-git/pull/828))
([PR #894](https://github.com/dahlbyk/posh-git/pull/894))
Thanks @NihilityT
- Fix tab expansion for PowerShell aliases to `git.exe`
([#854](https://github.com/dahlbyk/posh-git/issues/854))
([PR #855](https://github.com/dahlbyk/posh-git/pull/855))
- Fix tab expansion for symbolic refs
([#867](https://github.com/dahlbyk/posh-git/issues/867))
([PR #868](https://github.com/dahlbyk/posh-git/pull/868))
Thanks @dmringo
- Fix status inside `.github` directories
([#873](https://github.com/dahlbyk/posh-git/issues/873))
([PR #874](https://github.com/dahlbyk/posh-git/pull/874))
([PR #893](https://github.com/dahlbyk/posh-git/pull/893))
Thanks @jethas-bennettjones
- Version warning no longer flags VFS for Git
([#860](https://github.com/dahlbyk/posh-git/issues/860))
([PR #884](https://github.com/dahlbyk/posh-git/pull/884))
Thanks @shmuelie
- Version warning no longer flags Git for Windows release candidates
([#845](https://github.com/dahlbyk/posh-git/issues/845))
([PR #885](https://github.com/dahlbyk/posh-git/pull/885))
Thanks @dscho
### Chores
- Migrated to GitHub Actions
([PR #878](https://github.com/dahlbyk/posh-git/pull/878))
Thanks @dscho
- Fixed Scoop install instructions
([PR #862](https://github.com/dahlbyk/posh-git/pull/862))
Thanks @cjstewart88
- Fix typo
([PR #887](https://github.com/dahlbyk/posh-git/pull/887))
Thanks @bennett1412
## 1.0.0 - March 10, 2021
- Released to PowerShell Gallery.
- Fate of Chocolatey to be determined.
## 1.0.0-beta5 - February 14, 2021
### Added
- Added --renormalize to the "git add" parameters for tab-completion.
([PR #791](https://github.com/dahlbyk/posh-git/pull/791))
Thanks @dannoe
- Pass PowerShell aliases down to posh-git TabExpansion autocomplete function
([#257](https://github.com/dahlbyk/posh-git/issues/257))
([PR #779](https://github.com/dahlbyk/posh-git/pull/779))
Thanks @csc027
- Autocomplete user-defined pretty formats
([#786](https://github.com/dahlbyk/posh-git/issues/786))
([PR #802](https://github.com/dahlbyk/posh-git/pull/802))
Thanks @rdnlsmith
- Add warning for cygwin version of git, which does not play nicely
([#771](https://github.com/dahlbyk/posh-git/issues/771))
([PR #807](https://github.com/dahlbyk/posh-git/pull/807))
- Add BeforePath and AfterPath settings
([#821](https://github.com/dahlbyk/posh-git/pull/821))
([PR #822](https://github.com/dahlbyk/posh-git/pull/822))
Thanks @breisfeld Brad Reisfeld
### Changed
- `$GitPromptSettings.DefaultPromptAbbreviateHomeDirectory` defaults to `$false` on Windows. When enabled, `~` is
always substituted for the user's home path. Before this change, when directly in your home dir, this setting would
result in the full path displayed in the prompt e.g. `C:\Users\Keith`. After this change, `~` will be displayed.
The new behavior is consistent with how the home path is displayed in prompts in other shells on Linux.
([#746](https://github.com/dahlbyk/posh-git/pull/746))
([PR #801](https://github.com/dahlbyk/posh-git/pull/801))
- Adds `--no-optional-locks` when invoking git to reduce conflicts with other tools.
([PR #774](https://github.com/dahlbyk/posh-git/pull/774))
Thanks @jessehouwing
### Fixed
- Put 'CACHE ERROR' in prompt when [GitStatusCache](https://github.com/cmarcusreid/git-status-cache) returns failure.
([PR #759](https://github.com/dahlbyk/posh-git/pull/759))
Thanks @cmarcusreid
- Honor EnableStashStatus when using cache
([#761](https://github.com/dahlbyk/posh-git/pull/761))
([PR #762](https://github.com/dahlbyk/posh-git/pull/762))
- Register-ArgumentCompleter based tab-expansion in beta4 doesn't work with PowerShell aliases to git,tgit,gitk.
([#769](https://github.com/dahlbyk/posh-git/issues/769))
([PR #770](https://github.com/dahlbyk/posh-git/pull/770))
- Module now works in (and is tested in) strict mode
([PR #783](https://github.com/dahlbyk/posh-git/pull/783))
- "git help --all" output breaks $GitTabSettings.AllCommands = $true.
([#788](https://github.com/dahlbyk/posh-git/issues/788))
([PR #790](https://github.com/dahlbyk/posh-git/pull/790))
Thanks @dannoe
- Fixed non-ascii git branch name garbled
([PR #796](https://github.com/dahlbyk/posh-git/pull/796))
Thanks @LittleboyHarry
- Fix tab completion of branches in different worktrees
([PR #805](https://github.com/dahlbyk/posh-git/pull/805))
Thanks @wallybh
- Using `DarkYellow` no longer results in extra `$Errors`
([PR #806](https://github.com/dahlbyk/posh-git/pull/806))
## 1.0.0-beta4 - March 14, 2020
### Added
- Branch name completion to the new `Remove-GitBranch` command.
([PR #678](https://github.com/dahlbyk/posh-git/pull/678))
([PR #705](https://github.com/dahlbyk/posh-git/pull/705))
- `$global:GitPromptValues` with the following properties to enable users to have access to the information necessary
to display error status in their prompt as well as debug their prompt customizations:
- `DollarQuestion`
- `IsAdmin`
- `LastExitCode`
- `LastPrompt`
([PR #684](https://github.com/dahlbyk/posh-git/pull/684))
- Added tab-completion for new `git restore` and `git switch` commands.
([#691](https://github.com/dahlbyk/posh-git/issues/691))
([PR #702](https://github.com/dahlbyk/posh-git/pull/702))
([PR #743](https://github.com/dahlbyk/posh-git/pull/743))
Thanks @pinkfloydx33 for the direction and motivation to add this.
- Added tab-completion for `git merge --allow-unrelated-histories`
([#632](https://github.com/dahlbyk/posh-git/issues/632))
([PR #633](https://github.com/dahlbyk/posh-git/pull/633))
- Abbreviate path from git root with new setting `DefaultPromptAbbreviateGitDirectory`
([#719](https://github.com/dahlbyk/posh-git/issues/719))
([PR #720](https://github.com/dahlbyk/posh-git/pull/720))
([PR #729](https://github.com/dahlbyk/posh-git/pull/729))
Thanks Philippe Elsass (@elsassph)
- Two new properties have been added to `$global:GitTabSettings`
- `EnableLogging` - default is `$false` but when set to `$true`, tab expansion functions log to a file.
- `LogPath` - the path to the log file that is appended to (created if necessary) when `EnableLogging` is `$true`.
### Changed
- Module parameter changed from a [switch] that forced the posh-git prompt to be used to a bools. The use of this
parameters during import is now simplified to: `Import-Module posh-git -Args 1`.
- Shortened up the Windows title text to work better with Windows Terminal tabs. Now only displays '32-bit' in 32-bit
PowerShell, otherwise assumption is you're running 64-bit. Also display only PowerShell major.minor version number.
([PR #707](https://github.com/dahlbyk/posh-git/pull/707))
- Switched from overriding `TabExpansion` function to using `Register-ArgumentCompleter` for tab-completion on
PowerShell >= 6.0. `posh-git` can be configured to use the old `TabExpansion` function on PowerShell >= 6.0 by
importing the module using the following arguments: `Import-Module posh-git -ArgumentList 0,1`
before importing `posh-git`.
([#609](https://github.com/dahlbyk/posh-git/pull/609))
([PR #711](https://github.com/dahlbyk/posh-git/pull/711))
Thanks Andrew Bradley (@cspotcode)
- ([#733](https://github.com/dahlbyk/posh-git/issues/733))
([PR #741](https://github.com/dahlbyk/posh-git/pull/741))
- Fix conflict with `TabExpansionPlusPlus` module's `Register-ArgumentCompleter` command.
([#715](https://github.com/dahlbyk/posh-git/issues/715))
([PR #714](https://github.com/dahlbyk/posh-git/pull/714))
Thanks Kris Borowinski (@kborowinski)
- Update Ubuntu build system from 14.04 to 16.04
([PR #677](https://github.com/dahlbyk/posh-git/pull/677))
Thanks @ExE-Boss
- `$GitPromptSettings.BeforeIndex` is always displayed even if there is nothing in the index. The intent of
this separator setting is to provide a separator between the branch name / branch status and the following section of
index/working/summary/stash indicators.
([PR #723](https://github.com/dahlbyk/posh-git/pull/723))
- posh-git no longers sets missing `HOME` environment variable.
([#718](https://github.com/dahlbyk/posh-git/issues/718))
([PR #722](https://github.com/dahlbyk/posh-git/pull/722))
- `Get-GitStatus -Force` now also overrides `$GitPromptSettings.EnableFileStatus` as well as
`$GitPromptSettings.EnablePromptStatus`.
([#657](https://github.com/dahlbyk/posh-git/issues/657))
([PR #721](https://github.com/dahlbyk/posh-git/pull/721))
### Fixed
- Remove `.exe` suffix from PowerTab integration to enable PowerTab integration to work with `git`, `git.cmd` or `git.exe`
([#606](https://github.com/dahlbyk/posh-git/pull/606/))
- `BranchBehindAndAheadDisplay` minimal/compact bug
([#670](https://github.com/dahlbyk/posh-git/issues/670))
([PR #671](https://github.com/dahlbyk/posh-git/pull/671))
- Fix(status): Only reset changed colors
([PR #673](https://github.com/dahlbyk/posh-git/pull/673))
Thanks @ExE-Boss
- Fix rebase step count
([PR #674](https://github.com/dahlbyk/posh-git/pull/674))
Thanks Saša Kajfeš (@skajfes)
- Fix typo in cherry-pick parameters - `´continue`
([PR #675](https://github.com/dahlbyk/posh-git/pull/675))
Thanks @KexyBiscuit
- Prompt error in remote PSSession
([#708](https://github.com/dahlbyk/posh-git/issues/708))
([PR #727](https://github.com/dahlbyk/posh-git/pull/727)
- Typos
- ([PR #665](https://github.com/dahlbyk/posh-git/pull/665))
Thanks @SJMakin
- ([PR #716](https://github.com/dahlbyk/posh-git/pull/716))
Thanks @theaquamarine
## 1.0.0-beta3 - March 10, 2019
### Removed
- BREAKING: Removed SSH agent functionality from `posh-git` and put into another module focused solely on
Git SSH support. See [posh-sshell](https://github.com/dahlbyk/posh-sshell).
([#338](https://github.com/dahlbyk/posh-git/issues/338))
([PR #585](https://github.com/dahlbyk/posh-git/pull/585))
- BREAKING: Removed `PoshGitTextSpan.CustomAnsi` property - now just put your custom VT sequences in the
`PoshGitTextSpan.Text` property. Be sure to terminate your VT sequences with `"$([char]27)[0m"` or
``` "`e[0m" ``` on PowerShell Core.
([PR #616](https://github.com/dahlbyk/posh-git/pull/616))
### Added
- Added `Remove-GitBranch` command. Partially addresses #79.
These commands currently only delete local branches.
([#79](https://github.com/dahlbyk/posh-git/issues/79))
([PR #663](https://github.com/dahlbyk/posh-git/pull/663))
- Added support for vsts-cli Git integration.
([#549](https://github.com/dahlbyk/posh-git/issues/549))
([PR #581](https://github.com/dahlbyk/posh-git/pull/581))
Thanks David Gardiner (@flcdrg)
- Enhance prompt function to show username/hostname in SSH connection. Adds `Get-PromptConnectionInfo` command.
([#591](https://github.com/dahlbyk/posh-git/issues/591))
([PR #595](https://github.com/dahlbyk/posh-git/pull/595))
- Show Rebase Progress (plus `|REVERTING`).
([#102](https://github.com/dahlbyk/posh-git/issues/102))
([PR #599](https://github.com/dahlbyk/posh-git/pull/599))
- Set `$Env:COLUMNS` on prompt if necessary.
([PR #607](https://github.com/dahlbyk/posh-git/pull/607))
- Tab-completion for `git log --stat`, `git log --patch` and `git diff --staged`.
([PR #620](https://github.com/dahlbyk/posh-git/pull/620))
Thanks Vasily Korytov (@chillum)
- Tab-completion for `git update-git-for-windows` on Windows Git >= 2.16.2.
([PR #642](https://github.com/dahlbyk/posh-git/pull/642))
- `New-GitPromptSettings` to provide an easy way to create a `PoshGitPromptSettings` object which can be used to
reset to the default settings.
([PR #659](https://github.com/dahlbyk/posh-git/pull/659))
### Changed
- Eliminate traiing `=` on the tab-completion of `--force-with-lease=`.
([PR #622](https://github.com/dahlbyk/posh-git/pull/622))
Thanks Chuck Lu (@chucklu)
- Expand `PathStatusSeparator` string when composing prompt. This allows you to use string interpolation in the
`$GitPromptSettings.PathStatusSeparator.Text` setting.
([PR #630](https://github.com/dahlbyk/posh-git/pull/630))
Thanks Jason Shirk (@lzybkr)
### Fixed
- `WindowTitle` set by user overwritten by module. No longer updates Window title if `WindowTitle` setting set to `$null`.
([#594](https://github.com/dahlbyk/posh-git/issues/594))
([PR #597](https://github.com/dahlbyk/posh-git/pull/597))
- `Write-VcsStatus` behaving differently. When `AnsiConsole -eq $false`, `Write-VcsStatus` must not emit any strings.
([#612](https://github.com/dahlbyk/posh-git/issues/612))
([PR #617](https://github.com/dahlbyk/posh-git/pull/617))
- On Windows PowerShell, defer `Add-Type` until `Set-ConsoleMode` executed. This improves module load time.
([#637](https://github.com/dahlbyk/posh-git/issues/637))
([PR #638](https://github.com/dahlbyk/posh-git/pull/638))
([PR #662](https://github.com/dahlbyk/posh-git/pull/662))
- How do you manually install this? Added manual instructions for git clone of posh-git to README.md.
([#648](https://github.com/dahlbyk/posh-git/issues/648))
([PR #649](https://github.com/dahlbyk/posh-git/pull/649))
Thanks Kyle Spier-Swenson (@MrStonedOne)
## 1.0.0-beta2 - May 13, 2018
The 1.0.0 release is targeted specifically at Windows PowerShell 5.x and (cross-platform) PowerShell Core 6.x, both of
which support classes, enabling the enhanced structure of `$GitPromptSettings`,
and writing prompt strings using [ANSI escape sequences][ansi-esc-code] /
[Console Virtual Terminal Sequences][console-vt-seq] (supported since Windows 10 version 1511).
Consequently, this release introduces BREAKING changes with 0.x.
If you are still on Windows PowerShell 2.0, 3.0 or 4.0, please continue to use the 0.x version of posh-git.
### Changed
- Renamed `$GitPromptSettings` values
- `BeforeText` to `BeforeStatus`
- `DelimText` to `DelimStatus`
- `AfterText` to `AfterStatus`
- `BeforeIndexText` to `BeforeIndex`
- `BeforeStashText` to `BeforeStash`
- `AfterStashText` to `AfterStash`
- Split `$GirPromptSettings.DefaultPromptSuffix` and `$GitPromptSettings.DefaultPromptDebugSuffix` into:
1. `DefaultPromptBeforeSuffix` (`''`)
2. `DefaultPromptDebug` (`' [DBG]:'`), which is rendered if a debugger is attached
3. `DefaultPromptSuffix` (`'$(">" * ($nestedPromptLevel + 1)) '`), which is rendered last
(or returned from `prompt`, for terminals that don't support escape sequences)
- Renamed `$GitPromptSettings.EnableWindowTitle` to `$GitPromptSettings.WindowTitle` with significant improvements:
- `$Host.UI.RawUI.WindowTitle` is now set on every `prompt`, not just when inside a Git repo.
- To prevent setting `WindowTitle`, set `$GitPromptSettigs.WindowTitle` to `$null`.
- The `WindowTitle` update has been moved from the `Write-GitStatus` command to the built-in `prompt` function.
- `$GitPromptSettings.WindowTitle` is now fully customizable:
- As a `string`, it will be processed with [`ExpandString`][invokecommand-expandstring].
- As a `ScriptBlock` (default), it will be executed with two parameters: `$GitStatus` and `$IsAdmin`.
- When a color setting is specified by a `string` (color name), it is parsed as an HTML color
(on platforms that support `System.Drawing.ColorTranslator`) before being parsed as a `ConsoleColor`.
To force using `ConsoleColors`, use static member syntax (e.g. `[ConsoleColor]::Cyan`).
([PR #536](https://github.com/dahlbyk/posh-git/pull/536))
- `PoshGitVcsPrompt` errors now show details if `$GitPromptSettings.Debug`
([PR #560](https://github.com/dahlbyk/posh-git/pull/560))
### Added
- New command `Get-PromptPath` which formats the path displayed in the prompt and window title.
This command honors `$GitPromptSettings.DefaultPromptAbbreviateHomeDirectory`.
- A path exactly matching `$HOME` is now shown in full, rather than abbreviated to `~`
([PR #567](https://github.com/dahlbyk/posh-git/pull/567))
- New `$GitPromptSettings` values (default):
- `PathStatusSeparator` (` `)
- `DefaultPromptPath` (`'$(Get-PromptPath)'`)
- `DefaultPromptWriteStatusFirst` (`$false`)
- `DefaultPromptTimingFormat` (`' {0}ms'`)
- `RepoName` property has been addded to the `$global:GitStatus` object returned by `Get-GitStatus`.
- Added `$GitPromptSettings.UntrackedFilesMode`;
accepted values are `$null` (inherit `status.showUntrackedFiles`), "all", "no", and "normal"
([#556](https://github.com/dahlbyk/posh-git/pull/556))
([PR #557](https://github.com/dahlbyk/posh-git/pull/557))
Thanks David Snedecor (@TheSned)
- Exported `Expand-GitCommand` for use with custom tab expansion
([#562](https://github.com/dahlbyk/posh-git/pull/562))
([PR #563](https://github.com/dahlbyk/posh-git/pull/563))
### Fixed
- Fixed `$GitPromptSettings.EnablePromptStatus` should not affect `Get-GitStatus` by adding `-Force` parameter.
([#475](https://github.com/dahlbyk/posh-git/issues/475))
([PR #535](https://github.com/dahlbyk/posh-git/pull/535))
- Fixed PowerShell Core bug where we were using `Get-Content -Encoding Byte` when processing profile scripts during
Chocolatey install/uninstall. That encoding doesn't exist in PowerShell Core.
Switched to `Get-Content -AsByteStream` on PowerShell Core.
([PR #532](https://github.com/dahlbyk/posh-git/pull/532))
- Fixed ANSI rendering bug: when both `ForegroundColor` and `BackgroundColor` colors are `$null` (default),
we were emitting an unnecessary terminating escape sequence `"$([char]27)[0m"`.
([PR #532](https://github.com/dahlbyk/posh-git/pull/532))
- Fixed issue where setting `ForegroundColor` or `BackgroundColor` to 0 (Black) rendered the default color instead.
- Updated Git subcommand lists
([#561](https://github.com/dahlbyk/posh-git/issues/561))
([PR #571](https://github.com/dahlbyk/posh-git/pull/571))
## 1.0.0-beta1 - January 10, 2018
### Removed
- Drop support for PowerShell 2.0
([#163](https://github.com/dahlbyk/posh-git/issues/163))
([PR #427](https://github.com/dahlbyk/posh-git/pull/427))
- Drop support for PowerShell 3.0 and 4.0
([#328](https://github.com/dahlbyk/posh-git/issues/328))
([PR #513](https://github.com/dahlbyk/posh-git/pull/513))
- Remove public `Enable-GitColors`, `Get-AliasPattern`, `Get-GitBranch` and `Invoke-NullCoalescing` and its `??` alias
([#93](https://github.com/dahlbyk/posh-git/issues/93))
([PR #427](https://github.com/dahlbyk/posh-git/pull/427))
### Changed
- Changed the `$GitPromptSettings` hashtable to a stongly typed object.
Here is one example of the impact of this change:
```powershell
$GitPromptSettings.LocalWorkingStatusSymbol = '#'
$GitPromptSettings.LocalWorkingStatusForegroundColor = [ConsoleColor]::DarkRed
```
Changes to:
```powershell
$GitPromptSettings.LocalWorkingStatusSymbol.Text = '#'
$GitPromptSettings.LocalWorkingStatusSymbol.ForegroundColor = [ConsoleColor]::DarkRed
```
- Changed `Write-VcsStatus`, `Write-GitStatus` and `Write-Prompt` to return a string rather than write to host when
the host supports ANSI escape sequences.
### Added
- Implement support for ANSI escape sequences for colored output - support System.ConsoleColor, System.Drawing.HtmlColor
(if available on the platform) and 24-bit color. NOTE: this is a breaking change since `Write-VcsStatus`,
`Write-GitStatus` and `Write-Prompt` will now return a string rather than write to the host when the host supports
ANSI escape sequences.
([#304](https://github.com/dahlbyk/posh-git/pull/304))
([#447](https://github.com/dahlbyk/posh-git/pull/447))
([#455](https://github.com/dahlbyk/posh-git/pull/455))
- $GitPromptSettings is now a strongly typed object using PS classes
([#344](https://github.com/dahlbyk/posh-git/issues/344))
([PR #513](https://github.com/dahlbyk/posh-git/pull/513))
- Provide more granular commands than just `Write-GitStatus`.
([#345](https://github.com/dahlbyk/posh-git/issues/345))
([PR #513](https://github.com/dahlbyk/posh-git/pull/513))
We now export the commands that `Write-GitStatus` uses internally which are:
- Write-GitBranchName
- Write-GitBranchStatus
- Write-GitIndexStatus
- Write-GitStashCount
- Write-GitWorkingDirStatus
- Write-GitWorkingDirStatusSummary
### Fixed
- Fixed Get-AuthenticodeSignature not on PS Core.
([PR #487](https://github.com/dahlbyk/posh-git/pull/487))
- Provide DefaultPromptPrefixColor and DefaultPromptSuffixColor options
([#474](https://github.com/dahlbyk/posh-git/issues/474))
([PR #520](https://github.com/dahlbyk/posh-git/pull/520))
- Fixed posh-git prompt makes PowerShell transcripts less readable
([#282](https://github.com/dahlbyk/posh-git/issues/282))
([PR #447](https://github.com/dahlbyk/posh-git/pull/447))
## 0.7.3 - April 19, 2018
- posh-git now exports the variable `$GitPromptScriptBlock` which contains the code for the default prompt.
([#501](https://github.com/dahlbyk/posh-git/issues/501))
([PR #513](https://github.com/dahlbyk/posh-git/pull/513))
If you need to execute your own logic in your own prompt function but still want to display the default posh-git
prompt, you can execute this scriptblock from your prompt function e.g.:
```powershell
# profile.ps1
function prompt {
Set-NodeVersion
&$GitPromptScriptBlock
}
Import-Module posh-git
```
- Fixed 'Write-Prompt' to be able use Black as foreground color.
([#470](https://github.com/dahlbyk/posh-git/pull/470))
([PR #468](https://github.com/dahlbyk/posh-git/pull/468))
Thanks Vladimir Poleh (@vladimir-poleh)
- Pass "git.exe" instead of "git" to Get-Command.
([PR #478](https://github.com/dahlbyk/posh-git/pull/478))
([PR #479](https://github.com/dahlbyk/posh-git/pull/479))
Thanks Mike Sigsworth (@mikesigs)
- Squash ssh agent warnings if `-Quiet`.
([PR #484](https://github.com/dahlbyk/posh-git/pull/484))
Thanks Refael Ackermann (@refack)
- Fixed directory names that contain [brackets] cause GitPrompt to fail.
([PR #502](https://github.com/dahlbyk/posh-git/pull/502))
Thanks Duncan Smart (@duncansmart)
- Added `Add-PoshGitToProfile -AllUsers` support
([PR #504](https://github.com/dahlbyk/posh-git/pull/504))
- Fixed duplicated branch completion for git checkout
([#505](https://github.com/dahlbyk/posh-git/issues/505))
([PR #506](https://github.com/dahlbyk/posh-git/pull/506))
([PR #512](https://github.com/dahlbyk/posh-git/pull/512))
Thanks Christoph Bergmeister (@bergmeister)
- Fixed PSScriptAnalyzer warnings in the source
([PR #509](https://github.com/dahlbyk/posh-git/pull/509))
Thanks Christoph Bergmeister (@bergmeister)
- Fixed errors added to $Error collection by `Get-GitStatus` command
([#500](https://github.com/dahlbyk/posh-git/issues/500))
([PR #514](https://github.com/dahlbyk/posh-git/pull/514))
- Added custom path rendering in prompt
([#469](https://github.com/dahlbyk/posh-git/issues/469))
([PR #520](https://github.com/dahlbyk/posh-git/pull/520))
- Clean up wording for work dir local status in help file
([PR #516](https://github.com/dahlbyk/posh-git/pull/516))
- Added `$GitPromptSettings.AdminTitlePrefixText` (default: `'Administrator: '`)
([#537](https://github.com/dahlbyk/posh-git/pull/537))
([PR #538](https://github.com/dahlbyk/posh-git/pull/538))
Thanks Eric Jorgensen (@nebosite)
- Added `$GitPromptSettings.UntrackedFilesMode`;
accepted values are `$null` (inherit `status.showUntrackedFiles`), "all", "no", and "normal"
([#556](https://github.com/dahlbyk/posh-git/pull/556))
([PR #557](https://github.com/dahlbyk/posh-git/pull/557))
Thanks David Snedecor (@TheSned)
- `PoshGitVcsPrompt` errors now show details if `$GitPromptSettings.Debug`
([PR #560](https://github.com/dahlbyk/posh-git/pull/560))
- Exported `Expand-GitCommand` for use with custom tab expansion
([#562](https://github.com/dahlbyk/posh-git/pull/562))
([PR #563](https://github.com/dahlbyk/posh-git/pull/563))
- Add code coverage to Coveralls.io
([#416](https://github.com/dahlbyk/posh-git/pull/416))
([PR #461](https://github.com/dahlbyk/posh-git/pull/461))
Thanks Jan De Dobbeleer (@JanJoris)
## 0.7.1 - March 14, 2017
- Fixed tab completion issues with duplicate aliases
([#164](https://github.com/dahlbyk/posh-git/issues/164))
([#421](https://github.com/dahlbyk/posh-git/issues/421))
([PR #422](https://github.com/dahlbyk/posh-git/pull/422))
- `Add-PoshGitToProfile` will no longer modify a signed `$PROFILE` script; it also learned `-Confirm`
([PR #428](https://github.com/dahlbyk/posh-git/pull/428))
- Overwrite pre-0.7 posh-git prompt on import
([PR #425](https://github.com/dahlbyk/posh-git/pull/425))
- Fix Chocolatey deprecation warning with dependency on 0.9.10
([PR #426](https://github.com/dahlbyk/posh-git/pull/426))
- Don't rerun Pageant if there are no keys to add
([PR #441](https://github.com/dahlbyk/posh-git/pull/441))
- Improve (and hide for Chocolatey) profile.example.ps1 deprecation messaging
([#442](https://github.com/dahlbyk/posh-git/issues/442))
([PR #444](https://github.com/dahlbyk/posh-git/pull/444))
- Quote tab completion for remote names containing special characters
([PR #446](https://github.com/dahlbyk/posh-git/pull/446))
- Fix signed $PROFILE detection for PowerShell v2
([#448](https://github.com/dahlbyk/posh-git/issues/448))
([PR #450](https://github.com/dahlbyk/posh-git/pull/450))
- Create $PROFILE parent directory if missing
([PR #449](https://github.com/dahlbyk/posh-git/pull/449))
([PR #452](https://github.com/dahlbyk/posh-git/pull/452))
- Add -verbose parameter to install.ps1
([PR #451](https://github.com/dahlbyk/posh-git/pull/451))
- Write-Prompt now correctly handles $null color parameters;
the prompt now also uses DefaultForegroundColor when appropriate
([PR #454](https://github.com/dahlbyk/posh-git/pull/454))
- Add error handling to Write-GitStatus
([PR #170](https://github.com/dahlbyk/posh-git/pull/170))
([PR #453](https://github.com/dahlbyk/posh-git/pull/453))
## 0.7.0 - February 14, 2017
This release has focused on improving the "getting started" experience by adding an `Add-PoshGitToProfile` command that
modifies the user's PowerShell profile script to import the posh-git module whenever PowerShell starts.
When posh-git is imported, it will automatically install a posh-git prompt that displays Git status summary information.
Work was also done to improve performance of `Get-GitStatus` when inside large Git repositories.
Work was begun to eliminate some obvious crashes on PowerShell on .NET Core but more work remains to be done.
- Performance of `Get-GitStatus` on large repos has been improved
([PR #319](https://github.com/dahlbyk/posh-git/pull/319))
- Fix prompt and tab completion with non-ASCII characters
([#64](https://github.com/dahlbyk/posh-git/issues/64))
([PR #223](https://github.com/dahlbyk/posh-git/pull/223))
([PR #359](https://github.com/dahlbyk/posh-git/pull/359))
([#374](https://github.com/dahlbyk/posh-git/issues/374))
([#389](https://github.com/dahlbyk/posh-git/issues/389))
([PR #397](https://github.com/dahlbyk/posh-git/pull/397))
([PR #403](https://github.com/dahlbyk/posh-git/pull/403))
- Fix incorrect tab expansion for `git push --option <remote>`
([#234](https://github.com/dahlbyk/posh-git/issues/234))
([PR #379](https://github.com/dahlbyk/posh-git/pull/379))
- Fix support for bare repository
([#291](https://github.com/dahlbyk/posh-git/issues/291))
([PR #370](https://github.com/dahlbyk/posh-git/pull/370))
- Fix syntax error on setenv calls
([PR #297](https://github.com/dahlbyk/posh-git/pull/297))
- Fix temp path issue with ~ in 8.3 filenames
([#298](https://github.com/dahlbyk/posh-git/issues/298))
([PR #299](https://github.com/dahlbyk/posh-git/pull/299))
- Fix problem on open source PowerShell, missing `WindowsPrincipal`/`WindowsIdentity`
([#301](https://github.com/dahlbyk/posh-git/issues/301))
([PR #312](https://github.com/dahlbyk/posh-git/pull/312))
- Fix/simplify Chocolatey install and add uninstall
([#358](https://github.com/dahlbyk/posh-git/issues/358))
- Remove invalid branch from tab expansion when `HEAD` is detached
([PR #367](https://github.com/dahlbyk/posh-git/pull/367))
- Fix PowerShell Core error on `EnvironmentVariableTarget`
([#317](https://github.com/dahlbyk/posh-git/issues/317))
([#369](https://github.com/dahlbyk/posh-git/issues/369))
([PR #318](https://github.com/dahlbyk/posh-git/pull/318))
- Fewer errors generated in global `$Error` collection
([PR #370](https://github.com/dahlbyk/posh-git/pull/370))
- Remove error thrown by `git symbolic-ref` and `git describe`
([PR #307](https://github.com/dahlbyk/posh-git/pull/307))
- Export command Write-VcsStatus to improve module auto-loading
([PR #284](https://github.com/dahlbyk/posh-git/pull/284))
- Update module import so that it sets the prompt function *iff* the user does not have a customized prompt function
([#217](https://github.com/dahlbyk/posh-git/issues/217))
([PR #349](https://github.com/dahlbyk/posh-git/pull/349))
- Update profile.example.ps1 to remove prompt function and tweak how module is imported
([PR #349](https://github.com/dahlbyk/posh-git/pull/349))
- Add tab completion for AVH git-flow commands
([PR #231](https://github.com/dahlbyk/posh-git/pull/231))
- Add new commmand Add-PoshGitToProfile
([PR #361](https://github.com/dahlbyk/posh-git/pull/361))
- Add about_posh-git help topic
([PR #298](https://github.com/dahlbyk/posh-git/pull/287))
- Add new settings for default posh-git prompt:
- `DefaultPromptPrefix`
([PR #393](https://github.com/dahlbyk/posh-git/pull/393))
- `DefaultPromptSuffix` (default includes nested prompt level,
([PR #363](https://github.com/dahlbyk/posh-git/pull/363)))
- `DefaultPromptDebugSuffix`
- `DefaultPromptEnableTiming`
([PR #371](https://github.com/dahlbyk/posh-git/pull/371))
- `DefaultPromptAbbreviateHomeDirectory`
([#386](https://github.com/dahlbyk/posh-git/issues/386))
- Add ahead/behind count to prompt
([PR #256](https://github.com/dahlbyk/posh-git/pull/256))
- Add `BranchBehindAndAheadDisplay` setting to control count display (Full (default), Compact, Minimal)
- Fix empty `Git-SshPath` issue
([PR #268](https://github.com/dahlbyk/posh-git/pull/268))
- Add new settings for prompt status summary text: `FileAddedText`, `FileModifiedText`, `FileRemovedText` and `FileConflictText`
([PR #277](https://github.com/dahlbyk/posh-git/pull/277))
- Add tags to 'push' tab-completion
([PR #286](https://github.com/dahlbyk/posh-git/pull/286))
- Add new branch status to indicate upstream is gone
([PR #326](https://github.com/dahlbyk/posh-git/pull/326))
- Add tab completion support for shorthand force-push syntax (`git push <remote> +<tab>`)
([#173](https://github.com/dahlbyk/posh-git/issues/173))
([PR #174](https://github.com/dahlbyk/posh-git/pull/174))
([PR #343](https://github.com/dahlbyk/posh-git/pull/343))
- Add tab completion of unique remote branch names for `git checkout <tab>`
([#177](https://github.com/dahlbyk/posh-git/issues/177))
([PR #251](https://github.com/dahlbyk/posh-git/pull/251))
([PR #352](https://github.com/dahlbyk/posh-git/pull/352))
- Add `git worktree` tab completion
([PR #366](https://github.com/dahlbyk/posh-git/pull/366))
- Add alias support for TortoiseGit commands
([PR #394](https://github.com/dahlbyk/posh-git/pull/394))
- Add support for tab-completion of Git parameters, long and short
([PR #395](https://github.com/dahlbyk/posh-git/pull/395))
- Switch `$GitPromptSettings` type from `PSObject` to `PSCustomObject`. On PowerShell v5 and higher, this preserves the definition order of properties in `$GitPromptSettings` making it easier to find properties.
- Fix prompt status in worktree
([#407](https://github.com/dahlbyk/posh-git/issues/407))
([PR #408](https://github.com/dahlbyk/posh-git/pull/408))
- Quote tab completion for items containing special characters
([#293](https://github.com/dahlbyk/posh-git/issues/293))
([PR #413](https://github.com/dahlbyk/posh-git/pull/413))
## Thank You
Thank you to the following folks who contributed their time and scripting skills to make posh-git better:
- Keith Hill (@rkeithhill)
- [Pester test infrastructure](https://github.com/dahlbyk/posh-git/commits/master/test?author=rkeithhill)
- Triage of open issues and PRs
- Many README and help improvements
- Many of the fixes enumerated above
- Marcus Reid (@cmarcusreid)
- Use [GitStatusCache](https://github.com/cmarcusreid/git-status-cache) when it's installed
([PR #208](https://github.com/dahlbyk/posh-git/pull/208))
- Report UpstreamGone from GitStatusCache response
([PR #372](https://github.com/dahlbyk/posh-git/pull/372))
- Jason Shirk (@lzybkr)
- Speed up `Get-GitStatus`
([PR #319](https://github.com/dahlbyk/posh-git/pull/319))
- Use `PSCustomObject` case for sorted output of `$GitPromptSettings`
([PR #382](https://github.com/dahlbyk/posh-git/pull/382))
- Ralf Müller (@seamlessintegrations)
- Add support for tab-completion of Git parameters
([PR #395](https://github.com/dahlbyk/posh-git/pull/395))
- Aksel Kvitberg (@Flueworks)
- Add Worktree tab completion
([PR #366](https://github.com/dahlbyk/posh-git/pull/366))
- Eric Amodio (@eamodio)
- Add aliasing support for TortoiseGit commands
([PR #394](https://github.com/dahlbyk/posh-git/pull/394))
- Kevin Shaw (@shawmanz32na)
- Add DefaultPromptAbbreviateHomeDirectory setting
([PR #387](https://github.com/dahlbyk/posh-git/pull/387))
- KanjiBates (@KanjiBates)
- Fix link to git-scm.com in README.md
([PR #396](https://github.com/dahlbyk/posh-git/pull/396))
- Joel Rowley (@hjoelr)
- Fix syntax error on setenv calls
([PR #297](https://github.com/dahlbyk/posh-git/pull/297))
- Hui Sun (@JimAmuro)
- Fix [#298](https://github.com/dahlbyk/posh-git/issues/298) remove-item error after startup
([PR #299](https://github.com/dahlbyk/posh-git/pull/299))
- Josh (@joshgo)
- Add tags to 'push' tab-completion
([PR #286](https://github.com/dahlbyk/posh-git/pull/286))
- Rebecca Turner (@9999years)
- Add new settings for prompt FileAddedText, FileModifiedText, FileRemovedText and FileConflictText
([PR #277](https://github.com/dahlbyk/posh-git/pull/277))
- Jack (@Jackbennett)
- Export command Write-VcsStatus to improve module auto-loading
([PR #284](https://github.com/dahlbyk/posh-git/pull/284))
- Brendan Forster (@shiftkey)
- Improvements to README.md
([PR #273](https://github.com/dahlbyk/posh-git/pull/273))
([PR #274](https://github.com/dahlbyk/posh-git/pull/274))
- Paul Marston (@paulmarsy)
- Update README.md to reflect recent changes to the Git prompt
([PR #221](https://github.com/dahlbyk/posh-git/pull/221))
- Add error handling to Write-VcsStatus
([PR #170](https://github.com/dahlbyk/posh-git/pull/170))
- INOMATA Kentaro (@matarillo)
- Fix branch names using UTF8 characters do not display correctly
([PR #223](https://github.com/dahlbyk/posh-git/pull/223))
- Luis Vita (@Ivita)
- Fix typo in git commit parameter --amend in tab exansion
([PR #405](https://github.com/dahlbyk/posh-git/pull/405))
- Skeept (@skeept)
- Fix debug prompt breaking posh-git prompt on PowerShell v4
([PR #406](https://github.com/dahlbyk/posh-git/pull/406))
- @theaquamarine
- Fix [#249](https://github.com/dahlbyk/posh-git/issues/249), handling of multiple Pageant keys
([PR #255](https://github.com/dahlbyk/posh-git/pull/255))
- Jan De Dobbeleer (@JanJoris)
- Remove errors thrown by `git symbolic-ref` and `git describe`
([PR #307](https://github.com/dahlbyk/posh-git/pull/307))
- Dan Smith (@dozius)
- Add tab completion for AVH git-flow commands
([PR #231](https://github.com/dahlbyk/posh-git/pull/231))
- @drawfour
- Add ahead/behind count to prompt
([PR #256](https://github.com/dahlbyk/posh-git/pull/256))
- Dan Turner (@dan-turner)
- Add tab completion support for shorthand force-push syntax (`git push <remote> +<tab>`)
([PR #174](https://github.com/dahlbyk/posh-git/pull/174))
- Mark Hillebrand (@mah)
- Add tab completion of unique remote branch names for `git checkout <tab>`
([PR #251](https://github.com/dahlbyk/posh-git/pull/251))
- Jeff Yates (@somewhatabstract)
- Don't rerun Pageant if there are no keys to add
([PR #441](https://github.com/dahlbyk/posh-git/pull/441))
- Tolga Balci (@tolgabalci)
- Create $PROFILE parent directory if missing
([PR #449](https://github.com/dahlbyk/posh-git/pull/449))
- Add -verbose parameter to install.ps1
([PR #451](https://github.com/dahlbyk/posh-git/pull/451))
[ansi-esc-code]: https://en.wikipedia.org/wiki/ANSI_escape_code
[console-vt-seq]: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
[invokecommand-expandstring]: https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.commandinvocationintrinsics.expandstring
================================================
FILE: ISSUE_TEMPLATE.md
================================================
<!--
Check the FAQ https://github.com/dahlbyk/posh-git/wiki/FAQ to see if your issue is addressed there.
If not, PLEASE fill in the following details so that we can help you!
-->
### System Details
- posh-git version/path:
- PowerShell version:
- Git version:
- Operating system name and version:
<!--
To retrieve the system details, paste the following line into PowerShell, press Enter
and then copy/paste the resulting output above.
"- posh-git version/path: $($m = Get-Module posh-git; '{0} {1} {2}' -f $m.Version,$m.PrivateData.PSData.Prerelease,$m.ModuleBase.Replace($HOME,'~'))`n- PowerShell version: $($PSVersionTable.PSVersion)`n- $(
git --version)`n- OS: $([System.Environment]::OSVersion)"
-->
### Issue Description
I am experiencing a problem with...
================================================
FILE: LICENSE.txt
================================================
Copyright (c) 2010-2018 Keith Dahlby, Keith Hill, and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: PSScriptAnalyzerSettings.psd1
================================================
@{
# Use Severity when you want to limit the generated diagnostic records to a
# subset of: Error, Warning and Information.
# Uncomment the following line if you only want Errors and Warnings but
# not Information diagnostic records.
Severity = @('Error','Warning')
# Use IncludeRules when you want to run only a subset of the default rule set.
#IncludeRules = @('PSAvoidDefaultValueSwitchParameter',
# 'PSMissingModuleManifestField',
# 'PSReservedCmdletChar',
# 'PSReservedParams',
# 'PSShouldProcess',
# 'PSUseApprovedVerbs',
# 'PSUseDeclaredVarsMoreThanAssigments')
# Use ExcludeRules when you want to run most of the default set of rules except
# for a few rules you wish to "exclude". Note: if a rule is in both IncludeRules
# and ExcludeRules, the rule will be excluded.
ExcludeRules = @('PSAvoidUsingWriteHost', 'PSAvoidGlobalVars', 'PSAvoidUsingInvokeExpression', 'PSReviewUnusedParameter')
# You can use the following entry to supply parameters to rules that take parameters.
# For instance, the PSAvoidUsingCmdletAliases rule takes a whitelist for aliases you
# want to allow.
Rules = @{
# Do not flag 'cd' alias.
# PSAvoidUsingCmdletAliases = @{Whitelist = @('cd')}
# Check if your script uses cmdlets that are compatible on PowerShell Core, version 6.0.0-alpha, on Linux.
# PSUseCompatibleCmdlets = @{Compatibility = @("core-6.0.0-alpha-linux")}
}
}
================================================
FILE: README.md
================================================
# posh-git
[![Join the chat at https://gitter.im/dahlbyk/posh-git][gitter-img]][gitter]
[![PowerShell Gallery][psgallery-img]][psgallery-site]
[![posh-git on Chocolatey][choco-img]][choco-site]
Table of contents:
- [Overview](#overview)
- [Versions](#versions)
- [Installation](#installation)
- [Using posh-git](#using-posh-git)
- [Git status summary information](#git-status-summary-information)
- [Customization variables](#customization-variables)
- [Customizing the posh-git prompt](#customizing-the-posh-git-prompt)
- [Based on work by](#based-on-work-by)
## Overview
posh-git is a PowerShell module that integrates Git and PowerShell by providing Git status summary information that
can be displayed in the PowerShell prompt, e.g.:
![C:\Users\Keith\GitHub\posh-git [main ≡ +0 ~1 -0 | +0 ~1 -0 !]> ][prompt-def-long]
posh-git also provides tab completion support for common git commands, branch names, paths and more.
For example, with posh-git, PowerShell can tab complete git commands like `checkout` by typing `git ch` and pressing
the <kbd>tab</kbd> key. That will tab complete to `git checkout` and if you keep pressing <kbd>tab</kbd>, it will
cycle through other command matches such as `cherry` and `cherry-pick`. You can also tab complete remote names and
branch names e.g.: `git pull or<tab> ma<tab>` tab completes to `git pull origin main`.
## Versions
### posh-git v1.0
| Windows (AppVeyor) | Linux/macOS (Travis) | Code Coverage Status |
|--------------------|----------------------|----------------------|
| [![master build status][av-master-img]][av-master-site] | [![master build status][tv-master-img]][tv-master-site] | [![master build coverage][cc-master-img]][cc-master-site] |
[README][main-readme] • [CHANGELOG][main-change]
- Supports Windows PowerShell 5.x
- Supports PowerShell Core 6+ on all platforms
- Supports [ANSI escape sequences][ansi-esc-code] for color customization
- Includes breaking changes from v0.x ([roadmap](https://github.com/dahlbyk/posh-git/issues/328))
- **All SSH commands removed** from `posh-git` and moved into the new module [posh-sshell][posh-sshell-url]
#### Releases
- v1.1.0
( [README][v1.1-readme] • [CHANGELOG][v1.1-change] )
- v1.0.0
( [README][v1-readme] • [CHANGELOG][v1-change] )
- v1.0.0-beta5
( [README][v1b5-readme] • [CHANGELOG][v1b5-change] )
- v1.0.0-beta4
( [README][v1b4-readme] • [CHANGELOG][v1b4-change] )
- v1.0.0-beta3
( [README][v1b3-readme] • [CHANGELOG][v1b3-change] )
- v1.0.0-beta2
( [README][v1b2-readme] • [CHANGELOG][v1b2-change] )
- v1.0.0-beta1
( [README][v1b1-readme] • [CHANGELOG][v1b1-change] )
### posh-git v0.x
| Windows (AppVeyor) | Code Coverage Status |
|--------------------|----------------------|
| [![v0 build status][av-v0-img]][av-v0-site] | [![v0 build coverage][cc-v0-img]][cc-v0-site] |
[README][v0-readme] • [CHANGELOG][v0-change]
- Supports Windows PowerShell 3+
- Does not support PowerShell Core
- Avoids breaking changes, maintaining v0.x
#### Releases
- v0.7.3
( [README][v073-readme] • [CHANGELOG][v073-change] )
- v0.7.1
( [README][v071-readme] • [CHANGELOG][v071-change] )
- v0.7.0
( [README][v070-readme] • [CHANGELOG][v070-change] )
## Installation
These installation instructions, as well as the rest of this README, applies only to version 1.x of posh-git.
For v0.x installation instructions see this [README][v0-readme].
### Prerequisites
Before installing posh-git make sure the following prerequisites have been met.
1. Windows PowerShell 5.x or PowerShell Core 6.0.
You can get PowerShell Core 6.0 for Windows, Linux or macOS from [here][pscore-install].
Check your PowerShell version by executing `$PSVersionTable.PSVersion`.
2. On Windows, script execution policy must be set to either `RemoteSigned` or `Unrestricted`.
Check the script execution policy setting by executing `Get-ExecutionPolicy`.
If the policy is not set to one of the two required values, run PowerShell as Administrator and
execute `Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Confirm`.
3. Git must be installed and available via the PATH environment variable.
Check that `git` is accessible from PowerShell by executing `git --version` from PowerShell.
If `git` is not recognized as the name of a command, verify that you have Git installed.
If not, install Git from [https://git-scm.com](https://git-scm.com).
If you have Git installed, make sure the path to git is in your PATH environment variable.
### Installing posh-git via PowerShellGet on Linux, macOS and Windows
posh-git is available on the [PowerShell Gallery][psgallery-v1] and can be installed using the built-in PowerShellGet module.
1. Start Windows PowerShell 5.x or PowerShell >= v6 (`pwsh`).
2. Execute one of the following two commands from an elevated PowerShell prompt,
depending on whether (A) you've never installed posh-git, or (B) you've already installed a previous version:
```powershell
# (A) You've never installed posh-git from the PowerShell Gallery
PowerShellGet\Install-Module posh-git -Scope CurrentUser -Force
```
> **NOTE**: If you're asked to trust packages from the PowerShell Gallery, answer `yes` to continue installation of posh-git
OR
```powershell
# (B) You've already installed a previous version of posh-git from the PowerShell Gallery
PowerShellGet\Update-Module posh-git
```
### Installing posh-git via Chocolatey
If you prefer to manage posh-git as a Windows package, you can use [Chocolatey](https://chocolatey.org) to install posh-git.
If you don't have Chocolatey, you can install it from the [Chocolatey Install page](https://chocolatey.org/install).
With Chocolatey installed, execute the following command to install posh-git:
```powershell
choco install poshgit
```
### Installing posh-git via Scoop
Another popular package manager for Windows is [Scoop](https://scoop.sh/), which you can also use
to install posh-git. With Scoop installed, execute these commands to install posh-git and import
it into your profile:
```powershell
scoop bucket add extras
scoop install posh-git
Add-PoshGitToProfile
```
### Installing posh-git Manually
If you need to test/debug changes prior to contributing here, or would otherwise prefer to install posh-git without
the aid of a package manager, you can execute `Import-Module <path-to-src\posh-git.psd1>`. For example, if you
have git cloned posh-git to `~\git\posh-git` you can import this version of posh-git by executing
`Import-Module ~\git\posh-git\src\posh-git.psd1`.
## Using posh-git
After you have installed posh-git, you need to configure your PowerShell session to use the posh-git module.
### Step 1: Import posh-git
The first step is to import the module into your PowerShell session which will enable git tab completion.
You can do this with the command `Import-Module posh-git`.
### Step 2: Import posh-git from your PowerShell profile
You do not want to have to manually execute the `Import-Module` command every time you open a new PowerShell prompt.
Let's have PowerShell import this module for you in each new PowerShell session.
We can do this by either executing the command `Add-PoshGitToProfile` or by editing your PowerShell profile script and
adding the command `Import-Module posh-git`.
If you want posh-git to be available in all your PowerShell hosts (console, ISE, etc) then execute
`Add-PoshGitToProfile -AllHosts`. This will add a line containing `Import-Module posh-git` to the file
`$profile.CurrentUserAllHosts`.
If you want posh-git to be available in just the current host, then execute `Add-PoshGitToProfile`.
This will add the same command but to the file `$profile.CurrentUserCurrentHost`.
If you want posh-git to be available for all users on the system, start PowerShell as Administrator or
via sudo (`sudo pwsh`) on Linux/macOS then execute `Add-PoshGitToProfile -AllUsers -AllHosts`.
This will add the import command to `$profile.AllUsersAllHosts`.
If you want to configure posh-git for all users but only for the current host,
drop the `-AllHosts` parameter and the command will modify `$profile.AllUsersCurrentHost`.
If you'd prefer, you can manually edit the desired PowerShell profile script.
Open (or create) your profile script with the command `notepad $profile.CurrentUserAllHosts`.
In the profile script, add the following line:
```powershell
Import-Module posh-git
```
Save the profile script, then close PowerShell and open a new PowerShell session.
Type `git fe` and then press <kbd>tab</kbd>. If posh-git has been imported, that command should tab complete to
`git fetch`.
If you want posh-git to detect your own aliases for git, then you *must* have set the alias *before* importing posh-git.
So if you have `Set-Alias g git` then ensure it is executed before `Import-Module posh-git`, and `g checkout` will
complete as if you'd typed `git`.
## Git status summary information
The Git status summary information provides a wealth of "Git status" information at a glance, all the time in your
prompt.
By default, the status summary has the following format:
[{HEAD-name} S +A ~B -C !D | +E ~F -G !H W]
- `[` (`BeforeStatus`)
- `{HEAD-name}` is the current branch, or the SHA of a detached HEAD
- Cyan means the branch matches its remote
- Green means the branch is ahead of its remote (green light to push)
- Red means the branch is behind its remote
- Yellow means the branch is both ahead of and behind its remote
- `S` represents the branch status in relation to the remote (tracked origin) branch.
Note: This status information reflects the state of the remote tracked branch after the last `git fetch/pull`
of the remote. Execute `git fetch` to update to the latest on the default remote repo. If you have multiple remotes,
execute `git fetch --all`.
- `≡` = The local branch is at the same commit level as the remote branch (`BranchIdenticalStatus`)
- `↑<num>` = The local branch is ahead of the remote branch by the specified number of commits; a `git push` is
required to update the remote branch (`BranchAheadStatus`)
- `↓<num>` = The local branch is behind the remote branch by the specified number of commits; a `git pull` is
required to update the local branch (`BranchBehindStatus`)
- `<a>↕<b>` = The local branch is both ahead of the remote branch by the specified number of commits (a) and behind
by the specified number of commits (b); a rebase of the local branch is required before pushing local changes to
the remote branch (`BranchBehindAndAheadStatus`). NOTE: this status is only available if
`$GitPromptSettings.BranchBehindAndAheadDisplay` is set to `Compact`.
- `×` = The local branch is tracking a branch that is gone from the remote (`BranchGoneStatus`)
- `ABCD` represent the index; `|` (`DelimStatus`); `EFGH` represent the working directory
- `+` = Added files
- `~` = Modified files
- `-` = Removed files
- `!` = Conflicted files
- As with `git status` output, index status is displayed in dark green and working directory status in dark red
- `W` represents the overall status of the working directory
- `!` = There are unstaged changes in the working tree (`LocalWorkingStatusSymbol`)
- `~` = There are uncommitted changes i.e. staged changes in the working tree waiting to be committed (`LocalStagedStatusSymbol`)
- None = There are no unstaged or uncommitted changes to the working tree (`LocalDefaultStatusSymbol`)
- `]` (`AfterStatus`)
The symbols and surrounding text can be customized by the corresponding properties on `$GitPromptSettings`.
For example, a status of `[main ≡ +0 ~2 -1 | +1 ~1 -0]` corresponds to the following `git status`:
```powershell
# On branch main
#
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: this-changed.txt
# modified: this-too.txt
# deleted: gone.ps1
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: not-staged.ps1
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# new.file
```
## Customization variables
posh-git adds variables to your session to let you customize it, including `$GitPromptSettings`, `$GitTabSettings`, and
`$TortoiseGitSettings`. For an example of how to configure your PowerShell profile script to import the posh-git
module and create a custom prompt function that displays git status info, see the
[Customizing Your PowerShell Prompt](#customizing-the-posh-git-prompt) section below.
Note on performance: Displaying file status in the git prompt for a very large repo can be prohibitively slow.
Rather than turn off file status entirely (`$GitPromptSettings.EnableFileStatus = $false`), you can disable it on a
repo-by-repo basis by adding individual repository paths to `$GitPromptSettings.RepositoriesInWhichToDisableFileStatus`.
## Customizing the posh-git prompt
When you import the posh-git module, it will replace PowerShell's default prompt function with a new prompt function.
The posh-git prompt function will display Git status summary information when the current directory is inside a Git
repository. posh-git will not replace the prompt function if it has detected that you have your own, customized prompt
function.
The prompt function provided by posh-git creates a prompt that looks like this:
![~\GitHub\posh-git [main ≡]> ][prompt-default]
You can customize the posh-git prompt function or define your own custom prompt function.
The rest of this section covers how to customize posh-git's prompt function using the global variable
`$GitPromptSettings`.
**If you'd like to make any of following changes permanent, i.e. available whenever you start PowerShell, put the
corresponding setting(s) in one of your profile scripts after the line that imports posh-git.**
For instance, you can customize the default prompt prefix to display a colored timestamp with these settings:
```text
$GitPromptSettings.DefaultPromptPrefix.Text = '$(Get-Date -f "MM-dd HH:mm:ss") '
$GitPromptSettings.DefaultPromptPrefix.ForegroundColor = [ConsoleColor]::Magenta
```
This will change the prompt to:
![02-18 13:45:19 ~\GitHub\posh-git [main ≡]> ][prompt-prefix]
If you would prefer not to have any path under your home directory abbreviated with `~`, use the following setting:
```text
$GitPromptSettings.DefaultPromptAbbreviateHomeDirectory = $false
```
This will change the prompt to:
![C:\Users\Keith\GitHub\posh-git [main ≡]> ][prompt-no-abbr]
If you would like to change the color of the path, you can use the following setting on Windows:
```text
$GitPromptSettings.DefaultPromptPath.ForegroundColor = 'Orange'
```
> Note: Setting the ForegroundColor to a color name, other than one of the standard ConsoleColor names, only works on Windows.
On Windows, posh-git uses the `[System.Drawing.ColorTranslator]::FromHtml(string colorName)` method to parse a color
name as an HTML color. For a complete list of HTML colors, see this [W3Schools page][w3c-colors].
If you are on Linux or macOS and desire an Orange path, you will need to specify the RGB value for Orange e.g.:
```text
$GitPromptSettings.DefaultPromptPath.ForegroundColor = 0xFFA500
```
This will change the prompt to:
![~\GitHub\posh-git [main]> ][prompt-path]
If you would like to make your prompt span two lines, with a newline after the Git status summary, use this setting:
```text
$GitPromptSettings.DefaultPromptBeforeSuffix.Text = '`n'
```
This will change the prompt to:
![~\GitHub\posh-git [main ≡] > ][prompt-two-line]
You can swap the order of the path and the Git status summary with the following setting:
```text
$GitPromptSettings.DefaultPromptWriteStatusFirst = $true
```
This will change the prompt to:
![[main ≡] ~\GitHub\posh-git> ][prompt-swap]
Finally, you can combine these settings to customize the posh-git prompt fairly significantly.
In the `DefaultPromptSuffix` field below, we are prepending the PowerShell history id number before the prompt
char `>` e.g.:
```text
$GitPromptSettings.DefaultPromptWriteStatusFirst = $true
$GitPromptSettings.DefaultPromptBeforeSuffix.Text = '`n$([DateTime]::now.ToString("MM-dd HH:mm:ss"))'
$GitPromptSettings.DefaultPromptBeforeSuffix.ForegroundColor = 0x808080
$GitPromptSettings.DefaultPromptSuffix = ' $((Get-History -Count 1).id + 1)$(">" * ($nestedPromptLevel + 1)) '
```
This will change the prompt to:
![[main ≡] ~\GitHub\posh-git 02-18 14:04:35 38> ][prompt-custom]
Finally, the path portion of the prompt can be contained within delimiters.
For instance, if you would like the containing characters to be red, curly braces, the following settings can be used:
```powershell
$GitPromptSettings.BeforePath = '{'
$GitPromptSettings.AfterPath = '}'
$GitPromptSettings.BeforePath.ForegroundColor = 'Red'
$GitPromptSettings.AfterPath.ForegroundColor = 'Red'
```
With these additional values, the previous prompt would become
![[main ≡] {~\GitHub\posh-git} 02-18 14:04:35 38> ][prompt-custom-wpathdelim]
### Prompt Layouts
For reference, the following layouts show the relative position of the various parts of the posh-git prompt.
Note that `<>` denotes parts of the prompt that may not appear depending on the status of settings and whether or not
the current dir is in a Git repository.
To simplify the layout, `DP` is being used as an abbreviation for `DefaultPrompt` settings.
Default prompt layout:
```text
{DPPrefix}{BeforePath}{DPPath}{AfterPath}{PathStatusSeparator}<{BeforeStatus}{Status}{AfterStatus}>{DPBeforeSuffix}<{DPDebug}><{DPTimingFormat}>{DPSuffix}
```
Prompt layout when DefaultPromptWriteStatusFirst is set to $true:
```text
{DPPrefix}<{BeforeStatus}{Status}{AfterStatus}>{PathStatusSeparator}{BeforePath}{DPPath}{AfterPath}{DPBeforeSuffix}<{DPDebug}><{DPTimingFormat}>{DPSuffix}
```
### Displaying Error Information
If you want to display the error status of the last command, you can use the values stored in the `$global:GitPromptValues`
object which includes the value of `$LastExitCode` and `$?` (represented by the property `DollarQuestion`). Here is
a prompt customization that displays a Red exit code value when `$LastExitCode` is non-zero or a Red `!` if `$?`
is `$false`:
```powershell
function global:PromptWriteErrorInfo() {
if ($global:GitPromptValues.DollarQuestion) { return }
if ($global:GitPromptValues.LastExitCode) {
"`e[31m(" + $global:GitPromptValues.LastExitCode + ") `e[0m"
}
else {
"`e[31m! `e[0m"
}
}
$global:GitPromptSettings.DefaultPromptBeforeSuffix.Text = '`n$(PromptWriteErrorInfo)$([DateTime]::now.ToString("MM-dd HH:mm:ss"))'
```
When a PowerShell command fails, this is the prompt you will see:
![~\GitHub\posh-git [main ≡] ! 07-01 22:36:31> ][prompt-error1]
When an external application returns a non-zero exit code, 1 in this case, you will see the exit code in the prompt:
![~\GitHub\posh-git [main ≡] (1) 07-01 22:32:28> ][prompt-error2]
Note that until you run an external application that sets `$LASTEXITCODE` to zero or you manually set the variable to
0, you will see the exit code for any error. In addition to `LastExitCode` and `DollarQuestion`,
`$global:GitPromptValues` also has `IsAdmin` and `LastPrompt` properties. The `LastPrompt` property contains the ANSI
escaped string that was used for the last prompt. This can be useful for debugging your prompt display particularly
when using ANSI/VT sequences.
### $GitPromptScriptBlock
If you require even more customization than `$GitPromptSettings` provides, you can create your own prompt
function to show whatever information you want.
See the [Customizing Your PowerShell Prompt][wiki-custom-prompt] wiki page for details.
However, if you need a custom prompt just to perform some non-prompt logic, you can still use posh-git's
prompt function to write out the prompt string. This can be done with the `$GitPromptScriptBlock` variable as shown
below e.g.:
```powershell
# my profile.ps1
function prompt {
# Your non-prompt logic here
# Have posh-git display its default prompt
& $GitPromptScriptBlock
}
```
And if you'd like to write prompt text before and/or after the posh-git prompt,
you can use posh-git's `Write-Prompt` command as shown below:
```powershell
# my profile.ps1
function prompt {
# Your non-prompt logic here
$prompt = Write-Prompt "Text before posh-git prompt " -ForegroundColor ([ConsoleColor]::Green)
$prompt += & $GitPromptScriptBlock
$prompt += Write-Prompt "Text after posh-git prompt" -ForegroundColor ([ConsoleColor]::Magenta)
if ($prompt) { "$prompt " } else { " " }
}
```
## Based on work by
- Keith Dahlby, http://solutionizing.net/
- Mark Embling, http://www.markembling.info/
- Jeremy Skinner, http://www.jeremyskinner.co.uk/
[av-master-site]: https://ci.appveyor.com/project/dahlbyk/posh-git/branch/master
[av-master-img]: https://ci.appveyor.com/api/projects/status/eb8erd5afaa01w80/branch/master?svg=true&pendingText=master%20%E2%80%A3%20pending&failingText=master%20%E2%80%A3%20failing&passingText=master%20%E2%80%A3%20passing
[av-v0-img]: https://ci.appveyor.com/api/projects/status/eb8erd5afaa01w80/branch/v0?svg=true&pendingText=v0%20%E2%80%A3%20pending&failingText=v0%20%E2%80%A3%20failing&passingText=v0%20%E2%80%A3%20passing
[av-v0-site]: https://ci.appveyor.com/project/dahlbyk/posh-git/branch/v0
[tv-master-img]: https://travis-ci.org/dahlbyk/posh-git.svg?branch=master
[tv-master-site]: https://travis-ci.org/dahlbyk/posh-git
[cc-master-img]: https://coveralls.io/repos/github/dahlbyk/posh-git/badge.svg?branch=master
[cc-master-site]: https://coveralls.io/github/dahlbyk/posh-git?branch=master
[cc-v0-img]: https://coveralls.io/repos/github/dahlbyk/posh-git/badge.svg?branch=v0
[cc-v0-site]: https://coveralls.io/github/dahlbyk/posh-git?branch=v0
[ansi-esc-code]: https://en.wikipedia.org/wiki/ANSI_escape_code
[console-vt-seq]: https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
[gitter-img]: https://badges.gitter.im/dahlbyk/posh-git.svg
[gitter]: https://gitter.im/dahlbyk/posh-git?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
[pscore-install]: https://github.com/PowerShell/PowerShell#get-powershell
[choco-img]: https://img.shields.io/chocolatey/dt/poshgit.svg
[choco-site]: https://chocolatey.org/packages/poshgit/
[psgallery-img]: https://img.shields.io/powershellgallery/dt/posh-git.svg
[psgallery-site]: https://www.powershellgallery.com/packages/posh-git
[psgallery-v1]: https://www.powershellgallery.com/packages/posh-git/1.0.0
[w3c-colors]: https://www.w3schools.com/colors/colors_names.asp
[posh-sshell-url]: https://github.com/dahlbyk/posh-sshell
[prompt-def-long]: https://github.com/dahlbyk/posh-git/wiki/images/PromptDefaultLong.png "~\GitHub\posh-git [main ≡ +0 ~1 -0 | +0 ~1 -0 !]> "
[prompt-default]: https://github.com/dahlbyk/posh-git/wiki/images/PromptDefault.png "~\GitHub\posh-git [main ≡]> "
[prompt-prefix]: https://github.com/dahlbyk/posh-git/wiki/images/PromptPrefix.png "02-18 13:45:19 ~\GitHub\posh-git [main ≡]>"
[prompt-no-abbr]: https://github.com/dahlbyk/posh-git/wiki/images/PromptNoAbbrevHome.png "C:\Users\Keith\GitHub\posh-git [main ≡]> "
[prompt-path]: https://github.com/dahlbyk/posh-git/wiki/images/PromptOrangePath.png "~\GitHub\posh-git [main ≡]> "
[prompt-swap]: https://github.com/dahlbyk/posh-git/wiki/images/PromptStatusFirst.png "[main ≡] ~\GitHub\posh-git> "
[prompt-two-line]: https://github.com/dahlbyk/posh-git/wiki/images/PromptTwoLine.png "~\GitHub\posh-git [main ≡] > "
[prompt-custom]: https://github.com/dahlbyk/posh-git/wiki/images/PromptCustom.png "[main ≡] ~\GitHub\posh-git 02-18 14:04:35 38> "
[prompt-custom-wpathdelim]: https://github.com/dahlbyk/posh-git/wiki/images/PromptCustomDelim.png "[main ≡] {~\GitHub\posh-git} 02-18 14:04:35 38> "
[prompt-error1]: https://github.com/dahlbyk/posh-git/wiki/images/PromptError1.png "~\GitHub\posh-git [main ≡] ! 07-01 22:36:31> "
[prompt-error2]: https://github.com/dahlbyk/posh-git/wiki/images/PromptError2.png "~\GitHub\posh-git [main ≡] (1) 07-01 22:32:28> "
[v0-change]: https://github.com/dahlbyk/posh-git/blob/v0/CHANGELOG.md
[v0-readme]: https://github.com/dahlbyk/posh-git/blob/v0/README.md
[v070-change]: https://github.com/dahlbyk/posh-git/blob/v0.7.0/CHANGELOG.md
[v070-readme]: https://github.com/dahlbyk/posh-git/blob/v0.7.0/README.md
[v071-change]: https://github.com/dahlbyk/posh-git/blob/v0.7.1/CHANGELOG.md
[v071-readme]: https://github.com/dahlbyk/posh-git/blob/v0.7.1/README.md
[v073-change]: https://github.com/dahlbyk/posh-git/blob/v0.7.3/CHANGELOG.md
[v073-readme]: https://github.com/dahlbyk/posh-git/blob/v0.7.3/README.md
[main-change]: https://github.com/dahlbyk/posh-git/blob/master/CHANGELOG.md
[main-readme]: https://github.com/dahlbyk/posh-git/blob/master/README.md
[v1b1-change]: https://github.com/dahlbyk/posh-git/blob/v1.0.0-beta1/CHANGELOG.md
[v1b1-readme]: https://github.com/dahlbyk/posh-git/blob/v1.0.0-beta1/README.md
[v1b2-change]: https://github.com/dahlbyk/posh-git/blob/v1.0.0-beta2/CHANGELOG.md
[v1b2-readme]: https://github.com/dahlbyk/posh-git/blob/v1.0.0-beta2/README.md
[v1b3-change]: https://github.com/dahlbyk/posh-git/blob/v1.0.0-beta3/CHANGELOG.md
[v1b3-readme]: https://github.com/dahlbyk/posh-git/blob/v1.0.0-beta3/README.md
[v1b4-change]: https://github.com/dahlbyk/posh-git/blob/v1.0.0-beta4/CHANGELOG.md
[v1b4-readme]: https://github.com/dahlbyk/posh-git/blob/v1.0.0-beta4/README.md
[v1b5-change]: https://github.com/dahlbyk/posh-git/blob/v1.0.0-beta5/CHANGELOG.md
[v1b5-readme]: https://github.com/dahlbyk/posh-git/blob/v1.0.0-beta5/README.md
[v1-change]: https://github.com/dahlbyk/posh-git/blob/v1.0.0/CHANGELOG.md
[v1-readme]: https://github.com/dahlbyk/posh-git/blob/v1.0.0/README.md
[v1.1-change]: https://github.com/dahlbyk/posh-git/blob/v1.1.0/CHANGELOG.md
[v1.1-readme]: https://github.com/dahlbyk/posh-git/blob/v1.1.0/README.md
[wiki-custom-prompt]: https://github.com/dahlbyk/posh-git/wiki/Customizing-Your-PowerShell-Prompt
================================================
FILE: chocolatey/packAndLocalInstall.ps1
================================================
param ($Remote = 'origin', [switch]$Force)
Push-Location $PSScriptRoot
$nuspec = [xml](Get-Content poshgit.nuspec)
$version = $nuspec.package.metadata.version
$tag = "v$version"
if ($Force) {
git tag -f $tag
git push -f $Remote $tag
}
elseif (!$(git ls-remote $Remote $tag)) {
Write-Warning "'$Remote/$tag' not found! Use -Force to create tag at HEAD."
return
}
choco pack poshgit.nuspec
choco install -f -y poshgit -pre --version=$version -s .
Pop-Location
================================================
FILE: chocolatey/poshgit.nuspec
================================================
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>poshgit</id>
<title>posh-git</title>
<version>1.1.0-alpha</version>
<authors>Keith Dahlby, Keith Hill, Mark Embling, Jeremy Skinner</authors>
<owners>Keith Dahlby</owners>
<description>### posh-git
A set of PowerShell scripts which provide Git/PowerShell integration
### Prompt for Git repositories
The prompt within Git repositories can show the current branch and the state of files (additions, modifications, deletions) within.
### Tab completion
Provides tab completion for common commands when using git.
E.g. `git ch<tab>` --> `git checkout`
### Usage
See profile.example.ps1 as to how you can integrate the tab completion and/or git prompt into your own profile. Prompt formatting, among other things, can be customized using `$GitPromptSettings`, `$GitTabSettings` and `$TortoiseGitSettings`.
Note on performance: displaying file status in the git prompt for a very large repo can be prohibitively slow. Rather than turn off file status entirely, you can disable it on a repo-by-repo basis by adding individual repository paths to `$GitPromptSettings.RepositoriesInWhichToDisableFileStatus`.
</description>
<summary>Provides prompt with Git status summary information and tab completion for Git commands, parameters, remotes and branch names.</summary>
<tags>poshgit posh-git powershell git</tags>
<projectUrl>https://github.com/dahlbyk/posh-git</projectUrl>
<licenseUrl>https://github.com/dahlbyk/posh-git/blob/master/LICENSE.txt</licenseUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<dependencies>
<dependency id="chocolatey" version="0.9.10" />
<dependency id="git" />
</dependencies>
</metadata>
<files>
<file src="tools\**" target="tools" />
</files>
</package>
<!-- character encoding: “UTF-8” -->
================================================
FILE: chocolatey/tests/InstallChocolatey.Tests.ps1
================================================
$packageName = "poshgit"
cpack
function Setup-Environment {
Cleanup
$env:poshGit = join-path (Resolve-Path .\Tests ) dahlbyk-posh-git-60be436.zip
$profileScript = "function Prompt(){ `$host.ui.RawUI.WindowTitle = `"My Prompt`" }"
(Set-Content $Profile -value $profileScript -Force)
}
function Cleanup {
Clean-Temp
Remove-Item $env:ChocolateyInstall\lib\$packageName* -Recurse -Force
}
function Clean-Temp {
if(Test-Path $env:Temp\Chocolatey\$packageName) {Remove-Item $env:Temp\Chocolatey\$packageName -Recurse -Force}
}
function RunInstall {
cinst $packageName -source (Resolve-Path .)
}
$binRoot = join-path $env:systemdrive 'tools'
if($null -ne $env:chocolatey_bin_root){$binRoot = join-path $env:systemdrive $env:chocolatey_bin_root}
$poshgitPath = join-path $binRoot 'poshgit'
if(Test-Path $Profile) { $currentProfileScript = (Get-Content $Profile) }
function Clean-Environment {
Set-Content $Profile -value $currentProfileScript -Force
}
Describe "Install-Posh-Git" {
It "WillRemvePreviousInstallVersion" {
Setup-Environment
try{
Add-Content $profile -value ". '$poshgitPath\posh-git\profile.example.ps1'"
RunInstall
$newProfile = (Get-Content $Profile)
$pgitDir = [Array](Get-ChildItem "$poshgitPath\*posh-git*\" | Sort-Object -Property LastWriteTime)[-1]
($newProfile -like ". '$poshgitPath\posh-git\profile.example.ps1'").Count.should.be(0)
($newProfile -like ". '$pgitDir\profile.example.ps1'").Count.should.be(1)
}
catch {
write-host (Get-Content $Profile)
throw
}
finally {Clean-Environment}
}
It "WillNotAddDuplicateCallOnRepeatInstall" {
Setup-Environment
try{
RunInstall
Cleanup
RunInstall
$newProfile = (Get-Content $Profile)
$pgitDir = [Array](Get-ChildItem "$poshgitPath\*posh-git*\" | Sort-Object -Property LastWriteTime)[-1]
($newProfile -like ". '$pgitDir\profile.example.ps1'").Count.should.be(1)
}
catch {
write-host (Get-Content $Profile)
throw
}
finally {Clean-Environment}
}
It "WillPreserveOldPromptLogic" {
Setup-Environment
try{
RunInstall
. $Profile
$host.ui.RawUI.WindowTitle = "bad"
Prompt
$host.ui.RawUI.WindowTitle.should.be("My Prompt")
}
catch {
write-host (Get-Content function:\prompt)
throw
}
finally {
Clean-Environment
}
}
It "WillOutputVcsStatus" {
Setup-Environment
try{
RunInstall
mkdir PoshTest
Push-Location PoshTest
git init
. $Profile
$global:wh=""
New-Item function:\global:Write-Host -value "param([object] `$object, `$backgroundColor, `$foregroundColor, [switch] `$nonewline) try{Write-Output `$object;[string]`$global:wh += `$object.ToString()} catch{}"
Prompt
Pop-Location
$wh.should.be("$pwd\PoshTest [master]")
}
catch {
write-output (Get-Content $Profile)
throw
}
finally {
Clean-Environment
if( Test-Path function:\Write-Host ) {Remove-Item function:\Write-Host}
if( Test-Path PoshTest ) {Remove-Item PoshTest -Force -Recurse}
}
}
It "WillSucceedOnEmptyProfile" {
Setup-Environment
try{
Remove-Item $Profile -Force
RunInstall
mkdir PoshTest
Push-Location PoshTest
git init
. $Profile
$global:wh=""
New-Item function:\global:Write-Host -value "param([object] `$object, `$backgroundColor, `$foregroundColor, [switch] `$nonewline) try{Write-Output `$object;[string]`$global:wh += `$object.ToString()} catch{}"
Prompt
Pop-Location
$wh.should.be("$pwd\PoshTest [master]")
}
catch {
write-output (Get-Content $Profile)
throw
}
finally {
Clean-Environment
if( Test-Path function:\Write-Host ) {Remove-Item function:\Write-Host}
if( Test-Path PoshTest ) {Remove-Item PoshTest -Force -Recurse}
}
}
It "WillSucceedOnProfileWithPromptWithWriteHost" {
Cleanup
Setup-Environment
try{
Remove-Item $Profile -Force
Add-Content $profile -value "function prompt {Write-Host 'Hi'}" -Force
RunInstall
mkdir PoshTest
Push-Location PoshTest
git init
. $Profile
$global:wh=""
New-Item function:\global:Write-Host -value "param([object] `$object, `$backgroundColor, `$foregroundColor, [switch] `$nonewline) try{Write-Output `$object;[string]`$global:wh += `$object.ToString()} catch{}"
Prompt
Remove-Item function:\global:Write-Host
Pop-Location
$wh.should.be("$pwd\PoshTest [master]")
}
catch {
write-output (Get-Content $Profile)
throw
}
finally {
Clean-Environment
if( Test-Path function:\Write-Host ) {Remove-Item function:\Write-Host}
if( Test-Path PoshTest ) {Remove-Item PoshTest -Force -Recurse}
}
}
It "WillSucceedOnUpdatingFrom040" {
Cleanup
Setup-Environment
try{
Remove-Item $Profile -Force
Add-Content $profile -value ". 'C:\tools\poshgit\dahlbyk-posh-git-60be436\profile.example.ps1'" -Force
RunInstall
mkdir PoshTest
Push-Location PoshTest
git init
write-output (Get-Content function:\prompt)
. $Profile
$global:wh=""
New-Item function:\global:Write-Host -value "param([object] `$object, `$backgroundColor, `$foregroundColor, [switch] `$nonewline) try{Write-Output `$object;[string]`$global:wh += `$object.ToString()} catch{}"
Prompt
Remove-Item function:\global:Write-Host
Pop-Location
$wh.should.be("$pwd\PoshTest [master]")
}
catch {
write-output (Get-Content $Profile)
throw
}
finally {
Clean-Environment
if( Test-Path function:\Write-Host ) {Remove-Item function:\Write-Host}
if( Test-Path PoshTest ) {Remove-Item PoshTest -Force -Recurse}
}
}
}
================================================
FILE: chocolatey/tools/chocolateyInstall.ps1
================================================
try {
$poshgitPath = join-path (Get-ToolsLocation) 'poshgit'
try {
if (test-path($poshgitPath)) {
Write-Host "Attempting to remove existing `'$poshgitPath`'."
remove-item $poshgitPath -recurse -force
}
}
catch {
Write-Host "Could not remove `'$poshgitPath`'"
}
$version = "v$Env:chocolateyPackageVersion"
if ($version -eq 'v') { $version = 'master' }
$poshGitInstall = if ($env:poshGit) { $env:poshGit } else { "https://github.com/dahlbyk/posh-git/zipball/$version" }
$zip = Install-ChocolateyZipPackage 'poshgit' $poshGitInstall $poshgitPath
$currentVersionPath = Get-ChildItem "$poshgitPath\*posh-git*\" | Sort-Object -Property LastWriteTime | Select-Object -Last 1
if (Test-Path $PROFILE) {
$oldProfile = @(Get-Content $PROFILE)
. $currentVersionPath\src\Utils.ps1
$oldProfileEncoding = Get-FileEncoding $PROFILE
$newProfile = @()
foreach($line in $oldProfile) {
if ($line -like '*PoshGitPrompt*') { continue }
if ($line -like '. *posh-git*profile.example.ps1*') {
$line = ". '$currentVersionPath\profile.example.ps1' choco"
}
if ($line -like 'Import-Module *\src\posh-git.psd1*') {
$line = "Import-Module '$currentVersionPath\src\posh-git.psd1'"
}
$newProfile += $line
}
Set-Content -path $profile -value $newProfile -Force -Encoding $oldProfileEncoding
}
$installer = Join-Path $currentVersionPath 'install.ps1'
& $installer
} catch {
try {
if ($oldProfile ) {
Set-Content -path $PROFILE -value $oldProfile -Force -Encoding $oldProfileEncoding
}
}
catch {}
throw
}
================================================
FILE: chocolatey/tools/chocolateyUninstall.ps1
================================================
try {
$poshgitPath = join-path (Get-ToolsLocation) 'poshgit'
$currentVersionPath = Get-ChildItem "$poshgitPath\*posh-git*\" | Sort-Object -Property LastWriteTime | Select-Object -Last 1
if(Test-Path $PROFILE) {
$oldProfile = @(Get-Content $PROFILE)
. $currentVersionPath\src\Utils.ps1
$oldProfileEncoding = Get-FileEncoding $PROFILE
$newProfile = @()
foreach($line in $oldProfile) {
if ($line -like '*PoshGitPrompt*') { continue; }
if ($line -like '*Load posh-git example profile*') { continue; }
if($line -like '. *posh-git*profile.example.ps1*') {
continue;
}
if($line -like 'Import-Module *\src\posh-git.psd1*') {
continue;
}
$newProfile += $line
}
Set-Content -path $profile -value $newProfile -Force -Encoding $oldProfileEncoding
}
try {
if (test-path($poshgitPath)) {
Write-Host "Attempting to remove existing `'$poshgitPath`'."
remove-item $poshgitPath -recurse -force
}
} catch {
Write-Host "Could not remove `'$poshgitPath`'"
}
} catch {
try {
if($oldProfile){ Set-Content -path $PROFILE -value $oldProfile -Force -Encoding $oldProfileEncoding }
}
catch {}
throw
}
================================================
FILE: install.ps1
================================================
param([switch]$WhatIf = $false, [switch]$Force = $false, [switch]$Verbose = $false)
$installDir = Split-Path $MyInvocation.MyCommand.Path -Parent
Import-Module $installDir\src\posh-git.psd1
Add-PoshGitToProfile -WhatIf:$WhatIf -Force:$Force -Verbose:$Verbose
================================================
FILE: profile.example.ps1
================================================
# Import the posh-git module, first via installed posh-git module.
# If the module isn't installed, then attempt to load it from the cloned posh-git Git repo.
$poshGitModule = Get-Module posh-git -ListAvailable | Sort-Object Version -Descending | Select-Object -First 1
if ($poshGitModule) {
$poshGitModule | Import-Module
}
elseif (Test-Path -LiteralPath ($modulePath = Join-Path (Split-Path $MyInvocation.MyCommand.Path -Parent) (Join-Path src 'posh-git.psd1'))) {
Import-Module $modulePath
}
else {
throw "Failed to import posh-git."
}
# Settings for the prompt are in GitPrompt.ps1, so add any desired settings changes here.
# Example:
# $Global:GitPromptSettings.BranchBehindAndAheadDisplay = "Compact"
if ($args[0] -ne 'choco') {
Write-Warning "posh-git's profile.example.ps1 will be removed in a future version."
Write-Warning "Consider using `Add-PoshGitToProfile` instead."
}
================================================
FILE: src/AnsiUtils.ps1
================================================
# Color codes from https://msdn.microsoft.com/en-us/library/windows/desktop/mt638032(v=vs.85).aspx
$ConsoleColorToAnsi = @(
30 # Black
34 # DarkBlue
32 # DarkGreen
36 # DarkCyan
31 # DarkRed
35 # DarkMagenta
33 # DarkYellow
37 # Gray
90 # DarkGray
94 # Blue
92 # Green
96 # Cyan
91 # Red
95 # Magenta
93 # Yellow
97 # White
)
$AnsiDefaultColor = 39
$AnsiEscape = [char]27 + "["
[Reflection.Assembly]::LoadWithPartialName('System.Drawing') > $null
$ColorTranslatorType = 'System.Drawing.ColorTranslator' -as [Type]
$ColorType = 'System.Drawing.Color' -as [Type]
function EscapeAnsiString([string]$AnsiString) {
if ($PSVersionTable.PSVersion.Major -ge 6) {
$res = $AnsiString -replace "$([char]27)", '`e'
}
else {
$res = $AnsiString -replace "$([char]27)", '$([char]27)'
}
$res
}
function Test-VirtualTerminalSequece([psobject[]]$Object, [switch]$Force) {
foreach ($obj in $Object) {
if (($Force -or $global:GitPromptSettings.AnsiConsole) -and ($obj -is [string])) {
$obj.Contains($AnsiEscape)
}
else {
$false
}
}
}
function Get-VirtualTerminalSequence ($color, [int]$offset = 0) {
# Don't output ANSI escape sequences if the `$color` parameter is `$null`,
# they would be broken anyway
if ($null -eq $color) {
return $null;
}
if ($color -is [byte]) {
return "${AnsiEscape}$(38 + $offset);5;${color}m"
}
if ($color -is [int]) {
$r = ($color -shr 16) -band 0xff
$g = ($color -shr 8) -band 0xff
$b = $color -band 0xff
return "${AnsiEscape}$(38 + $offset);2;${r};${g};${b}m"
}
# Force 'DarkYellow' to ConsoleColor, since it is not an HTML color
if ($color -eq [System.ConsoleColor]::DarkYellow) {
$color = [System.ConsoleColor]::DarkYellow
}
elseif ($color -is [String]) {
try {
if ($ColorTranslatorType) {
$color = $ColorTranslatorType::FromHtml($color)
}
}
catch {
Write-Debug $_
}
}
if ($ColorType -and ($color -is $ColorType)) {
return "${AnsiEscape}$(38 + $offset);2;$($color.R);$($color.G);$($color.B)m"
}
if (($color -is [System.ConsoleColor]) -and ($color -ge 0) -and ($color -le 15)) {
return "${AnsiEscape}$($ConsoleColorToAnsi[$color] + $offset)m"
}
return "${AnsiEscape}$($AnsiDefaultColor + $offset)m"
}
function Get-ForegroundVirtualTerminalSequence($Color) {
return Get-VirtualTerminalSequence $Color
}
function Get-BackgroundVirtualTerminalSequence($Color) {
return Get-VirtualTerminalSequence $Color 10
}
================================================
FILE: src/CheckRequirements.ps1
================================================
$global:GitMissing = $false
$script:GitCygwin = $false
$script:GitVersion = $requiredVersion = [System.Version]'2.15'
if (!(Get-Command git -TotalCount 1 -ErrorAction SilentlyContinue)) {
Write-Warning "git command could not be found. Please create an alias or add it to your PATH."
$global:GitMissing = $true
return
}
function Test-GitVersion ($version = $([string](git --version 2> $null))) {
if ($version -notmatch '(?<ver>\d+(?:\.\d+)+)(?<g4w>(?<rc>[-.]rc\d+)?\.windows|\.vfs)?') {
Write-Warning "posh-git could not parse Git version ($version)"
$script:GitVersion = $version
return $false
}
# On Windows, check if Git is not "Git for Windows"
if ((($PSVersionTable.PSVersion.Major -le 5) -or $IsWindows) -and !$Matches['g4w']) {
$script:GitCygwin = $true
if (!$Env:POSHGIT_CYGWIN_WARNING) {
Write-Warning 'You appear to have an unsupported Git distribution; setting $GitPromptSettings.AnsiConsole = $false. posh-git recommends Git for Windows.'
}
}
$script:GitVersion = [System.Version]$Matches['ver']
return $GitVersion -ge $requiredVersion
}
if (!(Test-GitVersion)) {
Write-Warning "posh-git requires Git $requiredVersion or better. You have $GitVersion."
}
================================================
FILE: src/ConsoleMode.ps1
================================================
# Hack! https://gist.github.com/lzybkr/f2059cb2ee8d0c13c65ab933b75e998c
# Always skip setting the console mode on non-Windows platforms.
if (($PSVersionTable.PSVersion.Major -ge 6) -and !$IsWindows) {
function Set-ConsoleMode {
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
param()
}
return
}
$consoleModeSource = @"
using System;
using System.Runtime.InteropServices;
public class NativeConsoleMethods
{
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr GetStdHandle(int handleId);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool GetConsoleMode(IntPtr hConsoleOutput, out uint dwMode);
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool SetConsoleMode(IntPtr hConsoleOutput, uint dwMode);
public static uint GetConsoleMode(bool input = false)
{
var handle = GetStdHandle(input ? -10 : -11);
uint mode;
if (GetConsoleMode(handle, out mode))
{
return mode;
}
return 0xffffffff;
}
public static uint SetConsoleMode(bool input, uint mode)
{
var handle = GetStdHandle(input ? -10 : -11);
if (SetConsoleMode(handle, mode))
{
return GetConsoleMode(input);
}
return 0xffffffff;
}
}
"@
[Flags()]
enum ConsoleModeInputFlags
{
ENABLE_PROCESSED_INPUT = 0x0001
ENABLE_LINE_INPUT = 0x0002
ENABLE_ECHO_INPUT = 0x0004
ENABLE_WINDOW_INPUT = 0x0008
ENABLE_MOUSE_INPUT = 0x0010
ENABLE_INSERT_MODE = 0x0020
ENABLE_QUICK_EDIT_MODE = 0x0040
ENABLE_EXTENDED_FLAGS = 0x0080
ENABLE_AUTO_POSITION = 0x0100
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0200
}
[Flags()]
enum ConsoleModeOutputFlags
{
ENABLE_PROCESSED_OUTPUT = 0x0001
ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
}
function Set-ConsoleMode
{
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")]
param(
[Parameter(ParameterSetName = "ANSI")]
[switch]
$ANSI,
[Parameter(ParameterSetName = "Mode")]
[uint32]
$Mode,
[switch]
$StandardInput
)
begin {
# Module import is speeded up by deferring the Add-Type until the first time this function is called.
# Add the NativeConsoleMethods type but only once per session.
if (!('NativeConsoleMethods' -as [System.Type])) {
Add-Type $consoleModeSource
}
}
end {
if ($ANSI)
{
$outputMode = [NativeConsoleMethods]::GetConsoleMode($false)
$null = [NativeConsoleMethods]::SetConsoleMode($false, $outputMode -bor [ConsoleModeOutputFlags]::ENABLE_VIRTUAL_TERMINAL_PROCESSING)
if ($StandardInput)
{
$inputMode = [NativeConsoleMethods]::GetConsoleMode($true)
$null = [NativeConsoleMethods]::SetConsoleMode($true, $inputMode -bor [ConsoleModeInputFlags]::ENABLE_VIRTUAL_TERMINAL_PROCESSING)
}
}
else
{
[NativeConsoleMethods]::SetConsoleMode($StandardInput, $Mode)
}
}
}
================================================
FILE: src/GitParamTabExpansion.ps1
================================================
# Variable is used in GitTabExpansion.ps1
$shortGitParams = @{
add = 'n v f i p e u A N'
bisect = ''
blame = 'b L l t S p M C h c f n s e w'
branch = 'd D l f m M r a v vv q t u'
checkout = 'q f b B t l m p'
cherry = 'v'
'cherry-pick' = 'e x r m n s S X'
clean = 'd f i n q e x X'
clone = 'l s q v n o b u c'
commit = 'a p C c z F m t s n e i o u v q S'
config = 'f l z e'
diff = 'p u s U z B M C D l S G O R a b w W'
difftool = 'd y t x g'
fetch = 'a f k p n t u q v'
grep = 'a i I w v h H E G P F n l L O z c p C A B W f e q'
help = 'a g i m w'
init = 'q'
log = 'L n i E F g c c m r t'
merge = 'e n s X q v S m'
mergetool = 't y'
mv = 'f k n v'
notes = 'f m F C c n s q v'
prune = 'n v'
pull = 'q v e n s X r a f k u'
push = 'n f u q v'
rebase = 'm s X S q v n C f i p x'
remote = 'v'
reset = 'q p'
restore = 's p W S q m'
revert = 'e m n S s X'
rm = 'f n r q'
shortlog = 'n s e w'
stash = 'p k u a q'
status = 's b u z'
submodule = 'q b f n N'
switch = 'c C d f m q t'
tag = 'a s u f d v n l m F'
whatchanged = 'p'
}
# Variable is used in GitTabExpansion.ps1
$longGitParams = @{
add = 'dry-run verbose force interactive patch edit update all no-ignore-removal no-all ignore-removal intent-to-add refresh ignore-errors ignore-missing renormalize'
bisect = 'no-checkout term-old term-new'
blame = 'root show-stats reverse porcelain line-porcelain incremental encoding= contents date score-debug show-name show-number show-email abbrev'
branch = 'color no-color list abbrev= no-abbrev column no-column merged no-merged contains set-upstream track no-track set-upstream-to= unset-upstream edit-description delete create-reflog force move all verbose quiet'
checkout = 'quiet force ours theirs track no-track detach orphan ignore-skip-worktree-bits merge conflict= patch'
'cherry-pick' = 'edit mainline no-commit signoff gpg-sign ff allow-empty allow-empty-message keep-redundant-commits strategy= strategy-option= continue quit abort'
clean = 'force interactive dry-run quiet exclude='
clone = 'local no-hardlinks shared reference quiet verbose progress no-checkout bare mirror origin branch upload-pack template= config depth single-branch no-single-branch recursive recurse-submodules separate-git-dir='
commit = 'all patch reuse-message reedit-message fixup squash reset-author short branch porcelain long null file author date message template signoff no-verify allow-empty allow-empty-message cleanup= edit no-edit amend no-post-rewrite include only untracked-files verbose quiet dry-run status no-status gpg-sign no-gpg-sign'
config = 'replace-all add get get-all get-regexp get-urlmatch global system local file blob remove-section rename-section unset unset-all list bool int bool-or-int path null get-colorbool get-color edit includes no-includes'
describe = 'dirty all tags contains abbrev candidates= exact-match debug long match always first-parent'
diff = 'cached patch no-patch unified= raw patch-with-raw minimal patience histogram diff-algorithm= stat numstat shortstat dirstat summary patch-with-stat name-only name-status submodule color no-color word-diff word-diff-regex color-words no-renames check full-index binary apprev break-rewrites find-renames find-copies find-copies-harder irreversible-delete diff-filter= pickaxe-all pickaxe-regex relative text ignore-space-at-eol ignore-space-change ignore-all-space ignore-blank-lines inter-hunk-context= function-context exit-code quiet ext-diff no-ext-diff textconv no-textconv ignore-submodules src-prefix dst-prefix no-prefix staged'
difftool = 'dir-diff no-prompt prompt tool= tool-help no-symlinks symlinks extcmd= gui'
fetch = 'all append depth= unshallow update-shallow dry-run force keep multiple prune no-tags tags recurse-submodules= no-recurse-submodules submodule-prefix= recurse-submodules-default= update-head-ok upload-pack quiet verbose progress'
gc = 'aggressive auto prune= no-prune quiet force'
grep = 'cached no-index untracked no-exclude-standard exclude-standard text textconv no-textconv ignore-case max-depth word-regexp invert-match full-name extended-regexp basic-regexp perl-regexp fixed-strings line-number files-with-matches open-file-in-pager null count color no-color break heading show-function context after-context before-context function-context and or not all-match quiet'
help = 'all guides info man web'
init = 'quiet bare template= separate-git-dir= shared='
log = 'follow no-decorate decorate source use-mailmap full-diff log-size max-count skip since after until before author committer grep-reflog grep all-match regexp-ignore-case basic-regexp extended-regexp fixed-strings perl-regexp remove-empty merges no-merges min-parents max-parents no-min-parents no-max-parents first-parent not all branches tags remote glob= exclude= ignore-missing bisect stdin cherry-mark cherry-pick left-only right-only cherry walk-reflogs merge boundary simplify-by-decoration full-history dense sparse simplify-merges ancestry-path date-order author-date-order topo-order reverse objects objects-edge unpacked no-walk= do-walk pretty format= abbrev-commit no-abbrev-commit oneline encoding= notes no-notes standard-notes no-standard-notes show-signature relative-date date= parents children left-right graph show-linear-break patch stat'
merge = 'commit no-commit edit no-edit ff no-ff ff-only log no-log stat no-stat squash no-squash strategy strategy-option verify-signatures no-verify-signatures summary no-summary quiet verbose progress no-progress gpg-sign rerere-autoupdate no-rerere-autoupdate abort allow-unrelated-histories'
mergetool = 'tool= tool-help no-prompt prompt'
mv = 'force dry-run verbose'
notes = 'force message file reuse-message reedit-message ref ignore-missing stdin dry-run strategy= commit abort quiet verbose'
prune = 'dry-run verbose expire'
pull = 'quiet verbose recurse-submodules= no-recurse-submodules= commit no-commit edit no-edit ff no-ff ff-only log no-log stat no-stat squash no-squash strategy= strategy-option= verify-signatures no-verify-signatures summary no-summary rebase= no-rebase all append depth= unshallow update-shallow force keep no-tags update-head-ok upload-pack progress'
push = 'all prune mirror dry-run porcelain delete tags follow-tags receive-pack= exec= force-with-lease no-force-with-lease force repo= set-upstream thin no-thin quiet verbose progress recurse-submodules= verify no-verify'
rebase = 'onto continue abort keep-empty skip edit-todo merge strategy= strategy-option= gpg-sign quiet verbose stat no-stat no-verify verify force-rebase fork-point no-fork-point ignore-whitespace whitespace= committer-date-is-author-date ignore-date interactive preserve-merges exec root autosquash no-autosquash autostash no-autostash no-ff'
reflog = 'stale-fix expire= expire-unreachable= all updateref rewrite verbose'
remote = 'verbose'
reset = 'patch quiet soft mixed hard merge keep'
restore = 'source= patch worktree staged quiet progress no-progress ours theirs merge conflict= ignore-unmerged ignore-skip-worktree-bits overlay no-overlay'
revert = 'edit mainline no-edit no-commit gpg-sign signoff strategy= strategy-option continue quit abort'
rm = 'force dry-run cached ignore-unmatch quiet'
shortlog = 'numbered summary email format='
show = 'pretty= format= abbrev-commit no-abbrev-commit oneline encoding= expand-tabs no-expand-tabs notes no-notes show-notes no-standard-notes standard-notes show-signature name-only name-status stat shortstat numstat'
stash = 'patch no-keep-index keep-index include-untracked all quiet index'
status = 'short branch porcelain long untracked-files ignore-submodules ignored column no-column'
submodule = 'quiet branch force cached files summary-limit remote no-fetch checkout merge rebase init name reference recursive depth'
switch = 'create force-create detach guess no-guess force discard-changes merge conflict= quiet no-progress track no-track orphan ignore-other-worktrees recurse-submodules no-recurse-submodules'
tag = 'annotate sign local-user force delete verify list sort column no-column contains points-at message file cleanup'
whatchanged = 'since'
}
$shortVstsGlobal = 'h o'
$shortVstsParams = @{
abandon = "i $shortVstsGlobal"
create = "d i p r s t $shortVstsGlobal"
complete = "i $shortVstsGlobal"
list = "i p r s t $shortVstsGlobal"
reactivate = "i $shortVstsGlobal"
'set-vote' = "i $shortVstsGlobal"
show = "i $shortVstsGlobal"
update = "d i $shortVstsGlobal"
}
$longVstsGlobal = 'debug help output query verbose'
$longVstsParams = @{
abandon = "id detect instance $longVstsGlobal"
create = "auto-complete delete-source-branch work-items bypass-policy bypass-policy-reason description detect instance merge-commit-message open project repository reviewers source-branch squash target-branch title $longVstsGlobal"
complete = "id detect instance $longVstsGlobal"
list = " $longVstsGlobal"
reactivate = " $longVstsGlobal"
'set-vote' = " $longVstsGlobal"
show = " $longVstsGlobal"
update = " $longVstsGlobal"
}
# Variable is used in GitTabExpansion.ps1
$gitParamValues = @{
blame = @{
encoding = 'utf-8 none'
}
branch = @{
color = 'always never auto'
abbrev = '7 8 9 10'
}
checkout = @{
conflict = 'merge diff3'
}
'cherry-pick' = @{
strategy = 'resolve recursive octopus ours subtree'
}
commit = @{
'cleanup' = 'strip whitespace verbatim scissors default'
}
diff = @{
unified = '0 1 2 3 4 5'
'diff-algorithm' = 'default patience minimal histogram myers'
color = 'always never auto'
'word-diff' = 'color plain porcelain none'
abbrev = '7 8 9 10'
'diff-filter' = 'A C D M R T U X B *'
'inter-hunk-context' = '0 1 2 3 4 5'
'ignore-submodules' = 'none untracked dirty all'
}
difftool = @{
tool = 'vimdiff vimdiff2 araxis bc3 codecompare deltawalker diffmerge diffuse ecmerge emerge gvimdiff gvimdiff2 kdiff3 kompare meld opendiff p4merge tkdiff xxdiff'
}
fetch = @{
'recurse-submodules' = 'yes on-demand no'
'recurse-submodules-default' = 'yes on-demand'
}
init = @{
shared = 'false true umask group all world everybody o'
}
log = @{
decorate = 'short full no'
'no-walk' = 'sorted unsorted'
pretty = {
param($format)
gitConfigKeys 'pretty' $format 'oneline short medium full fuller email raw'
}
format = {
param($format)
gitConfigKeys 'pretty' $format 'oneline short medium full fuller email raw'
}
encoding = 'UTF-8'
date = 'relative local default iso rfc short raw'
}
merge = @{
strategy = 'resolve recursive octopus ours subtree'
log = '1 2 3 4 5 6 7 8 9'
}
mergetool = @{
tool = 'vimdiff vimdiff2 araxis bc3 codecompare deltawalker diffmerge diffuse ecmerge emerge gvimdiff gvimdiff2 kdiff3 kompare meld opendiff p4merge tkdiff xxdiff'
}
notes = @{
strategy = 'manual ours theirs union cat_sort_uniq'
}
pull = @{
strategy = 'resolve recursive octopus ours subtree'
'recurse-submodules' = 'yes on-demand no'
'no-recurse-submodules' = 'yes on-demand no'
rebase = 'false true preserve'
}
push = @{
'recurse-submodules' = 'check on-demand'
}
rebase = @{
strategy = 'resolve recursive octopus ours subtree'
}
restore = @{
conflict = 'merge diff3'
source = {
param($ref)
gitBranches $ref $true
gitTags $ref
}
}
revert = @{
strategy = 'resolve recursive octopus ours subtree'
}
show = @{
pretty = {
param($format)
gitConfigKeys 'pretty' $format 'oneline short medium full fuller email raw'
}
format = {
param($format)
gitConfigKeys 'pretty' $format 'oneline short medium full fuller email raw'
}
encoding = 'utf-8'
}
status = @{
'untracked-files' = 'no normal all'
'ignore-submodules' = 'none untracked dirty all'
}
switch = @{
conflict = 'merge diff3'
}
}
================================================
FILE: src/GitPrompt.ps1
================================================
# Inspired by Mark Embling
# http://www.markembling.info/view/my-ideal-powershell-prompt-with-git-integration
$global:GitPromptSettings = [PoshGitPromptSettings]::new()
$global:GitPromptValues = [PoshGitPromptValues]::new()
# Override some of the normal colors if the background color is set to the default DarkMagenta.
$s = $global:GitPromptSettings
if ($Host.UI.RawUI.BackgroundColor -eq [ConsoleColor]::DarkMagenta) {
$s.LocalDefaultStatusSymbol.ForegroundColor = 'Green'
$s.LocalWorkingStatusSymbol.ForegroundColor = 'Red'
$s.BeforeIndex.ForegroundColor = 'Green'
$s.IndexColor.ForegroundColor = 'Green'
$s.WorkingColor.ForegroundColor = 'Red'
}
<#
.SYNOPSIS
Creates a new instance of a PoshGitPromptSettings object that can be assigned to $GitPromptSettings.
.DESCRIPTION
Creates a new instance of a PoshGitPromptSettings object that can be used to reset the
$GitPromptSettings back to its default.
.INPUTS
None
.OUTPUTS
PoshGitPromptSettings
.EXAMPLE
PS> $GitPromptSettings = New-GitPromptSettings
This will reset the current $GitPromptSettings back to its default.
#>
function New-GitPromptSettings {
[PoshGitPromptSettings]::new()
}
<#
.SYNOPSIS
Writes the object to the display or renders it as a string using ANSI/VT sequences.
.DESCRIPTION
Writes the specified object to the display unless $GitPromptSettings.AnsiConsole
is enabled. In this case, the Object is rendered, along with the specified
colors, as a string with the appropriate ANSI/VT sequences for colors embedded
in the string. If a StringBuilder is provided, the string is appended to the
StringBuilder.
.EXAMPLE
PS C:\> Write-Prompt "PS > " -ForegroundColor Cyan -BackgroundColor Black
On a system where $GitPromptSettings.AnsiConsole is set to $false, this
will write the above to the display using the Write-Host command.
If AnsiConsole is set to $true, this will return a string of the form:
"`e[96m`e[40mPS > `e[0m".
.EXAMPLE
PS C:\> $sb = [System.Text.StringBuilder]::new()
PS C:\> $sb | Write-Prompt "PS > " -ForegroundColor Cyan -BackgroundColor Black
On a system where $GitPromptSettings.AnsiConsole is set to $false, this
will write the above to the display using the Write-Host command.
If AnsiConsole is set to $true, this will append the following string to the
StringBuilder object piped into the command:
"`e[96m`e[40mPS > `e[0m".
#>
function Write-Prompt {
[CmdletBinding(DefaultParameterSetName="Default")]
param(
# Specifies objects to display in the console or render as a string if
# $GitPromptSettings.AnsiConsole is enabled. If the Object is of type
# [PoshGitTextSpan] the other color parameters are ignored since a
# [PoshGitTextSpan] provides the colors.
[Parameter(Mandatory, Position=0)]
$Object,
# Specifies the foreground color.
[Parameter(ParameterSetName="Default")]
$ForegroundColor = $null,
# Specifies the background color.
[Parameter(ParameterSetName="Default")]
$BackgroundColor = $null,
# Specifies both the background and foreground colors via [PoshGitCellColor] object.
[Parameter(ParameterSetName="CellColor")]
[ValidateNotNull()]
[PoshGitCellColor]
$Color,
# When specified and $GitPromptSettings.AnsiConsole is enabled, the Object parameter
# is written to the StringBuilder along with the appropriate ANSI/VT sequences for
# the specified foreground and background colors.
[Parameter(ValueFromPipeline = $true)]
[System.Text.StringBuilder]
$StringBuilder
)
if (!$Object -or (($Object -is [PoshGitTextSpan]) -and !$Object.Text)) {
return $(if ($StringBuilder) { $StringBuilder } else { "" })
}
if ($PSCmdlet.ParameterSetName -eq "CellColor") {
$bgColor = $Color.BackgroundColor
$fgColor = $Color.ForegroundColor
}
else {
$bgColor = $BackgroundColor
$fgColor = $ForegroundColor
}
$s = $global:GitPromptSettings
if ($s) {
if ($null -eq $fgColor) {
$fgColor = $s.DefaultColor.ForegroundColor
}
if ($null -eq $bgColor) {
$bgColor = $s.DefaultColor.BackgroundColor
}
if ($s.AnsiConsole) {
if ($Object -is [PoshGitTextSpan]) {
$str = $Object.ToAnsiString()
}
else {
# If we know which colors were changed, we can reset only these and leave others be.
$reset = [System.Collections.Generic.List[string]]::new()
$e = [char]27 + "["
$fg = $fgColor
if (($null -ne $fg) -and !(Test-VirtualTerminalSequece $fg)) {
$fg = Get-ForegroundVirtualTerminalSequence $fg
$reset.Add('39')
}
$bg = $bgColor
if (($null -ne $bg) -and !(Test-VirtualTerminalSequece $bg)) {
$bg = Get-BackgroundVirtualTerminalSequence $bg
$reset.Add('49')
}
$str = "${Object}"
if (Test-VirtualTerminalSequece $str -Force) {
$reset.Clear()
$reset.Add('0')
}
$str = "${fg}${bg}" + $str
if ($reset.Count -gt 0) {
$str += "${e}$($reset -join ';')m"
}
}
return $(if ($StringBuilder) { $StringBuilder.Append($str) } else { $str })
}
}
if ($Object -is [PoshGitTextSpan]) {
$bgColor = $Object.BackgroundColor
$fgColor = $Object.ForegroundColor
$Object = $Object.Text
}
$writeHostParams = @{
Object = $Object;
NoNewLine = $true;
}
if ($bgColor -and ($bgColor -ge 0) -and ($bgColor -le 15)) {
$writeHostParams.BackgroundColor = $bgColor
}
if ($fgColor -and ($fgColor -ge 0) -and ($fgColor -le 15)) {
$writeHostParams.ForegroundColor = $fgColor
}
Write-Host @writeHostParams
return $(if ($StringBuilder) { $StringBuilder } else { "" })
}
<#
.SYNOPSIS
Writes the Git status for repo. Typically, you use Write-VcsStatus
function instead of this one.
.DESCRIPTION
Writes the Git status for repo. This includes the branch name, branch
status with respect to its remote (if exists), index status, working
dir status, working dir local status and stash count (optional).
Various settings from GitPromptSettngs are used to format and color
the Git status.
On systems that support ANSI terminal sequences, this method will
return a string containing ANSI sequences to color various parts of
the Git status string. This string can be written to the host and
the ANSI sequences will be interpreted and converted to the specified
behaviors which is typically setting the foreground and/or background
color of text.
.EXAMPLE
PS C:\> Write-GitStatus (Get-GitStatus)
Writes the Git status for the current repo.
.INPUTS
System.Management.Automation.PSCustomObject
This is PSCustomObject returned by Get-GitStatus
.OUTPUTS
System.String
This command returns a System.String object.
#>
function Write-GitStatus {
param(
# The Git status object that provides the status information to be written.
# This object is retrieved via the Get-GitStatus command.
[Parameter(Position = 0)]
$Status
)
$s = $global:GitPromptSettings
if (!$Status -or !$s) {
return
}
$sb = [System.Text.StringBuilder]::new(150)
# When prompt is first (default), place the separator before the status summary
if (!$s.DefaultPromptWriteStatusFirst) {
$sb | Write-Prompt $s.PathStatusSeparator.Expand() > $null
}
$sb | Write-Prompt $s.BeforeStatus > $null
$sb | Write-GitBranchName $Status -NoLeadingSpace > $null
$sb | Write-GitBranchStatus $Status > $null
$sb | Write-Prompt $s.BeforeIndex > $null
if ($s.EnableFileStatus -and $Status.HasIndex) {
$sb | Write-GitIndexStatus $Status > $null
if ($Status.HasWorking) {
$sb | Write-Prompt $s.DelimStatus > $null
}
}
if ($s.EnableFileStatus -and $Status.HasWorking) {
$sb | Write-GitWorkingDirStatus $Status > $null
}
$sb | Write-GitWorkingDirStatusSummary $Status > $null
if ($s.EnableStashStatus -and ($Status.StashCount -gt 0)) {
$sb | Write-GitStashCount $Status > $null
}
$sb | Write-Prompt $s.AfterStatus > $null
# When status is first, place the separator after the status summary
if ($s.DefaultPromptWriteStatusFirst) {
$sb | Write-Prompt $s.PathStatusSeparator.Expand() > $null
}
if ($sb.Length -gt 0) {
$sb.ToString()
}
}
<#
.SYNOPSIS
Formats the branch name text according to $GitPromptSettings.
.DESCRIPTION
Formats the branch name text according the $GitPromptSettings:
BranchNameLimit and TruncatedBranchSuffix.
.EXAMPLE
PS C:\> $branchName = Format-GitBranchName (Get-GitStatus).Branch
Gets the branch name formatted as specified by the user's $GitPromptSettings.
.INPUTS
System.String
This is the branch name as a string.
.OUTPUTS
System.String
This command returns a System.String object.
#>
function Format-GitBranchName {
param(
# The branch name to format according to the GitPromptSettings:
# BranchNameLimit and TruncatedBranchSuffix.
[Parameter(Position=0)]
[string]
$BranchName
)
$s = $global:GitPromptSettings
if (!$s -or !$BranchName) {
return "$BranchName"
}
$res = $BranchName
if (($s.BranchNameLimit -gt 0) -and ($BranchName.Length -gt $s.BranchNameLimit))
{
$res = "{0}{1}" -f $BranchName.Substring(0, $s.BranchNameLimit), $s.TruncatedBranchSuffix
}
$res
}
<#
.SYNOPSIS
Gets the colors to use for the branch status.
.DESCRIPTION
Gets the colors to use for the branch status. This color is typically
used for the branch name as well. The default color is specified by
$GitPromptSettins.BranchColor. But depending on the Git status object
passed in, the colors could be changed to match that of one these
other $GitPromptSettings: BranchBehindAndAheadStatusSymbol,
BranchBehindStatusSymbol or BranchAheadStatusSymbol.
.EXAMPLE
PS C:\> $branchStatusColor = Get-GitBranchStatusColor (Get-GitStatus)
Returns a PoshGitTextSpan with the foreground and background colors
for the branch status.
.INPUTS
System.Management.Automation.PSCustomObject
This is PSCustomObject returned by Get-GitStatus
.OUTPUTS
PoshGitTextSpan
A PoshGitTextSpan with colors reflecting those to be used by
branch status symbols.
#>
function Get-GitBranchStatusColor {
param(
# The Git status object that provides branch status information.
# This object is retrieved via the Get-GitStatus command.
[Parameter(Position = 0)]
$Status
)
$s = $global:GitPromptSettings
if (!$s) {
return [PoshGitTextSpan]::new()
}
$branchStatusTextSpan = [PoshGitTextSpan]::new($s.BranchColor)
if (($Status.BehindBy -ge 1) -and ($Status.AheadBy -ge 1)) {
# We are both behind and ahead of remote
$branchStatusTextSpan = [PoshGitTextSpan]::new($s.BranchBehindAndAheadStatusSymbol)
}
elseif ($Status.BehindBy -ge 1) {
# We are behind remote
$branchStatusTextSpan = [PoshGitTextSpan]::new($s.BranchBehindStatusSymbol)
}
elseif ($Status.AheadBy -ge 1) {
# We are ahead of remote
$branchStatusTextSpan = [PoshGitTextSpan]::new($s.BranchAheadStatusSymbol)
}
$branchStatusTextSpan.Text = ''
$branchStatusTextSpan
}
<#
.SYNOPSIS
Writes the branch name given the current Git status.
.DESCRIPTION
Writes the branch name given the current Git status which can retrieved
via the Get-GitStatus command. Branch name can be affected by the
$GitPromptSettings: BranchColor, BranchNameLimit, TruncatedBranchSuffix
and Branch*StatusSymbol colors.
.EXAMPLE
PS C:\> Write-GitBranchName (Get-GitStatus)
Writes the name of the current branch.
.INPUTS
System.Management.Automation.PSCustomObject
This is PSCustomObject returned by Get-GitStatus
.OUTPUTS
System.String, System.Text.StringBuilder
This command returns a System.String object unless the -StringBuilder parameter
is supplied. In this case, it returns a System.Text.StringBuilder.
#>
function Write-GitBranchName {
param(
# The Git status object that provides the status information to be written.
# This object is retrieved via the Get-GitStatus command.
[Parameter(Position = 0)]
$Status,
# If specified the branch name is written into the provided StringBuilder object.
[Parameter(ValueFromPipeline = $true)]
[System.Text.StringBuilder]
$StringBuilder,
# If specified, suppresses the output of the leading space character.
[Parameter()]
[switch]
$NoLeadingSpace
)
$s = $global:GitPromptSettings
if (!$Status -or !$s) {
return $(if ($StringBuilder) { $StringBuilder } else { "" })
}
$str = ""
# Use the branch status colors (or CustomAnsi) to display the branch name
$branchNameTextSpan = Get-GitBranchStatusColor $Status
$branchNameTextSpan.Text = Format-GitBranchName $Status.Branch
if (!$NoLeadingSpace) {
$branchNameTextSpan.Text = " " + $branchNameTextSpan.Text
}
if ($StringBuilder) {
$StringBuilder | Write-Prompt $branchNameTextSpan > $null
}
else {
$str = Write-Prompt $branchNameTextSpan
}
return $(if ($StringBuilder) { $StringBuilder } else { $str })
}
<#
.SYNOPSIS
Writes the branch status text given the current Git status.
.DESCRIPTION
Writes the branch status text given the current Git status which can retrieved
via the Get-GitStatus command. Branch status includes information about the
upstream branch, how far behind and/or ahead the local branch is from the remote.
.EXAMPLE
PS C:\> Write-GitBranchStatus (Get-GitStatus)
Writes the status of the current branch to the host.
.INPUTS
System.Management.Automation.PSCustomObject
This is PSCustomObject returned by Get-GitStatus
.OUTPUTS
System.String, System.Text.StringBuilder
This command returns a System.String object unless the -StringBuilder parameter
is supplied. In this case, it returns a System.Text.StringBuilder.
#>
function Write-GitBranchStatus {
param(
# The Git status object that provides the status information to be written.
# This object is retrieved via the Get-GitStatus command.
[Parameter(Position = 0)]
$Status,
# If specified the branch status is written into the provided StringBuilder object.
[Parameter(ValueFromPipeline = $true)]
[System.Text.StringBuilder]
$StringBuilder,
# If specified, suppresses the output of the leading space character.
[Parameter()]
[switch]
$NoLeadingSpace
)
$s = $global:GitPromptSettings
if (!$Status -or !$s) {
return $(if ($StringBuilder) { $StringBuilder } else { "" })
}
$branchStatusTextSpan = Get-GitBranchStatusColor $Status
if (!$Status.Upstream) {
$branchStatusTextSpan.Text = $s.BranchUntrackedText
}
elseif ($Status.UpstreamGone -eq $true) {
# Upstream branch is gone
$branchStatusTextSpan.Text = $s.BranchGoneStatusSymbol.Text
}
elseif (($Status.BehindBy -eq 0) -and ($Status.AheadBy -eq 0)) {
# We are aligned with remote
$branchStatusTextSpan.Text = $s.BranchIdenticalStatusSymbol.Text
}
elseif (($Status.BehindBy -ge 1) -and ($Status.AheadBy -ge 1)) {
# We are both behind and ahead of remote
if ($s.BranchBehindAndAheadDisplay -eq "Full") {
$branchStatusTextSpan.Text = ("{0}{1} {2}{3}" -f $s.BranchBehindStatusSymbol.Text, $Status.BehindBy, $s.BranchAheadStatusSymbol.Text, $status.AheadBy)
}
elseif ($s.BranchBehindAndAheadDisplay -eq "Compact") {
$branchStatusTextSpan.Text = ("{0}{1}{2}" -f $Status.BehindBy, $s.BranchBehindAndAheadStatusSymbol.Text, $Status.AheadBy)
}
else {
$branchStatusTextSpan.Text = $s.BranchBehindAndAheadStatusSymbol.Text
}
}
elseif ($Status.BehindBy -ge 1) {
# We are behind remote
if (($s.BranchBehindAndAheadDisplay -eq "Full") -Or ($s.BranchBehindAndAheadDisplay -eq "Compact")) {
$branchStatusTextSpan.Text = ("{0}{1}" -f $s.BranchBehindStatusSymbol.Text, $Status.BehindBy)
}
else {
$branchStatusTextSpan.Text = $s.BranchBehindStatusSymbol.Text
}
}
elseif ($Status.AheadBy -ge 1) {
# We are ahead of remote
if (($s.BranchBehindAndAheadDisplay -eq "Full") -or ($s.BranchBehindAndAheadDisplay -eq "Compact")) {
$branchStatusTextSpan.Text = ("{0}{1}" -f $s.BranchAheadStatusSymbol.Text, $Status.AheadBy)
}
else {
$branchStatusTextSpan.Text = $s.BranchAheadStatusSymbol.Text
}
}
else {
# This condition should not be possible but defaulting the variables to be safe
$branchStatusTextSpan.Text = "?"
}
$str = ""
if ($branchStatusTextSpan.Text) {
$textSpan = [PoshGitTextSpan]::new($branchStatusTextSpan)
if (!$NoLeadingSpace) {
$textSpan.Text = " " + $branchStatusTextSpan.Text
}
if ($StringBuilder) {
$StringBuilder | Write-Prompt $textSpan > $null
}
else {
$str = Write-Prompt $textSpan
}
}
return $(if ($StringBuilder) { $StringBuilder } else { $str })
}
<#
.SYNOPSIS
Writes the index status text given the current Git status.
.DESCRIPTION
Writes the index status text given the current Git status.
.EXAMPLE
PS C:\> Write-GitIndexStatus (Get-GitStatus)
Writes the Git index status to the host.
.INPUTS
System.Management.Automation.PSCustomObject
This is PSCustomObject returned by Get-GitStatus
.OUTPUTS
System.String, System.Text.StringBuilder
This command returns a System.String object unless the -StringBuilder parameter
is supplied. In this case, it returns a System.Text.StringBuilder.
#>
function Write-GitIndexStatus {
param(
# The Git status object that provides the status information to be written.
# This object is retrieved via the Get-GitStatus command.
[Parameter(Position = 0)]
$Status,
# If specified the index status is written into the provided StringBuilder object.
[Parameter(ValueFromPipeline = $true)]
[System.Text.StringBuilder]
$StringBuilder,
# If specified, suppresses the output of the leading space character.
[Parameter()]
[switch]
$NoLeadingSpace
)
$s = $global:GitPromptSettings
if (!$Status -or !$s) {
return $(if ($StringBuilder) { $StringBuilder } else { "" })
}
$str = ""
if ($Status.HasIndex) {
if ($s.ShowStatusWhenZero -or $Status.Index.Added) {
$indexStatusText = " "
if ($NoLeadingSpace) {
$indexStatusText = ""
$NoLeadingSpace = $false
}
$indexStatusText += "$($s.FileAddedText)$($Status.Index.Added.Count)"
if ($StringBuilder) {
$StringBuilder | Write-Prompt $indexStatusText -Color $s.IndexColor > $null
}
else {
$str += Write-Prompt $indexStatusText -Color $s.IndexColor
}
}
if ($s.ShowStatusWhenZero -or $status.Index.Modified) {
$indexStatusText = " "
if ($NoLeadingSpace) {
$indexStatusText = ""
$NoLeadingSpace = $false
}
$indexStatusText += "$($s.FileModifiedText)$($status.Index.Modified.Count)"
if ($StringBuilder) {
$StringBuilder | Write-Prompt $indexStatusText -Color $s.IndexColor > $null
}
else {
$str += Write-Prompt $indexStatusText -Color $s.IndexColor
}
}
if ($s.ShowStatusWhenZero -or $Status.Index.Deleted) {
$indexStatusText = " "
if ($NoLeadingSpace) {
$indexStatusText = ""
$NoLeadingSpace = $false
}
$indexStatusText += "$($s.FileRemovedText)$($Status.Index.Deleted.Count)"
if ($StringBuilder) {
$StringBuilder | Write-Prompt $indexStatusText -Color $s.IndexColor > $null
}
else {
$str += Write-Prompt $indexStatusText -Color $s.IndexColor
}
}
if ($Status.Index.Unmerged) {
$indexStatusText = " "
if ($NoLeadingSpace) {
$indexStatusText = ""
$NoLeadingSpace = $false
}
$indexStatusText += "$($s.FileConflictedText)$($Status.Index.Unmerged.Count)"
if ($StringBuilder) {
$StringBuilder | Write-Prompt $indexStatusText -Color $s.IndexColor > $null
}
else {
$str += Write-Prompt $indexStatusText -Color $s.IndexColor
}
}
}
return $(if ($StringBuilder) { $StringBuilder } else { $str })
}
<#
.SYNOPSIS
Writes the working directory status text given the current Git status.
.DESCRIPTION
Writes the working directory status text given the current Git status.
.EXAMPLE
PS C:\> Write-GitWorkingDirStatus (Get-GitStatus)
Writes the Git working directory status to the host.
.INPUTS
System.Management.Automation.PSCustomObject
This is PSCustomObject returned by Get-GitStatus
.OUTPUTS
System.String, System.Text.StringBuilder
This command returns a System.String object unless the -StringBuilder parameter
is supplied. In this case, it returns a System.Text.StringBuilder.
#>
function Write-GitWorkingDirStatus {
param(
# The Git status object that provides the status information to be written.
# This object is retrieved via the Get-GitStatus command.
[Parameter(Position = 0)]
$Status,
# If specified the working dir status is written into the provided StringBuilder object.
[Parameter(ValueFromPipeline = $true)]
[System.Text.StringBuilder]
$StringBuilder,
# If specified, suppresses the output of the leading space character.
[Parameter()]
[switch]
$NoLeadingSpace
)
$s = $global:GitPromptSettings
if (!$Status -or !$s) {
return $(if ($StringBuilder) { $StringBuilder } else { "" })
}
$str = ""
if ($Status.HasWorking) {
if ($s.ShowStatusWhenZero -or $Status.Working.Added) {
$workingStatusText = " "
if ($NoLeadingSpace) {
$workingStatusText = ""
$NoLeadingSpace = $false
}
$workingStatusText += "$($s.FileAddedText)$($Status.Working.Added.Count)"
if ($StringBuilder) {
$StringBuilder | Write-Prompt $workingStatusText -Color $s.WorkingColor > $null
}
else {
$str += Write-Prompt $workingStatusText -Color $s.WorkingColor
}
}
if ($s.ShowStatusWhenZero -or $Status.Working.Modified) {
$workingStatusText = " "
if ($NoLeadingSpace) {
$workingStatusText = ""
$NoLeadingSpace = $false
}
$workingStatusText += "$($s.FileModifiedText)$($Status.Working.Modified.Count)"
if ($StringBuilder) {
$StringBuilder | Write-Prompt $workingStatusText -Color $s.WorkingColor > $null
}
else {
$str += Write-Prompt $workingStatusText -Color $s.WorkingColor
}
}
if ($s.ShowStatusWhenZero -or $Status.Working.Deleted) {
$workingStatusText = " "
if ($NoLeadingSpace) {
$workingStatusText = ""
$NoLeadingSpace = $false
}
$workingStatusText += "$($s.FileRemovedText)$($Status.Working.Deleted.Count)"
if ($StringBuilder) {
$StringBuilder | Write-Prompt $workingStatusText -Color $s.WorkingColor > $null
}
else {
$str += Write-Prompt $workingStatusText -Color $s.WorkingColor
}
}
if ($Status.Working.Unmerged) {
$workingStatusText = " "
if ($NoLeadingSpace) {
$workingStatusText = ""
$NoLeadingSpace = $false
}
$workingStatusText += "$($s.FileConflictedText)$($Status.Working.Unmerged.Count)"
if ($StringBuilder) {
$StringBuilder | Write-Prompt $workingStatusText -Color $s.WorkingColor > $null
}
else {
$str += Write-Prompt $workingStatusText -Color $s.WorkingColor
}
}
}
return $(if ($StringBuilder) { $StringBuilder } else { $str })
}
<#
.SYNOPSIS
Writes the working directory status summary text given the current Git status.
.DESCRIPTION
Writes the working directory status summary text given the current Git status.
If there are any unstaged commits, the $GitPromptSettings.LocalWorkingStatusSymbol
will be output. If not, then if are any staged but uncommmited changes, the
$GitPromptSettings.LocalStagedStatusSymbol will be output. If not, then
$GitPromptSettings.LocalDefaultStatusSymbol will be output.
.EXAMPLE
PS C:\> Write-GitWorkingDirStatusSummary (Get-GitStatus)
Outputs the Git working directory status summary text.
.INPUTS
System.Management.Automation.PSCustomObject
This is PSCustomObject returned by Get-GitStatus
.OUTPUTS
System.String, System.Text.StringBuilder
This command returns a System.String object unless the -StringBuilder parameter
is supplied. In this case, it returns a System.Text.StringBuilder.
#>
function Write-GitWorkingDirStatusSummary {
param(
# The Git status object that provides the status information to be written.
# This object is retrieved via the Get-GitStatus command.
[Parameter(Position = 0)]
$Status,
# If specified the working dir local status is written into the provided StringBuilder object.
[Parameter(ValueFromPipeline = $true)]
[System.Text.StringBuilder]
$StringBuilder,
# If specified, suppresses the output of the leading space character.
[Parameter()]
[switch]
$NoLeadingSpace
)
$s = $global:GitPromptSettings
if (!$Status -or !$s) {
return $(if ($StringBuilder) { $StringBuilder } else { "" })
}
$str = ""
# No uncommited changes
$localStatusSymbol = $s.LocalDefaultStatusSymbol
if ($Status.HasWorking) {
# We have un-staged files in the working tree
$localStatusSymbol = $s.LocalWorkingStatusSymbol
}
elseif ($Status.HasIndex) {
# We have staged but uncommited files
$localStatusSymbol = $s.LocalStagedStatusSymbol
}
if ($localStatusSymbol.Text) {
$textSpan = [PoshGitTextSpan]::new($localStatusSymbol)
if (!$NoLeadingSpace) {
$textSpan.Text = " " + $localStatusSymbol.Text
}
if ($StringBuilder) {
$StringBuilder | Write-Prompt $textSpan > $null
}
else {
$str += Write-Prompt $textSpan
}
}
return $(if ($StringBuilder) { $StringBuilder } else { $str })
}
<#
.SYNOPSIS
Writes the stash count given the current Git status.
.DESCRIPTION
Writes the stash count given the current Git status.
.EXAMPLE
PS C:\> Write-GitStashCount (Get-GitStatus)
Writes the Git stash count to the host.
.INPUTS
System.Management.Automation.PSCustomObject
This is PSCustomObject returned by Get-GitStatus
.OUTPUTS
System.String, System.Text.StringBuilder
This command returns a System.String object unless the -StringBuilder parameter
is supplied. In this case, it returns a System.Text.StringBuilder.
#>
function Write-GitStashCount {
param(
# The Git status object that provides the status information to be written.
# This object is retrieved via the Get-GitStatus command.
[Parameter(Position = 0)]
$Status,
# If specified the working dir local status is written into the provided StringBuilder object.
[Parameter(ValueFromPipeline = $true)]
[System.Text.StringBuilder]
$StringBuilder
)
$s = $global:GitPromptSettings
if (!$Status -or !$s) {
return $(if ($StringBuilder) { $StringBuilder } else { "" })
}
$str = ""
if ($Status.StashCount -gt 0) {
$stashText = "$($Status.StashCount)"
if ($StringBuilder) {
$StringBuilder | Write-Prompt $s.BeforeStash > $null
$StringBuilder | Write-Prompt $stashText -Color $s.StashColor > $null
$StringBuilder | Write-Prompt $s.AfterStash > $null
}
else {
$str += Write-Prompt $s.BeforeStash
$str += Write-Prompt $stashText -Color $s.StashColor
$str += Write-Prompt $s.AfterStash
}
}
return $(if ($StringBuilder) { $StringBuilder } else { $str })
}
if (!(Test-Path Variable:Global:VcsPromptStatuses)) {
$global:VcsPromptStatuses = @()
}
<#
.SYNOPSIS
Writes all version control prompt statuses configured in $global:VcsPromptStatuses.
.DESCRIPTION
Writes all version control prompt statuses configured in $global:VcsPromptStatuses.
By default, this includes the PoshGit prompt status.
.EXAMPLE
PS C:\> Write-VcsStatus
Writes all version control prompt statuses that have been configured
with the global variable $VcsPromptStatuses
#>
function Global:Write-VcsStatus {
Set-ConsoleMode -ANSI
$OFS = ""
$sb = [System.Text.StringBuilder]::new(256)
foreach ($promptStatus in $global:VcsPromptStatuses) {
[void]$sb.Append("$(& $promptStatus)")
}
if ($sb.Length -gt 0) {
$sb.ToString()
}
}
# Add scriptblock that will execute for Write-VcsStatus
$PoshGitVcsPrompt = {
try {
$global:GitStatus = Get-GitStatus
Write-GitStatus $GitStatus
}
catch {
$s = $global:GitPromptSettings
if ($s) {
$errorText = "PoshGitVcsPrompt error: $_"
$sb = [System.Text.StringBuilder]::new()
# When prompt is first (default), place the separator before the status summary
if (!$s.DefaultPromptWriteStatusFirst) {
$sb | Write-Prompt $s.PathStatusSeparator.Expand() > $null
}
$sb | Write-Prompt $s.BeforeStatus > $null
$sb | Write-Prompt $errorText -Color $s.ErrorColor > $null
if ($s.Debug) {
if (!$s.AnsiConsole) { Write-Host }
Write-Verbose "PoshGitVcsPrompt error details: $($_ | Format-List * -Force | Out-String)" -Verbose
}
$sb | Write-Prompt $s.AfterStatus > $null
if ($sb.Length -gt 0) {
$sb.ToString()
}
}
}
}
$global:VcsPromptStatuses += $PoshGitVcsPrompt
================================================
FILE: src/GitTabExpansion.ps1
================================================
# Initial implementation by Jeremy Skinner
# http://www.jeremyskinner.co.uk/2010/03/07/using-git-with-windows-powershell/
$Global:GitTabSettings = New-Object PSObject -Property @{
AllCommands = $false
KnownAliases = @{
'!f() { exec vsts code pr "$@"; }; f' = 'vsts.pr'
}
EnableLogging = $false
LogPath = Join-Path ([System.IO.Path]::GetTempPath()) posh-git_tabexp.log
RegisteredCommands = ""
}
$subcommands = @{
bisect = "start bad good skip reset visualize replay log run"
notes = 'add append copy edit get-ref list merge prune remove show'
'vsts.pr' = 'create update show list complete abandon reactivate reviewers work-items set-vote policies'
reflog = "show delete expire"
remote = "
add rename remove set-head set-branches
get-url set-url show prune update
"
rerere = "clear forget diff remaining status gc"
stash = 'push save list show apply clear drop pop create branch'
submodule = "add status init deinit update summary foreach sync"
svn = "
init fetch clone rebase dcommit log find-rev
set-tree commit-diff info create-ignore propget
proplist show-ignore show-externals branch tag blame
migrate mkdirs reset gc
"
tfs = "
list-remote-branches clone quick-clone bootstrap init
clone fetch pull quick-clone unshelve shelve-list labels
rcheckin checkin checkintool shelve shelve-delete
branch
info cleanup cleanup-workspaces help verify autotag subtree reset-remote checkout
"
flow = "init feature bugfix release hotfix support help version"
worktree = "add list lock move prune remove unlock"
}
$gitflowsubcommands = @{
init = 'help'
feature = 'list start finish publish track diff rebase checkout pull help delete'
bugfix = 'list start finish publish track diff rebase checkout pull help delete'
release = 'list start finish track publish help delete'
hotfix = 'list start finish track publish help delete'
support = 'list start help'
config = 'list set base'
}
function script:gitCmdOperations($commands, $command, $filter) {
$commands[$command].Trim() -split '\s+' | Where-Object { $_ -like "$filter*" }
}
$script:someCommands = @('add','am','annotate','archive','bisect','blame','branch','bundle','checkout','cherry',
'cherry-pick','citool','clean','clone','commit','config','describe','diff','difftool','fetch',
'format-patch','gc','grep','gui','help','init','instaweb','log','merge','mergetool','mv',
'notes','prune','pull','push','rebase','reflog','remote','rerere','reset','restore','revert','rm',
'shortlog','show','stash','status','submodule','svn','switch','tag','whatchanged', 'worktree')
if ((($PSVersionTable.PSVersion.Major -eq 5) -or $IsWindows) -and ($script:GitVersion -ge [System.Version]'2.16.2')) {
$script:someCommands += 'update-git-for-windows'
}
$script:gitCommandsWithLongParams = $longGitParams.Keys -join '|'
$script:gitCommandsWithShortParams = $shortGitParams.Keys -join '|'
$script:gitCommandsWithParamValues = $gitParamValues.Keys -join '|'
$script:vstsCommandsWithShortParams = $shortVstsParams.Keys -join '|'
$script:vstsCommandsWithLongParams = $longVstsParams.Keys -join '|'
# The regular expression here is roughly follows this pattern:
#
# <begin anchor><whitespace>*<git>(<whitespace><parameter>)*<whitespace>+<$args><whitespace>*<end anchor>
#
# The delimiters inside the parameter list and between some of the elements are non-newline whitespace characters ([^\S\r\n]).
# In those instances, newlines are only allowed if they preceded by a non-newline whitespace character.
#
# Begin anchor (^|[;`n])
# Whitespace (\s*)
# Git Command (?<cmd>$(GetAliasPattern git))
# Parameters (?<params>(([^\S\r\n]|[^\S\r\n]``\r?\n)+\S+)*)
# $args Anchor (([^\S\r\n]|[^\S\r\n]``\r?\n)+\`$args)
# Whitespace (\s|``\r?\n)*
# End Anchor ($|[|;`n])
$script:GitProxyFunctionRegex = "(^|[;`n])(\s*)(?<cmd>$(Get-AliasPattern git))(?<params>(([^\S\r\n]|[^\S\r\n]``\r?\n)+\S+)*)(([^\S\r\n]|[^\S\r\n]``\r?\n)+\`$args)(\s|``\r?\n)*($|[|;`n])"
try {
if ($null -ne (git help -a 2>&1 | Select-String flow)) {
$script:someCommands += 'flow'
}
}
catch {
Write-Debug "Search for 'flow' in 'git help' output failed with error: $_"
}
filter quoteStringWithSpecialChars {
if ($_ -and ($_ -match '\s+|#|@|\$|;|,|''|\{|\}|\(|\)')) {
$str = $_ -replace "'", "''"
"'$str'"
}
else {
$_
}
}
function script:gitCommands($filter, $includeAliases) {
$cmdList = @()
if (-not $global:GitTabSettings.AllCommands) {
$cmdList += $someCommands -like "$filter*"
}
else {
$cmdList += git help --all |
Where-Object { $_ -match '^\s{2,}\S.*' } |
ForEach-Object { $_.Split(' ', [StringSplitOptions]::RemoveEmptyEntries) } |
Where-Object { $_ -like "$filter*" }
}
if ($includeAliases) {
$cmdList += gitAliases $filter
}
$cmdList | Sort-Object
}
function script:gitRemotes($filter) {
git remote |
Where-Object { $_ -like "$filter*" } |
quoteStringWithSpecialChars
}
function script:gitBranches($filter, $includeHEAD = $false, $prefix = '') {
if ($filter -match "^(?<from>\S*\.{2,3})(?<to>.*)") {
$prefix += $matches['from']
$filter = $matches['to']
}
$branches = @(git branch --no-color | ForEach-Object { if (($_ -notmatch "^\* \(HEAD detached .+\)$") -and ($_ -match "^[\*\+]?\s*(?<ref>\S+)(?: -> .+)?")) { $matches['ref'] } }) +
@(git branch --no-color -r | ForEach-Object { if ($_ -match "^ (?<ref>\S+)(?: -> .+)?") { $matches['ref'] } }) +
@(if ($includeHEAD) { 'HEAD','FETCH_HEAD','ORIG_HEAD','MERGE_HEAD' })
$branches |
Where-Object { $_ -ne '(no branch)' -and $_ -like "$filter*" } |
ForEach-Object { $prefix + $_ } |
quoteStringWithSpecialChars
}
function script:gitRemoteUniqueBranches($filter) {
git branch --no-color -r |
ForEach-Object { if ($_ -match "^ (?<remote>[^/]+)/(?<branch>\S+)(?! -> .+)?$") { $matches['branch'] } } |
Group-Object -NoElement |
Where-Object { $_.Count -eq 1 } |
Select-Object -ExpandProperty Name |
Where-Object { $_ -like "$filter*" } |
quoteStringWithSpecialChars
}
function script:gitConfigKeys($section, $filter, $defaultOptions = '') {
$completions = @($defaultOptions -split ' ')
git config --name-only --get-regexp ^$section\..* |
ForEach-Object { $completions += ($_ -replace "$section\.","") }
return $completions |
Where-Object { $_ -like "$filter*" } |
Sort-Object |
quoteStringWithSpecialChars
}
function script:gitTags($filter, $prefix = '') {
git tag |
Where-Object { $_ -like "$filter*" } |
ForEach-Object { $prefix + $_ } |
quoteStringWithSpecialChars
}
function script:gitFeatures($filter, $command) {
$featurePrefix = git config --local --get "gitflow.prefix.$command"
$branches = @(git branch --no-color | ForEach-Object { if ($_ -match "^\*?\s*$featurePrefix(?<ref>.*)") { $matches['ref'] } })
$branches |
Where-Object { $_ -ne '(no branch)' -and $_ -like "$filter*" } |
ForEach-Object { $featurePrefix + $_ } |
quoteStringWithSpecialChars
}
function script:gitRemoteBranches($remote, $ref, $filter, $prefix = '') {
git branch --no-color -r |
Where-Object { $_ -like " $remote/$filter*" } |
ForEach-Object { $prefix + $ref + ($_ -replace " $remote/","") } |
quoteStringWithSpecialChars
}
function script:gitStashes($filter) {
(git stash list) -replace ':.*','' |
Where-Object { $_ -like "$filter*" } |
quoteStringWithSpecialChars
}
function script:gitTfsShelvesets($filter) {
(git tfs shelve-list) |
Where-Object { $_ -like "$filter*" } |
quoteStringWithSpecialChars
}
function script:gitFiles($filter, $files) {
$files | Sort-Object |
Where-Object { $_ -like "$filter*" } |
quoteStringWithSpecialChars
}
function script:gitIndex($GitStatus, $filter) {
gitFiles $filter $GitStatus.Index
}
function script:gitAddFiles($GitStatus, $filter) {
gitFiles $filter (@($GitStatus.Working.Unmerged) + @($GitStatus.Working.Modified) + @($GitStatus.Working.Added))
}
function script:gitCheckoutFiles($GitStatus, $filter) {
gitFiles $filter (@($GitStatus.Working.Unmerged) + @($GitStatus.Working.Modified) + @($GitStatus.Working.Deleted))
}
function script:gitDeleted($GitStatus, $filter) {
gitFiles $filter $GitStatus.Working.Deleted
}
function script:gitDiffFiles($GitStatus, $filter, $staged) {
if ($staged) {
gitFiles $filter $GitStatus.Index.Modified
}
else {
gitFiles $filter (@($GitStatus.Working.Unmerged) + @($GitStatus.Working.Modified) + @($GitStatus.Index.Modified))
}
}
function script:gitMergeFiles($GitStatus, $filter) {
gitFiles $filter $GitStatus.Working.Unmerged
}
function script:gitRestoreFiles($GitStatus, $filter, $staged) {
if ($staged) {
gitFiles $filter (@($GitStatus.Index.Added) + @($GitStatus.Index.Modified) + @($GitStatus.Index.Deleted))
}
else {
gitFiles $filter (@($GitStatus.Working.Unmerged) + @($GitStatus.Working.Modified) + @($GitStatus.Working.Deleted))
}
}
function script:gitAliases($filter) {
git config --get-regexp ^alias\. | ForEach-Object{
if ($_ -match "^alias\.(?<alias>\S+) .*") {
$alias = $Matches['alias']
if ($alias -like "$filter*") {
$alias
}
}
} | Sort-Object -Unique
}
function script:expandGitAlias($cmd, $rest) {
$alias = git config "alias.$cmd"
if ($alias) {
$known = $Global:GitTabSettings.KnownAliases[$alias]
if ($known) {
return "git $known$rest"
}
return "git $alias$rest"
}
else {
return "git $cmd$rest"
}
}
function script:expandLongParams($hash, $cmd, $filter) {
$hash[$cmd].Trim() -split ' ' |
Where-Object { $_ -like "$filter*" } |
Sort-Object |
ForEach-Object { -join ("--", $_) }
}
function script:expandShortParams($hash, $cmd, $filter) {
$hash[$cmd].Trim() -split ' ' |
Where-Object { $_ -like "$filter*" } |
Sort-Object |
ForEach-Object { -join ("-", $_) }
}
function script:expandParamValues($cmd, $param, $filter) {
$paramValues = $gitParamValues[$cmd][$param]
$completions = if ($paramValues -is [scriptblock]) {
& $paramValues $filter
}
else {
$paramValues.Trim() -split ' ' | Where-Object { $_ -like "$filter*" } | Sort-Object
}
$completions | ForEach-Object { -join ("--", $param, "=", $_) }
}
function Expand-GitCommand($Command) {
# Parse all Git output as UTF8, including tab completion output - https://github.com/dahlbyk/posh-git/pull/359
$res = Invoke-Utf8ConsoleCommand { GitTabExpansionInternal $Command $Global:GitStatus }
$res
}
function GitTabExpansionInternal($lastBlock, $GitStatus = $null) {
$ignoreGitParams = '(?<params>\s+-(?:[aA-zZ0-9]+|-[aA-zZ0-9][aA-zZ0-9-]*)(?:=\S+)?)*'
if ($lastBlock -match "^$(Get-AliasPattern git) (?<cmd>\S+)(?<args> .*)$") {
$lastBlock = expandGitAlias $Matches['cmd'] $Matches['args']
}
# Handles tgit <command> (tortoisegit)
if ($lastBlock -match "^$(Get-AliasPattern tgit) (?<cmd>\S*)$") {
# Need return statement to prevent fall-through.
return $Global:TortoiseGitSettings.TortoiseGitCommands.Keys.GetEnumerator() | Sort-Object | Where-Object { $_ -like "$($matches['cmd'])*" }
}
# Handles gitk
if ($lastBlock -match "^$(Get-AliasPattern gitk).* (?<ref>\S*)$") {
return gitBranches $matches['ref'] $true
}
switch -regex ($lastBlock -replace "^$(Get-AliasPattern git) ","") {
# Handles git <cmd> <op>
"^(?<cmd>$($subcommands.Keys -join '|'))\s+(?<op>\S*)$" {
gitCmdOperations $subcommands $matches['cmd'] $matches['op']
}
# Handles git flow <cmd> <op>
"^flow (?<cmd>$($gitflowsubcommands.Keys -join '|'))\s+(?<op>\S*)$" {
gitCmdOperations $gitflowsubcommands $matches['cmd'] $matches['op']
}
# Handles git flow <command> <op> <name>
"^flow (?<command>\S*)\s+(?<op>\S*)\s+(?<name>\S*)$" {
gitFeatures $matches['name'] $matches['command']
}
# Handles git remote (rename|rm|set-head|set-branches|set-url|show|prune) <stash>
"^remote.* (?:rename|rm|set-head|set-branches|set-url|show|prune).* (?<remote>\S*)$" {
gitRemotes $matches['remote']
}
# Handles git stash (show|apply|drop|pop|branch) <stash>
"^stash (?:show|apply|drop|pop|branch).* (?<stash>\S*)$" {
gitStashes $matches['stash']
}
# Handles git bisect (bad|good|reset|skip) <ref>
"^bisect (?:bad|good|reset|skip).* (?<ref>\S*)$" {
gitBranches $matches['ref'] $true
}
# Handles git tfs unshelve <shelveset>
"^tfs +unshelve.* (?<shelveset>\S*)$" {
gitTfsShelvesets $matches['shelveset']
}
# Handles git branch -d|-D|-m|-M <branch name>
# Handles git branch <branch name> <start-point>
"^branch.* (?<branch>\S*)$" {
gitBranches $matches['branch']
}
# Handles git <cmd> (commands & aliases)
"^(?<cmd>\S*)$" {
gitCommands $matches['cmd'] $TRUE
}
# Handles git help <cmd> (commands only)
"^help (?<cmd>\S*)$" {
gitCommands $matches['cmd'] $FALSE
}
# Handles git push remote <ref>:<branch>
# Handles git push remote +<ref>:<branch>
"^push${ignoreGitParams}\s+(?<remote>[^\s-]\S*).*\s+(?<force>\+?)(?<ref>[^\s\:]*\:)(?<branch>\S*)$" {
gitRemoteBranches $matches['remote'] $matches['ref'] $matches['branch'] -prefix $matches['force']
}
# Handles git push remote <ref>
# Handles git push remote +<ref>
# Handles git pull remote <ref>
"^(?:push|pull)${ignoreGitParams}\s+(?<remote>[^\s-]\S*).*\s+(?<force>\+?)(?<ref>[^\s\:]*)$" {
gitBranches $matches['ref'] -prefix $matches['force']
gitTags $matches['ref'] -prefix $matches['force']
}
# Handles git pull <remote>
# Handles git push <remote>
# Handles git fetch <remote>
"^(?:push|pull|fetch)${ignoreGitParams}\s+(?<remote>\S*)$" {
gitRemotes $matches['remote']
}
# Handles git reset HEAD <path>
# Handles git reset HEAD -- <path>
"^reset.* HEAD(?:\s+--)? (?<path>\S*)$" {
gitIndex $GitStatus $matches['path']
}
# Handles git <cmd> <ref>
"^commit.*-C\s+(?<ref>\S*)$" {
gitBranches $matches['ref'] $true
}
# Handles git add <path>
"^add.* (?<files>\S*)$" {
gitAddFiles $GitStatus $matches['files']
}
# Handles git checkout -- <path>
"^checkout.* -- (?<files>\S*)$" {
gitCheckoutFiles $GitStatus $matches['files']
}
# Handles git restore -s <ref> / --source=<ref> - must come before the next regex case
"^restore.* (?-i)(-s\s*|(?<source>--source=))(?<ref>\S*)$" {
gitBranches $matches['ref'] $true $matches['source']
gitTags $matches['ref']
break
}
# Handles git restore <path>
"^restore(?:.* (?<staged>(?:(?-i)-S|--staged))|.*) (?<files>\S*)$" {
gitRestoreFiles $GitStatus $matches['files'] $matches['staged']
}
# Handles git rm <path>
"^rm.* (?<index>\S*)$" {
gitDeleted $GitStatus $matches['index']
}
# Handles git diff/difftool <path>
"^(?:diff|difftool)(?:.* (?<staged>(?:--cached|--staged))|.*) (?<files>\S*)$" {
gitDiffFiles $GitStatus $matches['files'] $matches['staged']
}
# Handles git merge/mergetool <path>
"^(?:merge|mergetool).* (?<files>\S*)$" {
gitMergeFiles $GitStatus $matches['files']
}
# Handles git checkout|switch <ref>
"^(?:checkout|switch).* (?<ref>\S*)$" {
& {
gitBranches $matches['ref'] $true
gitRemoteUniqueBranches $matches['ref']
gitTags $matches['ref']
# Return only unique branches (to eliminate duplicates where the branch exists locally and on the remote)
} | Select-Object -Unique
}
# Handles git worktree add <path> <ref>
"^worktree add.* (?<files>\S+) (?<ref>\S*)$" {
gitBranches $matches['ref']
}
# Handles git <cmd> <ref>
"^(?:cherry|cherry-pick|diff|difftool|log|merge|rebase|reflog\s+show|reset|revert|show).* (?<ref>\S*)$" {
gitBranches $matches['ref'] $true
gitTags $matches['ref']
}
# Handles git <cmd> --<param>=<value>
"^(?<cmd>$gitCommandsWithParamValues).* --(?<param>[^=]+)=(?<value>\S*)$" {
expandParamValues $matches['cmd'] $matches['param'] $matches['value']
}
# Handles git <cmd> --<param>
"^(?<cmd>$gitCommandsWithLongParams).* --(?<param>\S*)$" {
expandLongParams $longGitParams $matches['cmd'] $matches['param']
}
# Handles git <cmd> -<shortparam>
"^(?<cmd>$gitCommandsWithShortParams).* -(?<shortparam>\S*)$" {
expandShortParams $shortGitParams $matches['cmd'] $matches['shortparam']
}
# Handles git pr alias
"vsts\.pr\s+(?<op>\S*)$" {
gitCmdOperations $subcommands 'vsts.pr' $matches['op']
}
# Handles git pr <cmd> --<param>
"vsts\.pr\s+(?<cmd>$vstsCommandsWithLongParams).*--(?<param>\S*)$"
{
expandLongParams $longVstsParams $matches['cmd'] $matches['param']
}
# Handles git pr <cmd> -<shortparam>
"vsts\.pr\s+(?<cmd>$vstsCommandsWithShortParams).*-(?<shortparam>\S*)$"
{
expandShortParams $shortVstsParams $matches['cmd'] $matches['shortparam']
}
}
}
function Expand-GitProxyFunction($command) {
# Make sure the incoming command matches: <Command> <Args>, so we can extract the alias/command
# name and the arguments being passed in.
if ($command -notmatch '^(?<command>\S+)([^\S\r\n]|[^\S\r\n]`\r?\n)+(?<args>([^\S\r\n]|[^\S\r\n]`\r?\n|\S)*)$') {
return $command
}
# Store arguments for replacement later
$arguments = $matches['args']
# Get the command name; if an alias exists, get the actual command name
$commandName = $matches['command']
if (Test-Path -Path Alias:\$commandName) {
$commandName = Get-Item -Path Alias:\$commandName | Select-Object -ExpandProperty 'ResolvedCommandName'
}
# Extract definition of git usage
if (Test-Path -Path Function:\$commandName) {
$definition = Get-Item -Path Function:\$commandName | Select-Object -ExpandProperty 'Definition'
if ($definition -match $script:GitProxyFunctionRegex) {
# Clean up the command by removing extra delimiting whitespace and backtick preceding newlines
return (("$($matches['cmd'].TrimStart()) $($matches['params']) $arguments") -replace '`\r?\n', ' ' -replace '\s+', ' ')
}
}
return $command
}
function WriteTabExpLog([string] $Message) {
if (!$global:GitTabSettings.EnableLogging) { return }
$timestamp = Get-Date -Format HH:mm:ss
"[$timestamp] $Message" | Out-File -Append $global:GitTabSettings.LogPath
}
if (!$UseLegacyTabExpansion -and ($PSVersionTable.PSVersion.Major -ge 6)) {
$cmdNames = "git","tgit","gitk"
# Create regex pattern from $cmdNames: ^(git|git\.exe|tgit|tgit\.exe|gitk|gitk\.exe)$
$cmdNamesPattern = "^($($cmdNames -join '|'))(\.exe)?$"
$cmdNames += Get-Alias | Where-Object { $_.Definition -match $cmdNamesPattern } | Foreach-Object Name
if ($EnableProxyFunctionExpansion) {
$funcNames += Get-ChildItem -Path Function:\ | Where-Object { $_.Definition -match $script:GitProxyFunctionRegex } | Foreach-Object Name
$cmdNames += $funcNames
# Create regex pattern from $funcNames e.g.: ^(Git-Checkout|Git-Switch)$
$funcNamesPattern = "^($($funcNames -join '|'))$"
$cmdNames += Get-Alias | Where-Object { $_.Definition -match $funcNamesPattern } | Foreach-Object Name
}
$global:GitTabSettings.RegisteredCommands = $cmdNames -join ", "
Microsoft.PowerShell.Core\Register-ArgumentCompleter -CommandName $cmdNames -Native -ScriptBlock {
param($wordToComplete, $commandAst, $cursorPosition)
# The PowerShell completion has a habit of stripping the trailing space when completing:
# git checkout <tab>
# The Expand-GitCommand expects this trailing space, so pad with a space if necessary.
$padLength = $cursorPosition - $commandAst.Extent.StartOffset
$textToComplete = $commandAst.ToString().PadRight($padLength, ' ').Substring(0, $padLength)
if ($EnableProxyFunctionExpansion) {
$textToComplete = Expand-GitProxyFunction($textToComplete)
}
WriteTabExpLog "Expand: command: '$($commandAst.Extent.Text)', padded: '$textToComplete', padlen: $padLength"
Expand-GitCommand $textToComplete
}
}
else {
$PowerTab_RegisterTabExpansion = if (Get-Module -Name powertab) { Get-Command Register-TabExpansion -Module powertab -ErrorAction SilentlyContinue }
if ($PowerTab_RegisterTabExpansion) {
& $PowerTab_RegisterTabExpansion git -Type Command {
param($Context, [ref]$TabExpansionHasOutput, [ref]$QuoteSpaces)
$line = $Context.Line
$lastBlock = [regex]::Split($line, '[|;]')[-1].TrimStart()
if ($EnableProxyFunctionExpansion) {
$lastBlock = Expand-GitProxyFunction($lastBlock)
}
$TabExpansionHasOutput.Value = $true
WriteTabExpLog "PowerTab expand: '$lastBlock'"
Expand-GitCommand $lastBlock
}
return
}
function TabExpansion($line, $lastWord) {
$lastBlock = [regex]::Split($line, '[|;]')[-1].TrimStart()
if ($EnableProxyFunctionExpansion) {
$lastBlock = Expand-GitProxyFunction($lastBlock)
}
$msg = "Legacy expand: '$lastBlock'"
switch -regex ($lastBlock) {
# Execute git tab completion for all git-related commands
"^$(Get-AliasPattern git) (.*)" { WriteTabExpLog $msg; Expand-GitCommand $lastBlock }
"^$(Get-AliasPattern tgit) (.*)" { WriteTabExpLog $msg; Expand-GitCommand $lastBlock }
"^$(Get-AliasPattern gitk) (.*)" { WriteTabExpLog $msg; Expand-GitCommand $lastBlock }
}
}
}
# Handles Remove-GitBranch -Name parameter auto-completion using the built-in mechanism for cmdlet parameters
Microsoft.PowerShell.Core\Register-ArgumentCompleter -CommandName Remove-GitBranch -ParameterName Name -ScriptBlock {
param($Command, $Parameter, $WordToComplete, $CommandAst, $FakeBoundParams)
gitBranches $WordToComplete $true
}
================================================
FILE: src/GitUtils.ps1
================================================
# Inspired by Mark Embling
# http://www.markembling.info/view/my-ideal-powershell-prompt-with-git-integration
<#
.SYNOPSIS
Gets the path to the current repository's .git dir.
.DESCRIPTION
Gets the path to the current repository's .git dir. Or if the repository
is a bare repository, the root directory of the bare repository.
.EXAMPLE
PS C:\GitHub\posh-git\tests> Get-GitDirectory
Returns C:\GitHub\posh-git\.git
.INPUTS
None.
.OUTPUTS
System.String
#>
function Get-GitDirectory {
$pathInfo = Microsoft.PowerShell.Management\Get-Location
if (!$pathInfo -or ($pathInfo.Provider.Name -ne 'FileSystem')) {
$null
}
elseif ($Env:GIT_DIR) {
$Env:GIT_DIR -replace '\\|/', [System.IO.Path]::DirectorySeparatorChar
}
else {
$currentDir = Get-Item -LiteralPath $pathInfo -Force
while ($currentDir) {
$gitDirPath = Join-Path $currentDir.FullName .git
if (Test-Path -LiteralPath $gitDirPath -PathType Container) {
return $gitDirPath
}
# Handle the worktree case where .git is a file
if (Test-Path -LiteralPath $gitDirPath -PathType Leaf) {
$gitDirPath = Invoke-Utf8ConsoleCommand { git rev-parse --git-dir 2>$null }
if ($gitDirPath) {
return $gitDirPath
}
}
$headPath = Join-Path $currentDir.FullName HEAD
if (Test-Path -LiteralPath $headPath -PathType Leaf) {
$refsPath = Join-Path $currentDir.FullName refs
$objsPath = Join-Path $currentDir.FullName objects
if ((Test-Path -LiteralPath $refsPath -PathType Container) -and
(Test-Path -LiteralPath $objsPath -PathType Container)) {
$bareDir = Invoke-Utf8ConsoleCommand { git rev-parse --git-dir 2>$null }
if ($bareDir -and (Test-Path -LiteralPath $bareDir -PathType Container)) {
$resolvedBareDir = (Resolve-Path $bareDir).Path
return $resolvedBareDir
}
}
}
$currentDir = $currentDir.Parent
}
}
}
function Get-GitBranch($branch = $null, $gitDir = $(Get-GitDirectory), [switch]$isDotGitOrBare, [Diagnostics.Stopwatch]$sw) {
if (!$gitDir) { return }
Invoke-Utf8ConsoleCommand {
dbg 'Finding branch' $sw
$r = ''; $b = ''; $c = ''
$step = ''; $total = ''
if (Test-Path $gitDir/rebase-merge) {
dbg 'Found rebase-merge' $sw
if (Test-Path $gitDir/rebase-merge/interactive) {
dbg 'Found rebase-merge/interactive' $sw
$r = '|REBASE-i'
}
else {
$r = '|REBASE-m'
}
$b = "$(Get-Content $gitDir/rebase-merge/head-name)"
$step = "$(Get-Content $gitDir/rebase-merge/msgnum)"
$total = "$(Get-Content $gitDir/rebase-merge/end)"
}
else {
if (Test-Path $gitDir/rebase-apply) {
dbg 'Found rebase-apply' $sw
$step = "$(Get-Content $gitDir/rebase-apply/next)"
$total = "$(Get-Content $gitDir/rebase-apply/last)"
if (Test-Path $gitDir/rebase-apply/rebasing) {
dbg 'Found rebase-apply/rebasing' $sw
$r = '|REBASE'
}
elseif (Test-Path $gitDir/rebase-apply/applying) {
dbg 'Found rebase-apply/applying' $sw
$r = '|AM'
}
else {
$r = '|AM/REBASE'
}
}
elseif (Test-Path $gitDir/MERGE_HEAD) {
dbg 'Found MERGE_HEAD' $sw
$r = '|MERGING'
}
elseif (Test-Path $gitDir/CHERRY_PICK_HEAD) {
dbg 'Found CHERRY_PICK_HEAD' $sw
$r = '|CHERRY-PICKING'
}
elseif (Test-Path $gitDir/REVERT_HEAD) {
dbg 'Found REVERT_HEAD' $sw
$r = '|REVERTING'
}
elseif (Test-Path $gitDir/BISECT_LOG) {
dbg 'Found BISECT_LOG' $sw
$r = '|BISECTING'
}
if ($step -and $total) {
$r += " $step/$total"
}
$b = Invoke-NullCoalescing `
$b `
$branch `
{ dbg 'Trying symbolic-ref' $sw; git --no-optional-locks symbolic-ref HEAD -q 2>$null } `
{ '({0})' -f (Invoke-NullCoalescing `
{
dbg 'Trying describe' $sw
switch ($Global:GitPromptSettings.DescribeStyle) {
'contains' { git --no-optional-locks describe --contains HEAD 2>$null }
'branch' { git --no-optional-locks describe --contains --all HEAD 2>$null }
'describe' { git --no-optional-locks describe HEAD 2>$null }
default { git --no-optional-locks tag --points-at HEAD 2>$null }
}
} `
{
dbg 'Falling back on parsing HEAD' $sw
$ref = $null
if (Test-Path $gitDir/HEAD) {
dbg 'Reading from .git/HEAD' $sw
$ref = Get-Content $gitDir/HEAD 2>$null
}
else {
dbg 'Trying rev-parse' $sw
$ref = git --no-optional-locks rev-parse HEAD 2>$null
}
if ($ref -match 'ref: (?<ref>.+)') {
return $Matches['ref']
}
elseif ($ref -and $ref.Length -ge 7) {
return $ref.Substring(0, 7) + '...'
}
else {
return 'unknown'
}
}
) }
}
if ($isDotGitOrBare -or !$b) {
dbg 'Inside git directory?' $sw
$revParseOut = git --no-optional-locks rev-parse --is-inside-git-dir 2>$null
if ('true' -eq $revParseOut) {
dbg 'Inside git directory' $sw
$revParseOut = git --no-optional-locks rev-parse --is-bare-repository 2>$null
if ('true' -eq $revParseOut) {
$c = 'BARE:'
}
else {
$b = 'GIT_DIR!'
}
}
}
"$c$($b -replace 'refs/heads/','')$r"
}
}
function GetUniquePaths($pathCollections) {
$hash = New-Object System.Collections.Specialized.OrderedDictionary
foreach ($pathCollection in $pathCollections) {
foreach ($path in $pathCollection) {
$hash[$path] = 1
}
}
$hash.Keys
}
$castStringSeq = [Linq.Enumerable].GetMethod("Cast").MakeGenericMethod([string])
<#
.SYNOPSIS
Gets a Git status object that is used by `Write-GitStatus`.
.DESCRIPTION
The `Get-GitStatus` cmdlet gets the status of the current Git repo.
The status object returned by this cmdlet provides the information
displayed in the various sections of the posh-git prompt. The following
properties in $GitPromptSettings control what information is returned in
the status object:
EnableFileStatus = $true # Or $false if Git not installed
EnableFileStatusFromCache = <unset> # Or $true if GitStatusCachePoshClient installed
EnablePromptStatus = $true
EnableStashStatus = $false
UntrackedFilesMode = Default # Other enum values: No, Normal, All
The `Force` parameter can be used to override the EnableFileStatus and
EnablePromptStatus properties to ensure that both file and prompt status
information is returned in the status object.
.EXAMPLE
PS C:\> $s = Get-GitStatus; Write-GitStatus $s
Gets a Git status object. Then passes the object to Write-GitStatus which
writes out a posh-git prompt (or returns a string in ANSI mode) with the
information contained in the status object.
.EXAMPLE
PS C:\> $s = Get-GitStatus -Force
Gets a Git status object that always returns all status information even
if $GitPromptSettings has disabled `EnableFileStatus` and/or
`EnablePromptStatus`.
.INPUTS
None
.OUTPUTS
System.Management.Automation.PSObject
.LINK
Write-GitStatus
#>
function Get-GitStatus {
param(
# The path of a directory within a Git repository that you want to get
# the Git status.
[Parameter(Position = 0)]
$GitDir = (Get-GitDirectory),
# If specified, overrides $GitPromptSettings.EnableFileStatus and
# $GitPromptSettings.EnablePromptStatus when they are set to $false.
[Parameter()]
[switch]
$Force
)
$settings = if ($global:GitPromptSettings) { $global:GitPromptSettings } else { [PoshGitPromptSettings]::new() }
$promptStatusEnabled = $Force -or $settings.EnablePromptStatus
if ($promptStatusEnabled -and $GitDir) {
if ($settings.Debug) {
$sw = [Diagnostics.Stopwatch]::StartNew(); Write-Host ''
}
else {
$sw = $null
}
$branch = $null
$aheadBy = 0
$behindBy = 0
$gone = $false
$upstream = $null
$indexAdded = New-Object System.Collections.Generic.List[string]
$indexModified = New-Object System.Collections.Generic.List[string]
$indexDeleted = New-Object System.Collections.Generic.List[string]
$indexUnmerged = New-Object System.Collections.Generic.List[string]
$filesAdded = New-Object System.Collections.Generic.List[string]
$filesModified = New-Object System.Collections.Generic.List[string]
$filesDeleted = New-Object System.Collections.Generic.List[string]
$filesUnmerged = New-Object System.Collections.Generic.List[string]
$stashCount = 0
$fileStatusEnabled = $Force -or $settings.EnableFileStatus
# Optimization: short-circuit to avoid InDotGitOrBareRepoDir and InDisabledRepository if !$fileStatusEnabled
if ($fileStatusEnabled -and !$($isDotGitOrBare = InDotGitOrBareRepoDir $GitDir) -and !$(InDisabledRepository)) {
if ($null -eq $settings.EnableFileStatusFromCache) {
$settings.EnableFileStatusFromCache = $null -ne (Get-Module GitStatusCachePoshClient)
}
if ($settings.EnableFileStatusFromCache) {
dbg 'Getting status from cache' $sw
$cacheResponse = Get-GitStatusFromCache
if ($cacheResponse.Error) {
# git-status-cache failed; set $global:GitStatusCacheLoggingEnabled = $true, call Restart-GitStatusCache,
# and check %temp%\GitStatusCache_[timestamp].log for details.
dbg "Cache returned an error: $($cacheResponse.Error)" $sw
$branch = "CACHE ERROR"
$behindBy = 1
}
else {
dbg 'Parsing status' $sw
$indexAdded.AddRange($castStringSeq.Invoke($null, (, @($cacheResponse.IndexAdded))))
$indexModified.AddRange($castStringSeq.Invoke($null, (, @($cacheResponse.IndexModified))))
foreach ($indexRenamed in $cacheResponse.IndexRenamed) {
$indexModified.Add($indexRenamed.Old)
}
$indexDeleted.AddRange($castStringSeq.Invoke($null, (, @($cacheResponse.IndexDeleted))))
$indexUnmerged.AddRange($castStringSeq.Invoke($null, (, @($cacheResponse.Conflicted))))
$filesAdded.AddRange($castStringSeq.Invoke($null, (, @($cacheResponse.WorkingAdded))))
$filesModified.AddRange($castStringSeq.Invoke($null, (, @($cacheResponse.WorkingModified))))
foreach ($workingRenamed in $cacheResponse.WorkingRenamed) {
$filesModified.Add($workingRenamed.Old)
}
$filesDeleted.AddRange($castStringSeq.Invoke($null, (, @($cacheResponse.WorkingDeleted))))
$filesUnmerged.AddRange($castStringSeq.Invoke($null, (, @($cacheResponse.Conflicted))))
$branch = $cacheResponse.Branch
$upstream = $cacheResponse.Upstream
$gone = $cacheResponse.UpstreamGone
$aheadBy = $cacheResponse.AheadBy
$behindBy = $cacheResponse.BehindBy
if ($settings.EnableStashStatus -and $cacheResponse.Stashes) {
$stashCount = $cacheResponse.Stashes.Length
}
if ($cacheResponse.State) {
$branch += "|" + $cacheResponse.State
}
}
}
else {
dbg 'Getting status' $sw
switch ($settings.UntrackedFilesMode) {
"No" { $untrackedFilesOption = "-uno" }
"All" { $untrackedFilesOption = "-uall" }
default { $untrackedFilesOption = "-unormal" }
}
$status = Invoke-Utf8ConsoleCommand { git --no-optional-locks '-c' core.quotepath=false '-c' color.status=false status $untrackedFilesOption --short --branch 2>$null }
if ($settings.EnableStashStatus) {
dbg 'Getting stash count' $sw
$stashCount = $null | git --no-optional-locks stash list 2>$null | measure-object | Select-Object -expand Count
}
dbg 'Parsing status' $sw
switch -regex ($status) {
'^(?<index>[^#])(?<working>.) (?<path1>.*?)(?: -> (?<path2>.*))?$' {
if ($sw) { dbg "Status: $_" $sw }
$path1 = $matches['path1']
# Even with core.quotePath=false, paths with spaces are wrapped in ""
# https://github.com/git/git/commit/dbfdc625a5aad10c47e3ffa446d0b92e341a7b44
# https://github.com/git/git/commit/f3fc4a1b8680c114defd98ce6f2429f8946a5dc1
if ($path1 -like '"*"') {
$path1 = $path1.Substring(1, $path1.Length - 2)
}
switch ($matches['index']) {
'A' { $null = $indexAdded.Add($path1); break }
'M' { $null = $indexModified.Add($path1); break }
'R' { $null = $indexModified.Add($path1); break }
'C' { $null = $indexModified.Add($path1); break }
'D' { $null = $indexDeleted.Add($path1); break }
'U' { $null = $indexUnmerged.Add($path1); break }
}
switch ($matches['working']) {
'?' { $null = $filesAdded.Add($path1); break }
'A' { $null = $filesAdded.Add($path1); break }
'M' { $null = $filesModified.Add($path1); break }
'D' { $null = $filesDeleted.Add($path1); break }
'U' { $null = $filesUnmerged.Add($path1); break }
}
continue
}
'^## (?<branch>\S+?)(?:\.\.\.(?<upstream>\S+))?(?: \[(?:ahead (?<ahead>\d+))?(?:, )?(?:behind (?<behind>\d+))?(?<gone>gone)?\])?$' {
if ($sw) { dbg "Status: $_" $sw }
$branch = $matches['branch']
$upstream = $matches['upstream']
$aheadBy = [int]$matches['ahead']
$behindBy = [int]$matches['behind']
$gone = [string]$matches['gone'] -eq 'gone'
continue
}
'^## Initial commit on (?<branch>\S+)$' {
if ($sw) { dbg "Status: $_" $sw }
$branch = $matches['branch']
continue
}
default { if ($sw) { dbg "Status: $_" $sw } }
}
}
}
$branch = Get-GitBranch -Branch $branch -GitDir $GitDir -IsDotGitOrBare:$isDotGitOrBare -sw $sw
dbg 'Building status object' $sw
# This collection is used twice, so create the array just once
$filesAdded = $filesAdded.ToArray()
$indexPaths = @(GetUniquePaths $indexAdded, $indexModified, $indexDeleted, $indexUnmerged)
$workingPaths = @(GetUniquePaths $filesAdded, $filesModified, $filesDeleted, $filesUnmerged)
$index = (, $indexPaths) |
Add-Member -Force -PassThru NoteProperty Added $indexAdded.ToArray() |
Add-Member -Force -PassThru NoteProperty Modified $indexModified.ToArray() |
Add-Member -Force -PassThru NoteProperty Deleted $indexDeleted.ToArray() |
Add-Member -Force -PassThru NoteProperty Unmerged $indexUnmerged.ToArray()
$working = (, $workingPaths) |
Add-Member -Force -PassThru NoteProperty Added $filesAdded |
Add-Member -Force -PassThru NoteProperty Modified $filesModified.ToArray() |
Add-Member -Force -PassThru NoteProperty Deleted $filesDeleted.ToArray() |
Add-Member -Force -PassThru NoteProperty Unmerged $filesUnmerged.ToArray()
$result = New-Object PSObject -Property @{
GitDir = $GitDir
RepoName = Split-Path (Split-Path $GitDir -Parent) -Leaf
Branch = $branch
AheadBy = $aheadBy
BehindBy = $behindBy
UpstreamGone = $gone
Upstream = $upstream
HasIndex = [bool]$index
Index = $index
HasWorking = [bool]$working
Working = $working
HasUntracked = [bool]$filesAdded
StashCount = $stashCount
}
dbg 'Finished' $sw
if ($sw) { $sw.Stop() }
return $result
}
}
function InDisabledRepository {
$currentLocation = Get-Location
foreach ($repo in $Global:GitPromptSettings.RepositoriesInWhichToDisableFileStatus) {
if ($currentLocation -like "$repo*") {
return $true
}
}
return $false
}
function InDotGitOrBareRepoDir([string][ValidateNotNullOrEmpty()]$GitDir) {
# A UNC path has no drive so it's better to use the ProviderPath e.g. "\\server\share".
# However for any path with a drive defined, it's better to use the Path property.
# In this case, ProviderPath is "\LocalMachine\My"" whereas Path is "Cert:\LocalMachine\My".
# The latter is more desirable.
$pathInfo = Microsoft.PowerShell.Management\Get-Location
$currentPath = if ($pathInfo.Drive) { $pathInfo.Path } else { $pathInfo.ProviderPath }
$separator = [System.IO.Path]::DirectorySeparatorChar
$res = "$currentPath$separator".StartsWith("$GitDir$separator", (Get-PathStringComparison))
$res
}
function Get-AliasPattern($cmd) {
$aliases = @($cmd) + @(Get-Alias | Where-Object { $_.Definition -match "^$cmd(\.exe)?$" } | Foreach-Object Name)
"($($aliases -join '|'))"
}
<#
.SYNOPSIS
Deletes the specified Git branches.
.DESCRIPTION
Deletes the specified Git branches that have been merged into the commit specified by the Commit parameter (HEAD by default). You must either specify a branch name via the Name parameter, which accepts wildard characters, or via the Pattern parameter, which accepts a regular expression.
The following branches are always excluded from deletion:
* The current branch
* develop
* master
The default set of excluded branches can be overridden with the ExcludePattern parameter.
Consider always running this command FIRST with the WhatIf parameter. This will show you which branches will be deleted. This gives you a chance to adjust your branch name wildcard pattern or regular expression if you are using the Pattern parameter.
IMPORTANT: Be careful using this command. Even though by default this command deletes only merged branches, most, if not all, of your historical branches have been merged. But that doesn't mean you want to delete them. That is why this command excludes `develop` and `master` by default. But you may use different names e.g. `development` or have other historical branches you don't want to delete. In these cases, you can either:
* Specify a narrower branch name wildcard such as "user/$env:USERNAME/*".
* Specify an updated ExcludeParameter e.g. '(^\*)|(^. (develop|master|v\d+)$)' which adds any branch matching the pattern 'v\d+' to the exclusion list.
If necessary, you can delete the specified branches REGARDLESS of their merge status by using the IncludeUnmerged parameter. BE VERY CAREFUL using the IncludeUnmerged parameter together with the Force parameter, since you will not be given the opportunity to confirm each branch deletion.
The following Git commands are executed by this command:
git branch --merged $Commit |
Where-Object { $_ -notmatch $ExcludePattern } |
Where-Object { $_.Trim() -like $Name } |
Foreach-Object { git branch --delete $_.Trim() }
If the IncludeUnmerged parameter is specified, execution changes to:
git branch |
Where-Object { $_ -notmatch $ExcludePattern } |
Where-Object { $_.Trim() -like $Name } |
Foreach-Object { git branch --delete $_.Trim() }
If the DeleteForce parameter is specified, the Foreach-Object changes to:
Foreach-Object { git branch --delete --force $_.Trim() }
If the Pattern parameter is used instead of the Name parameter, the second Where-Object changes to:
Where-Object { $_ -match $Pattern }
Recovering Deleted Branches
If you wind up deleting a branch you didn't intend to, you can easily recover it with the info provided by Git during the delete. For instance, let's say you realized you didn't want to delete the branch 'feature/exp1'. In the output of this command, you should see a deletion entry for this branch that looks like:
Deleted branch feature/exp1 (was 08f9000).
To recover this branch, execute the following Git command:
# git branch <branch-name> <sha1>
git branch feature/exp1 08f9000
.EXAMPLE
PS> Remove-GitBranch -Name "user/${env:USERNAME}/*" -WhatIf
Shows the merged branches that would be deleted by the specified branch name without actually deleting. Remove the WhatIf parameter when you are happy with the list of branches that will be deleted.
.EXAMPLE
PS> Remove-GitBranch "feature/*" -Force
Deletes the merged branches that match the specified wildcard. Using the Force parameter skips all confirmation prompts. Name is a positional parameter. The first argument is assumed to be the value of the Name parameter.
.EXAMPLE
PS> Remove-GitBranch "bugfix/*" -Force -DeleteForce
Deletes the merged branches that match the specified wildcard. Using the Force parameter skips all confirmation prompts while the DeleteForce parameter uses the --force option in the underlying Git command.
.EXAMPLE
PS> Remove-GitBranch -Pattern 'user/(dahlbyk|hillr)/.*'
Deletes the merged branches that match the specified regular expression.
.EXAMPLE
PS> Remove-GitBranch -Name * -ExcludePattern '(^\*)|(^. (develop|master|v\d+)$)'
Deletes merged branches except the current branch, develop, master and branches that also match the pattern 'v\d+' e.g. v1, v1.0, v1.x. BE VERY CAREFUL SPECIYING SUCH A BROAD BRANCH NAME WILDCARD!
.EXAMPLE
PS> Remove-GitBranch "feature/*" -IncludeUnmerged -WhatIf
Shows the branches, both merged and unmerged, that match the specified wildcard that would be deleted without actually deleting them. Once you've verified the list of branches looks correct, remove the WhatIf parameter to actually delete the branches.
#>
function Remove-GitBranch {
[CmdletBinding(DefaultParameterSetName = "Wildcard", SupportsShouldProcess, ConfirmImpact = "Medium")]
param(
# Specifies a regular expression pattern for the branches that will be deleted. Certain branches are always excluded from deletion e.g. the current branch as well as the develop and master branches. See the ExcludePattern parameter to modify that pattern.
[Parameter(Position = 0, Mandatory, ParameterSetName = "Wildcard")]
[ValidateNotNullOrEmpty()]
[string]
$Name,
# Specifies a regular expression for the branches that will be deleted. Certain branches are always excluded from deletion e.g. the current branch as well as the develop and master branches. See the ExcludePattern parameter to modify that pattern.
[Parameter(Position = 0, Mandatory, ParameterSetName = "Pattern")]
[ValidateNotNull()]
[string]
$Pattern,
# Specifies a regular expression used to exclude merged branches from being deleted. The default pattern excludes the current branch, develop and master branches.
[Parameter()]
[ValidateNotNull()]
[string]
$ExcludePattern = '(^\*)|(^. (develop|master)$)',
# Branches whose tips are reachable from the specified commit will be deleted. The default commit is HEAD. This parameter is ignored if the IncludeUnmerged parameter is specified.
[Parameter()]
[string]
$Commit = "HEAD",
# Specifies that unmerged branches are also eligible to be deleted.
[Parameter()]
[switch]
$IncludeUnmerged,
# Deletes the specified branches without prompting for confirmation. By default, Remove-GitBranch prompts for confirmation before deleting branches.
[Parameter()]
[switch]
$Force,
# Deletes the specified branches by adding the --force parameter to the git branch --delete command e.g. git branch --delete --force <branch-name>. This is also the equivalent of using the -D parameter on the git branch command.
[Parameter()]
[switch]
$DeleteForce
)
if ($IncludeUnmerged) {
$branches = git branch
}
else {
$branches = git branch --merged $Commit
}
$filteredBranches = $branches | Where-Object { $_ -notmatch $ExcludePattern }
if ($PSCmdlet.ParameterSetName -eq "Wildcard") {
$branchesToDelete = $filteredBranches | Where-Object { $_.Trim() -like $Name }
}
else {
$branchesToDelete = $filteredBranches | Where-Object { $_ -match $Pattern }
}
$action = if ($DeleteForce) { "delete with force" } else { "delete" }
$yesToAll = $noToAll = $false
foreach ($branch in $branchesToDelete) {
$targetBranch = $branch.Trim()
if ($PSCmdlet.ShouldProcess($targetBranch, $action)) {
if ($Force -or $yesToAll -or
$PSCmdlet.ShouldContinue(
"Are you REALLY sure you want to $action `"$targetBranch`"?",
"Confirm branch deletion", [ref]$yesToAll, [ref]$noToAll)) {
if ($noToAll) { return }
if ($DeleteForce) {
Invoke-Utf8ConsoleCommand { git branch --delete --force $targetBranch }
}
else {
Invoke-Utf8ConsoleCommand { git branch --delete $targetBranch }
}
}
}
}
}
function Update-AllBranches($Upstream = 'master', [switch]$Quiet) {
$head = git rev-parse --abbrev-ref HEAD
git checkout -q $Upstream
$branches = Invoke-Utf8ConsoleCommand { (git branch --no-color --no-merged) } | Where-Object { $_ -notmatch '^\* ' }
foreach ($line in $branches) {
$branch = $line.SubString(2)
if (!$Quiet) { Write-Host "Rebasing $branch onto $Upstream..." }
git rebase -q $Upstream $branch > $null 2> $null
if ($LASTEXITCODE) {
git rebase --abort
Write-Warning "Rebase failed for $branch"
}
}
git checkout -q $head
}
================================================
FILE: src/PoshGitTypes.ps1
================================================
enum BranchBehindAndAheadDisplayOptions { Full; Compact; Minimal }
enum UntrackedFilesMode { Default; No; Normal; All }
class PoshGitCellColor {
[psobject]$BackgroundColor
[psobject]$ForegroundColor
PoshGitCellColor() {
$this.ForegroundColor = $null
$this.BackgroundColor = $null
}
PoshGitCellColor([psobject]$ForegroundColor) {
$this.ForegroundColor = $ForegroundColor
$this.BackgroundColor = $null
}
PoshGitCellColor([psobject]$ForegroundColor, [psobject]$BackgroundColor) {
$this.ForegroundColor = $ForegroundColor
$this.BackgroundColor = $BackgroundColor
}
hidden [string] ToString($color) {
$ansiTerm = "$([char]27)[0m"
$colorSwatch = " "
$str = ""
if (!$color) {
$str = "<default>"
}
elseif (Test-VirtualTerminalSequece $color -Force) {
if ($global:GitPromptSettings.AnsiConsole) {
# Use '#' for FG color swatch since we are just applying the VT seqs as-is and
# a " " swatch char won't show anything for a FG color.
if ($color -eq $this.ForegroundColor) {
$colorSwatch = "#"
}
$str = "${color}$colorSwatch${ansiTerm} "
}
$str = "`"$(EscapeAnsiString $color)`""
}
else {
if ($global:GitPromptSettings.AnsiConsole) {
$bg = Get-BackgroundVirtualTerminalSequence $color
$str = "${bg}${colorSwatch}${ansiTerm} "
}
if ($color -is [int]) {
$str += "0x{0:X6}" -f $color
}
else {
$str += $color.ToString()
}
}
return $str
}
[string] ToEscapedString() {
if (!$global:GitPromptSettings.AnsiConsole) {
return ""
}
$str = ""
if ($this.ForegroundColor) {
if (Test-VirtualTerminalSequece $this.ForegroundColor) {
$str += EscapeAnsiString $this.ForegroundColor
}
else {
$seq = Get-ForegroundVirtualTerminalSequence $this.ForegroundColor
$str += EscapeAnsiString $seq
}
}
if ($this.BackgroundColor) {
if (Test-VirtualTerminalSequece $this.BackgroundColor) {
$str += EscapeAnsiString $this.BackgroundColor
}
else {
$seq = Get-BackgroundVirtualTerminalSequence $this.BackgroundColor
$str += EscapeAnsiString $seq
}
}
return $str
}
[string] ToString() {
$str = "ForegroundColor: "
$str += $this.ToString($this.ForegroundColor) + ", "
$str += "BackgroundColor: "
$str += $this.ToString($this.BackgroundColor)
return $str
}
}
class PoshGitTextSpan {
[string]$Text
[psobject]$BackgroundColor
[psobject]$ForegroundColor
PoshGitTextSpan() {
$this.Text = ""
$this.ForegroundColor = $null
$this.BackgroundColor = $null
}
PoshGitTextSpan([string]$Text) {
$this.Text = $Text
$this.ForegroundColor = $null
$this.BackgroundColor = $null
}
PoshGitTextSpan([string]$Text, [psobject]$ForegroundColor) {
$this.Text = $Text
$this.ForegroundColor = $ForegroundColor
$this.BackgroundColor = $null
}
PoshGitTextSpan([string]$Text, [psobject]$ForegroundColor, [psobject]$BackgroundColor) {
$this.Text = $Text
$this.ForegroundColor = $ForegroundColor
$this.BackgroundColor = $BackgroundColor
}
PoshGitTextSpan([PoshGitTextSpan]$PoshGitTextSpan) {
$this.Text = $PoshGitTextSpan.Text
$this.ForegroundColor = $PoshGitTextSpan.ForegroundColor
$this.BackgroundColor = $PoshGitTextSpan.BackgroundColor
}
PoshGitTextSpan([PoshGitCellColor]$PoshGitCellColor) {
$this.Text = ''
$this.ForegroundColor = $PoshGitCellColor.ForegroundColor
$this.BackgroundColor = $PoshGitCellColor.BackgroundColor
}
[PoshGitTextSpan] Expand() {
if (!$this.Text) {
return $this
}
$execContext = Get-Variable ExecutionContext -ValueOnly
$expandedText = $execContext.SessionState.InvokeCommand.ExpandString($this.Text)
$newTextSpan = [PoshGitTextSpan]::new($expandedText, $this.ForegroundColor, $this.BackgroundColor)
return $newTextSpan
}
# This method is used by Write-Prompt to render an instance of a PoshGitTextSpan when
# $GitPromptSettings.AnsiConsole is $
gitextract_xoqawrl5/
├── .editorconfig
├── .git-blame-ignore-revs
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ └── workflows/
│ ├── powershell.yml
│ └── pwsh.yml
├── .gitignore
├── .vscode/
│ ├── extensions.json
│ ├── launch.json
│ ├── settings.json
│ └── tasks.json
├── CHANGELOG.md
├── ISSUE_TEMPLATE.md
├── LICENSE.txt
├── PSScriptAnalyzerSettings.psd1
├── README.md
├── chocolatey/
│ ├── packAndLocalInstall.ps1
│ ├── poshgit.nuspec
│ ├── tests/
│ │ └── InstallChocolatey.Tests.ps1
│ └── tools/
│ ├── chocolateyInstall.ps1
│ └── chocolateyUninstall.ps1
├── install.ps1
├── profile.example.ps1
├── src/
│ ├── AnsiUtils.ps1
│ ├── CheckRequirements.ps1
│ ├── ConsoleMode.ps1
│ ├── GitParamTabExpansion.ps1
│ ├── GitPrompt.ps1
│ ├── GitTabExpansion.ps1
│ ├── GitUtils.ps1
│ ├── PoshGitTypes.ps1
│ ├── TortoiseGit.ps1
│ ├── Utils.ps1
│ ├── WindowTitle.ps1
│ ├── en-US/
│ │ └── about_posh-git.help.txt
│ ├── posh-git.psd1
│ └── posh-git.psm1
└── test/
├── Ansi.Tests.ps1
├── CheckRequirements.Tests.ps1
├── DefaultPrompt.Tests.ps1
├── Get-GitBranch.Tests.ps1
├── Get-GitDirectory.Tests.ps1
├── Get-GitStatus.Tests.ps1
├── GitParamTabExpansion.Tests.ps1
├── GitParamTabExpansionVsts.Tests.ps1
├── GitPrompt.Tests.ps1
├── GitProxyFunctionExpansion.Tests.ps1
├── ModuleManifest.Tests.ps1
├── Shared.ps1
├── TabExpansion.Tests.ps1
├── Utils.Tests.ps1
└── git-help.txt
Condensed preview — 52 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (380K chars).
[
{
"path": ".editorconfig",
"chars": 364,
"preview": "# To use this file you must have EditorConfig installed for your editor.\n# For Visual Studio Code, install the extension"
},
{
"path": ".git-blame-ignore-revs",
"chars": 66,
"preview": "# Normalize line endings\n4256c20d7fa3514651df10f4dbc38bcd8fa012e3\n"
},
{
"path": ".gitattributes",
"chars": 52,
"preview": "# Enable LF normalization for all files\n* text=auto\n"
},
{
"path": ".github/FUNDING.yml",
"chars": 30,
"preview": "github: [dahlbyk, rkeithhill]\n"
},
{
"path": ".github/workflows/powershell.yml",
"chars": 1200,
"preview": "name: Windows PowerShell\n\non:\n push:\n branches: [ main, master ]\n pull_request:\n branches: [ main, master ]\n\ncon"
},
{
"path": ".github/workflows/pwsh.yml",
"chars": 1218,
"preview": "name: PowerShell Core\n\non:\n push:\n branches: [ main, master ]\n pull_request:\n branches: [ main, master ]\n\nconcur"
},
{
"path": ".gitignore",
"chars": 35,
"preview": "VERSION\n*.log\n*.nupkg\nobj\n.history\n"
},
{
"path": ".vscode/extensions.json",
"chars": 264,
"preview": "{\n // See http://go.microsoft.com/fwlink/?LinkId=827846\n // for the documentation about the extensions.json format"
},
{
"path": ".vscode/launch.json",
"chars": 938,
"preview": "{\n \"version\": \"0.2.0\",\n \"configurations\": [\n {\n \"type\": \"PowerShell\",\n \"request\": \"la"
},
{
"path": ".vscode/settings.json",
"chars": 571,
"preview": "{\n \"editor.insertSpaces\": true,\n \"editor.rulers\": [\n 120\n ],\n \"editor.tabSize\": 4,\n \"files.insertF"
},
{
"path": ".vscode/tasks.json",
"chars": 1786,
"preview": "{\n // See https://go.microsoft.com/fwlink/?LinkId=733558\n // for the documentation about the tasks.json format\n "
},
{
"path": "CHANGELOG.md",
"chars": 37327,
"preview": "# posh-git Release History\n\n## 1.1.0 - March 31, 2022\n\n### Added\n\n- `Remove-PoshGitFromProfile`\n ([git-for-windows/buil"
},
{
"path": "ISSUE_TEMPLATE.md",
"chars": 769,
"preview": "<!--\nCheck the FAQ https://github.com/dahlbyk/posh-git/wiki/FAQ to see if your issue is addressed there.\nIf not, PLEASE "
},
{
"path": "LICENSE.txt",
"chars": 1091,
"preview": "Copyright (c) 2010-2018 Keith Dahlby, Keith Hill, and contributors\n\nPermission is hereby granted, free of charge, to any"
},
{
"path": "PSScriptAnalyzerSettings.psd1",
"chars": 1583,
"preview": "@{\n # Use Severity when you want to limit the generated diagnostic records to a\n # subset of: Error, Warning and I"
},
{
"path": "README.md",
"chars": 26496,
"preview": "# posh-git\n\n[![Join the chat at https://gitter.im/dahlbyk/posh-git][gitter-img]][gitter]\n[![PowerShell Gallery][psgaller"
},
{
"path": "chocolatey/packAndLocalInstall.ps1",
"chars": 478,
"preview": "param ($Remote = 'origin', [switch]$Force)\nPush-Location $PSScriptRoot\n\n$nuspec = [xml](Get-Content poshgit.nuspec)\n$ver"
},
{
"path": "chocolatey/poshgit.nuspec",
"chars": 1956,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<package xmlns=\"http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd\">\n <me"
},
{
"path": "chocolatey/tests/InstallChocolatey.Tests.ps1",
"chars": 6716,
"preview": "$packageName = \"poshgit\"\ncpack\n\nfunction Setup-Environment {\n Cleanup\n $env:poshGit = join-path (Resolve-Path .\\T"
},
{
"path": "chocolatey/tools/chocolateyInstall.ps1",
"chars": 1788,
"preview": "try {\n $poshgitPath = join-path (Get-ToolsLocation) 'poshgit'\n\n try {\n if (test-path($poshgitPath)) {\n "
},
{
"path": "chocolatey/tools/chocolateyUninstall.ps1",
"chars": 1328,
"preview": "try {\n $poshgitPath = join-path (Get-ToolsLocation) 'poshgit'\n\n $currentVersionPath = Get-ChildItem \"$poshgitPath"
},
{
"path": "install.ps1",
"chars": 261,
"preview": "param([switch]$WhatIf = $false, [switch]$Force = $false, [switch]$Verbose = $false)\n\n$installDir = Split-Path $MyInvocat"
},
{
"path": "profile.example.ps1",
"chars": 911,
"preview": "# Import the posh-git module, first via installed posh-git module.\n# If the module isn't installed, then attempt to load"
},
{
"path": "src/AnsiUtils.ps1",
"chars": 2730,
"preview": "# Color codes from https://msdn.microsoft.com/en-us/library/windows/desktop/mt638032(v=vs.85).aspx\n$ConsoleColorToAnsi ="
},
{
"path": "src/CheckRequirements.ps1",
"chars": 1276,
"preview": "$global:GitMissing = $false\n$script:GitCygwin = $false\n$script:GitVersion = $requiredVersion = [System.Version]'2.15'\n\ni"
},
{
"path": "src/ConsoleMode.ps1",
"chars": 3527,
"preview": "# Hack! https://gist.github.com/lzybkr/f2059cb2ee8d0c13c65ab933b75e998c\n\n# Always skip setting the console mode on non-W"
},
{
"path": "src/GitParamTabExpansion.ps1",
"chars": 12526,
"preview": "# Variable is used in GitTabExpansion.ps1\n$shortGitParams = @{\n add = 'n v f i p e u A N'\n bisect = ''\n blame ="
},
{
"path": "src/GitPrompt.ps1",
"chars": 31979,
"preview": "# Inspired by Mark Embling\n# http://www.markembling.info/view/my-ideal-powershell-prompt-with-git-integration\n\n$global:"
},
{
"path": "src/GitTabExpansion.ps1",
"chars": 23459,
"preview": "# Initial implementation by Jeremy Skinner\n# http://www.jeremyskinner.co.uk/2010/03/07/using-git-with-windows-powershell"
},
{
"path": "src/GitUtils.ps1",
"chars": 28609,
"preview": "# Inspired by Mark Embling\n# http://www.markembling.info/view/my-ideal-powershell-prompt-with-git-integration\n\n<#\n.SYNOP"
},
{
"path": "src/PoshGitTypes.ps1",
"chars": 11593,
"preview": "enum BranchBehindAndAheadDisplayOptions { Full; Compact; Minimal }\nenum UntrackedFilesMode { Default; No; Normal; All }\n"
},
{
"path": "src/TortoiseGit.ps1",
"chars": 2596,
"preview": "# TortoiseGit\n\nfunction private:Get-TortoiseGitPath {\n if ((Test-Path \"C:\\Program Files\\TortoiseGit\\bin\\TortoiseGitPr"
},
{
"path": "src/Utils.ps1",
"chars": 18388,
"preview": "# Need this variable as long as we support PS v2\n$ModuleBasePath = Split-Path $MyInvocation.MyCommand.Path -Parent\n\n# St"
},
{
"path": "src/WindowTitle.ps1",
"chars": 2850,
"preview": "$HostSupportsSettingWindowTitle = $null\n$OriginalWindowTitle = $null\n\nfunction Test-WindowTitleIsWriteable {\n if ($nu"
},
{
"path": "src/en-US/about_posh-git.help.txt",
"chars": 9073,
"preview": "TOPIC\n posh-git\n\nSHORT DESCRIPTION\n posh-git integrates Git and PowerShell providing tab completion of Git\n co"
},
{
"path": "src/posh-git.psd1",
"chars": 2543,
"preview": "@{\n\n# Script module or binary module file associated with this manifest.\nRootModule = 'posh-git.psm1'\n\n# Version number "
},
{
"path": "src/posh-git.psm1",
"chars": 7325,
"preview": "param([bool]$ForcePoshGitPrompt, [bool]$UseLegacyTabExpansion, [bool]$EnableProxyFunctionExpansion)\n\nif (Test-Path Env:\\"
},
{
"path": "test/Ansi.Tests.ps1",
"chars": 783,
"preview": "BeforeAll {\n . $PSScriptRoot\\Shared.ps1\n}\n\nDescribe 'ANSI Tests' {\n Context 'Returns correct ANSI sequence for spe"
},
{
"path": "test/CheckRequirements.Tests.ps1",
"chars": 1441,
"preview": "# Not using BeforeAll because discovery doesn't like InModuleScope without posh-git loaded\n. $PSScriptRoot\\Shared.ps1\n\nD"
},
{
"path": "test/DefaultPrompt.Tests.ps1",
"chars": 24129,
"preview": "BeforeAll {\n . $PSScriptRoot\\Shared.ps1\n\n [System.Diagnostics.CodeAnalysis.SuppressMessage('PSUseDeclaredVarsMoreT"
},
{
"path": "test/Get-GitBranch.Tests.ps1",
"chars": 943,
"preview": "BeforeAll {\n . $PSScriptRoot\\Shared.ps1\n}\n\nDescribe 'Get-GitBranch Tests' {\n Context 'Get-GitBranch GIT_DIR Tests'"
},
{
"path": "test/Get-GitDirectory.Tests.ps1",
"chars": 4547,
"preview": "BeforeAll {\n . $PSScriptRoot\\Shared.ps1\n}\n\nDescribe 'Get-GitDiretory Tests' {\n Context \"Test normal repository\" {\n"
},
{
"path": "test/Get-GitStatus.Tests.ps1",
"chars": 22668,
"preview": "# For info on Pester mocking see - http://www.powershellmagazine.com/2014/09/30/pester-mock-and-testdrive/\nBeforeAll {\n "
},
{
"path": "test/GitParamTabExpansion.Tests.ps1",
"chars": 8523,
"preview": "BeforeAll {\n . $PSScriptRoot\\Shared.ps1\n}\n\nDescribe 'ParamsTabExpansion Tests' {\n Context 'Push Parameters TabExpa"
},
{
"path": "test/GitParamTabExpansionVsts.Tests.ps1",
"chars": 2558,
"preview": "BeforeAll {\n . $PSScriptRoot\\Shared.ps1\n}\n\nDescribe 'ParamsTabExpansion VSTS Tests' {\n Context 'Push Parameters Ta"
},
{
"path": "test/GitPrompt.Tests.ps1",
"chars": 1848,
"preview": "BeforeAll {\n . $PSScriptRoot\\Shared.ps1\n}\n\nDescribe 'Write-VcsStatus Tests' {\n BeforeAll {\n Mock -ModuleNam"
},
{
"path": "test/GitProxyFunctionExpansion.Tests.ps1",
"chars": 17252,
"preview": "BeforeAll {\n . $PSScriptRoot\\Shared.ps1\n}\n\nDescribe 'Proxy Function Expansion Tests' {\n Context 'Proxy Function Na"
},
{
"path": "test/ModuleManifest.Tests.ps1",
"chars": 240,
"preview": "BeforeAll {\n . $PSScriptRoot\\Shared.ps1\n}\n\nDescribe 'Module Manifest Tests' {\n It 'Passes Test-ModuleManifest' {\n "
},
{
"path": "test/Shared.ps1",
"chars": 5432,
"preview": "# Define these variables since they are not defined in WinPS 5.x\nif ($PSVersionTable.PSVersion.Major -lt 6) {\n [Syste"
},
{
"path": "test/TabExpansion.Tests.ps1",
"chars": 16483,
"preview": "BeforeAll {\n . $PSScriptRoot\\Shared.ps1\n}\n\nDescribe 'TabExpansion function test' -Skip:($PSVersionTable.PSVersion.Maj"
},
{
"path": "test/Utils.Tests.ps1",
"chars": 11024,
"preview": "BeforeAll {\n . $PSScriptRoot\\Shared.ps1\n . $modulePath\\Utils.ps1\n}\n\nDescribe 'Utils Function Tests' {\n Context "
},
{
"path": "test/git-help.txt",
"chars": 2037,
"preview": "usage: git [--version] [--help] [-C <path>] [-c name=value]\n [--exec-path[=<path>]] [--html-path] [--man-path]"
}
]
About this extraction
This page contains the full source code of the dahlbyk/posh-git GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 52 files (357.0 KB), approximately 96.0k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.