diff --git a/.gitattributes b/.gitattributes
index a4cc200a0..1a336bfbd 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,3 +1,2 @@
-# Disable LF normalization for all files
-* -text
-*.yml text=auto
+# Enable LF normalization for all files
+* text=auto
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 04e7501a6..d73c93a67 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,4 +1,4 @@
-{
- "editor.rulers": [ 120 ],
- "powershell.scriptAnalysis.settingsPath": "PSScriptAnalyzerSettings.psd1"
-}
+{
+ "editor.rulers": [ 120 ],
+ "powershell.scriptAnalysis.settingsPath": "PSScriptAnalyzerSettings.psd1"
+}
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index 95d2b15d3..3b6cb45b4 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -1,66 +1,66 @@
-// Available variables which can be used inside of strings.
-// ${workspaceRoot}: the root folder of the team
-// ${file}: the current opened file
-// ${relativeFile}: the current opened file relative to workspaceRoot
-// ${fileBasename}: the current opened file's basename
-// ${fileDirname}: the current opened file's dirname
-// ${fileExtname}: the current opened file's extension
-// ${cwd}: the current working directory of the spawned process
-{
- // See https://go.microsoft.com/fwlink/?LinkId=733558
- // for the documentation about the tasks.json format
- "version": "0.1.0",
-
- // Start PowerShell
- "windows": {
- "command": "${env.windir}\\sysnative\\windowspowershell\\v1.0\\PowerShell.exe"
- },
- "linux": {
- "command": "/usr/bin/powershell"
- },
- "osx": {
- "command": "/usr/local/bin/powershell"
- },
-
- // The command is a shell script
- "isShellCommand": true,
-
- // Show the output window always
- "showOutput": "always",
-
- "args": [
- "-NoProfile", "-ExecutionPolicy", "Bypass"
- ],
-
- // Associate with test task runner
- "tasks": [
- {
- "taskName": "Test",
- "suppressTaskName": true,
- "isTestCommand": true,
- "showOutput": "always",
- "args": [
- "Write-Host 'Invoking Pester'; Invoke-Pester test -PesterOption @{IncludeVSCodeMarker=$true};",
- "Invoke-Command { Write-Host 'Completed Test task in task runner.' }"
- ],
- "problemMatcher": [
- {
- "owner": "powershell",
- "fileLocation": ["absolute"],
- "severity": "error",
- "pattern": [
- {
- "regexp": "^\\s*(\\[-\\]\\s*.*?)(\\d+)ms\\s*$",
- "message": 1
- },
- {
- "regexp": "^\\s+at\\s+[^,]+,\\s*(.*?):\\s+line\\s+(\\d+)$",
- "file": 1,
- "line": 2
- }
- ]
- }
- ]
- }
- ]
-}
+// Available variables which can be used inside of strings.
+// ${workspaceRoot}: the root folder of the team
+// ${file}: the current opened file
+// ${relativeFile}: the current opened file relative to workspaceRoot
+// ${fileBasename}: the current opened file's basename
+// ${fileDirname}: the current opened file's dirname
+// ${fileExtname}: the current opened file's extension
+// ${cwd}: the current working directory of the spawned process
+{
+ // See https://go.microsoft.com/fwlink/?LinkId=733558
+ // for the documentation about the tasks.json format
+ "version": "0.1.0",
+
+ // Start PowerShell
+ "windows": {
+ "command": "${env.windir}\\sysnative\\windowspowershell\\v1.0\\PowerShell.exe"
+ },
+ "linux": {
+ "command": "/usr/bin/powershell"
+ },
+ "osx": {
+ "command": "/usr/local/bin/powershell"
+ },
+
+ // The command is a shell script
+ "isShellCommand": true,
+
+ // Show the output window always
+ "showOutput": "always",
+
+ "args": [
+ "-NoProfile", "-ExecutionPolicy", "Bypass"
+ ],
+
+ // Associate with test task runner
+ "tasks": [
+ {
+ "taskName": "Test",
+ "suppressTaskName": true,
+ "isTestCommand": true,
+ "showOutput": "always",
+ "args": [
+ "Write-Host 'Invoking Pester'; Invoke-Pester test -PesterOption @{IncludeVSCodeMarker=$true};",
+ "Invoke-Command { Write-Host 'Completed Test task in task runner.' }"
+ ],
+ "problemMatcher": [
+ {
+ "owner": "powershell",
+ "fileLocation": ["absolute"],
+ "severity": "error",
+ "pattern": [
+ {
+ "regexp": "^\\s*(\\[-\\]\\s*.*?)(\\d+)ms\\s*$",
+ "message": 1
+ },
+ {
+ "regexp": "^\\s+at\\s+[^,]+,\\s*(.*?):\\s+line\\s+(\\d+)$",
+ "file": 1,
+ "line": 2
+ }
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 27bde6b32..db9347e8e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,25 +1,25 @@
-# posh-git Release History
-
-## 0.7.0 - January 31, 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
-- Fix crash on PowerShell Core due to missing .NET types for WindowsIdentity/Principal
-- Fix syntax error on setenv calls
-- Fix temp path issue with ~ in 8.3 filenames
-- Fix unable to find type [EnvironmentVariableTarget] in PowerShell on .NET Core
-- Fix support for bare repository ([#291](https://github.com/dahlbyk/posh-git/issues/291))
-- Fewer errors generated in global $Error collection
-- Remove error thrown by symbolic-ref and describe
-- 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))
-- Update profile.example.ps1 to remove prompt function and tweak how module is imported
-- Add new commmand Add-PoshGitToProfile
-- Add about_posh-git help topic
-- Add new branch status to indicate upstream is gone ([#326](https://github.com/dahlbyk/posh-git/pull/326))
-- Add ahead/behind count to prompt ([#256](https://github.com/dahlbyk/posh-git/pull/256))
-- Add BranchBehindAndAheadDisplay setting to control count display (Full (default), Compact, Minimal)
-- 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.
+# posh-git Release History
+
+## 0.7.0 - January 31, 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
+- Fix crash on PowerShell Core due to missing .NET types for WindowsIdentity/Principal
+- Fix syntax error on setenv calls
+- Fix temp path issue with ~ in 8.3 filenames
+- Fix unable to find type [EnvironmentVariableTarget] in PowerShell on .NET Core
+- Fix support for bare repository ([#291](https://github.com/dahlbyk/posh-git/issues/291))
+- Fewer errors generated in global $Error collection
+- Remove error thrown by symbolic-ref and describe
+- 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))
+- Update profile.example.ps1 to remove prompt function and tweak how module is imported
+- Add new commmand Add-PoshGitToProfile
+- Add about_posh-git help topic
+- Add new branch status to indicate upstream is gone ([#326](https://github.com/dahlbyk/posh-git/pull/326))
+- Add ahead/behind count to prompt ([#256](https://github.com/dahlbyk/posh-git/pull/256))
+- Add BranchBehindAndAheadDisplay setting to control count display (Full (default), Compact, Minimal)
+- 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.
diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md
index df392197f..ddf617c05 100644
--- a/ISSUE_TEMPLATE.md
+++ b/ISSUE_TEMPLATE.md
@@ -1,23 +1,23 @@
-
-
-### System Details
-
-- posh-git version:
-- PowerShell version:
-- Git version:
-- Operating system name and version:
-
-
-
-### Issue Description
-
-I am experiencing a problem with...
+
+
+### System Details
+
+- posh-git version:
+- PowerShell version:
+- Git version:
+- Operating system name and version:
+
+
+
+### Issue Description
+
+I am experiencing a problem with...
diff --git a/LICENSE.txt b/LICENSE.txt
index d81420990..7b3d7e3f2 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,7 +1,7 @@
-Copyright (c) 2010-2016 Keith Dahlby 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.
+Copyright (c) 2010-2016 Keith Dahlby 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.
diff --git a/PSScriptAnalyzerSettings.psd1 b/PSScriptAnalyzerSettings.psd1
index caa200069..e3f881411 100644
--- a/PSScriptAnalyzerSettings.psd1
+++ b/PSScriptAnalyzerSettings.psd1
@@ -1,32 +1,32 @@
-@{
- # 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')
-
- # 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")}
- }
-}
+@{
+ # 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')
+
+ # 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")}
+ }
+}
diff --git a/README.md b/README.md
index e7aa1ff67..40fdadf38 100644
--- a/README.md
+++ b/README.md
@@ -1,192 +1,192 @@
-# posh-git
-
-[![Build status](https://ci.appveyor.com/api/projects/status/eb8erd5afaa01w80?svg=true)](https://ci.appveyor.com/project/dahlbyk/posh-git)
-[![Join the chat at https://gitter.im/dahlbyk/posh-git](https://badges.gitter.im/dahlbyk/posh-git.svg)](https://gitter.im/dahlbyk/posh-git?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
-
-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 [master ≡ +0 ~1 -0 !]>
-```
-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 tab key.
-That will tab complete to `git checkout` and if you keep pressing tab, 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 ma` tab completes to `git pull origin master`.
-
-## Notes
-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` 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`.
-
-## Installation
-### Prerequisites
-Before installing posh-git make sure the following prerequisites have been met.
-
-1. PowerShell 2.0 or higher. Check your PowerShell version by executing `$PSVersionTable.PSVersion`.
-
-2. 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.exe is in your PATH environment variable.
-
-### Installing posh-git via PowerShellGet
-If you are on PowerShell version 5 or higher, execute the command below to install from the [PowerShell Gallery](https://www.powershellgallery.com/):
-
-```
-PowerShellGet\Install-Module posh-git -Scope CurrentUser
-```
-You may be asked if you trust packages coming from the PowerShell Gallery. Answer yes to allow installation of this module to proceed.
-
-If you are on PowerShell version 3 or 4, you will need to install the [Package Management Preview for PowerShell 3 & 4](https://www.microsoft.com/en-us/download/details.aspx?id=51451) in order to run the command above.
-
-Note: If you get an error message from Install-Module about NuGet being required to interact with NuGet-based repositories, execute the following commands to bootstrap the NuGet provider:
-```
-Install-PackageProvider NuGet -Force
-Import-PackageProvider NuGet -Force
-```
-Then retry the Install-Module command above.
-
-After you have successfully installed the posh-git module from the PowerShell Gallery, you will be able to update to a newer version by executing the command:
-```
-Update-Module posh-git
-```
-
-### Installing posh-git via Chocolatey
-If you have PowerShell version 2 or are having issues using Install-Module with PowerShell version 3 or 4, you can use [Chocolatey](https://chocolatey.org) to install posh-git.
-If you don't have Chocolatey, you can install it from the [Chocolately Install page](https://chocolatey.org/install).
-With Chocolatey installed, execute the following command to install posh-git:
-```
-choco install poshgit
-```
-
-## 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'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:
-```
-Import-Module posh-git
-```
-Save the profile script, then close PowerShell and open a new PowerShell session.
-Type `git fe` and then press tab. If posh-git has been imported, that command should tab complete to `git fetch`.
-
-### Step 3 (optional): Customize Your PowerShell Prompt
-By default, posh-git will update your PowerShell prompt function to display Git status summary information when the current dir is inside a Git repository.
-posh-git will not update your PowerShell prompt function if you have your own, customized prompt function that has been defined before importing posh-git.
-
-The posh-git prompt is a single line prompt that looks like this:
-```
-C:\Users\Keith\GitHub\posh-git [master ≡ +0 ~1 -0 !]>
-```
-You can customize the posh-git prompt or define your own custom prompt function.
-The most common customization for the posh-git provided prompt is to make it span two lines which can be done with the following command:
-```
-$GitPromptSettings.DefaultPromptSuffix = '`n$(''>'' * ($nestedPromptLevel + 1)) '
-```
-This will change the prompt to:
-```
-C:\Users\Keith\GitHub\posh-git [master ≡ +0 ~1 -0 !]
->
-```
-You can also customize the default prompt prefix text e.g.:
-```
-$GitPromptSettings.DefaultPromptPrefix = '[$(hostname)] '
-```
-This will change the prompt to:
-```
-[KEITH1] C:\Users\Keith\GitHub\posh-git [master ≡ +0 ~1 -0 !]>
-```
-And if you would prefer to have any path under your home directory abbreviated with ~, you can change this setting:
-```
-$GitPromptSettings.DefaultPromptAbbreviateHomeDirectory = $true
-```
-This will change the prompt to the one shown below:
-```
-~\GitHub\posh-git [master ≡ +0 ~1 -0 !]>
-```
-
-You can also create your own prompt function to show whatever information you want.
-See the [Customizing Your PowerShell Prompt](https://github.com/dahlbyk/posh-git/wiki/Customizing-Your-PowerShell-Prompt) wiki page for details.
-
-## 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]
-
-* ` [` (`BeforeText`)
-* `{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 remote (tracked origin) branch. Note: This information reflects the state of the remote tracked branch after the last `git fetch/pull` of the remote.
- * ≡ = The local branch in at the same commit level as the remote branch (`BranchIdenticalStatus`)
- * ↑`` = 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`)
- * ↓`` = 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`)
- * ``↕`` = 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; ` | ` (`DelimText`); EFGH represent the working directory
- * `+` = Added files
- * `~` = Modified files
- * `-` = Removed files
- * `!` = Conflicted files
- * As in `git status`, index status is dark green and working directory status is dark red
-*
-* W represents the status of the working folder
- * `!` = There are untracked changes in the working tree (`LocalStagedStatus`)
- * `~` = There are staged changes in the working tree waiting to be committed (`LocalWorkingStatus`)
- * None = There are no uncommitted or unstaged changes to the working tree (`LocalDefault`)
-* `]` (`AfterText`)
-
-The symbols and surrounding text can be customized by the corresponding properties on `$GitPromptSettings`.
-
-For example, a status of `[master ≡ +0 ~2 -1 | +1 ~1 -0]` corresponds to the following `git status`:
-
- # On branch master
- #
- # Changes to be committed:
- # (use "git reset HEAD ..." to unstage)
- #
- # modified: this-changed.txt
- # modified: this-too.txt
- # deleted: gone.ps1
- #
- # Changed but not updated:
- # (use "git add ..." to update what will be committed)
- # (use "git checkout -- ..." to discard changes in working directory)
- #
- # modified: not-staged.ps1
- #
- # Untracked files:
- # (use "git add ..." to include in what will be committed)
- #
- # new.file
-
-## Based on work by:
-
- - Keith Dahlby, http://solutionizing.net/
- - Mark Embling, http://www.markembling.info/
- - Jeremy Skinner, http://www.jeremyskinner.co.uk/
+# posh-git
+
+[![Build status](https://ci.appveyor.com/api/projects/status/eb8erd5afaa01w80?svg=true)](https://ci.appveyor.com/project/dahlbyk/posh-git)
+[![Join the chat at https://gitter.im/dahlbyk/posh-git](https://badges.gitter.im/dahlbyk/posh-git.svg)](https://gitter.im/dahlbyk/posh-git?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
+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 [master ≡ +0 ~1 -0 !]>
+```
+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 tab key.
+That will tab complete to `git checkout` and if you keep pressing tab, 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 ma` tab completes to `git pull origin master`.
+
+## Notes
+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` 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`.
+
+## Installation
+### Prerequisites
+Before installing posh-git make sure the following prerequisites have been met.
+
+1. PowerShell 2.0 or higher. Check your PowerShell version by executing `$PSVersionTable.PSVersion`.
+
+2. 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.exe is in your PATH environment variable.
+
+### Installing posh-git via PowerShellGet
+If you are on PowerShell version 5 or higher, execute the command below to install from the [PowerShell Gallery](https://www.powershellgallery.com/):
+
+```
+PowerShellGet\Install-Module posh-git -Scope CurrentUser
+```
+You may be asked if you trust packages coming from the PowerShell Gallery. Answer yes to allow installation of this module to proceed.
+
+If you are on PowerShell version 3 or 4, you will need to install the [Package Management Preview for PowerShell 3 & 4](https://www.microsoft.com/en-us/download/details.aspx?id=51451) in order to run the command above.
+
+Note: If you get an error message from Install-Module about NuGet being required to interact with NuGet-based repositories, execute the following commands to bootstrap the NuGet provider:
+```
+Install-PackageProvider NuGet -Force
+Import-PackageProvider NuGet -Force
+```
+Then retry the Install-Module command above.
+
+After you have successfully installed the posh-git module from the PowerShell Gallery, you will be able to update to a newer version by executing the command:
+```
+Update-Module posh-git
+```
+
+### Installing posh-git via Chocolatey
+If you have PowerShell version 2 or are having issues using Install-Module with PowerShell version 3 or 4, you can use [Chocolatey](https://chocolatey.org) to install posh-git.
+If you don't have Chocolatey, you can install it from the [Chocolately Install page](https://chocolatey.org/install).
+With Chocolatey installed, execute the following command to install posh-git:
+```
+choco install poshgit
+```
+
+## 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'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:
+```
+Import-Module posh-git
+```
+Save the profile script, then close PowerShell and open a new PowerShell session.
+Type `git fe` and then press tab. If posh-git has been imported, that command should tab complete to `git fetch`.
+
+### Step 3 (optional): Customize Your PowerShell Prompt
+By default, posh-git will update your PowerShell prompt function to display Git status summary information when the current dir is inside a Git repository.
+posh-git will not update your PowerShell prompt function if you have your own, customized prompt function that has been defined before importing posh-git.
+
+The posh-git prompt is a single line prompt that looks like this:
+```
+C:\Users\Keith\GitHub\posh-git [master ≡ +0 ~1 -0 !]>
+```
+You can customize the posh-git prompt or define your own custom prompt function.
+The most common customization for the posh-git provided prompt is to make it span two lines which can be done with the following command:
+```
+$GitPromptSettings.DefaultPromptSuffix = '`n$(''>'' * ($nestedPromptLevel + 1)) '
+```
+This will change the prompt to:
+```
+C:\Users\Keith\GitHub\posh-git [master ≡ +0 ~1 -0 !]
+>
+```
+You can also customize the default prompt prefix text e.g.:
+```
+$GitPromptSettings.DefaultPromptPrefix = '[$(hostname)] '
+```
+This will change the prompt to:
+```
+[KEITH1] C:\Users\Keith\GitHub\posh-git [master ≡ +0 ~1 -0 !]>
+```
+And if you would prefer to have any path under your home directory abbreviated with ~, you can change this setting:
+```
+$GitPromptSettings.DefaultPromptAbbreviateHomeDirectory = $true
+```
+This will change the prompt to the one shown below:
+```
+~\GitHub\posh-git [master ≡ +0 ~1 -0 !]>
+```
+
+You can also create your own prompt function to show whatever information you want.
+See the [Customizing Your PowerShell Prompt](https://github.com/dahlbyk/posh-git/wiki/Customizing-Your-PowerShell-Prompt) wiki page for details.
+
+## 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]
+
+* ` [` (`BeforeText`)
+* `{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 remote (tracked origin) branch. Note: This information reflects the state of the remote tracked branch after the last `git fetch/pull` of the remote.
+ * ≡ = The local branch in at the same commit level as the remote branch (`BranchIdenticalStatus`)
+ * ↑`` = 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`)
+ * ↓`` = 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`)
+ * ``↕`` = 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; ` | ` (`DelimText`); EFGH represent the working directory
+ * `+` = Added files
+ * `~` = Modified files
+ * `-` = Removed files
+ * `!` = Conflicted files
+ * As in `git status`, index status is dark green and working directory status is dark red
+*
+* W represents the status of the working folder
+ * `!` = There are untracked changes in the working tree (`LocalStagedStatus`)
+ * `~` = There are staged changes in the working tree waiting to be committed (`LocalWorkingStatus`)
+ * None = There are no uncommitted or unstaged changes to the working tree (`LocalDefault`)
+* `]` (`AfterText`)
+
+The symbols and surrounding text can be customized by the corresponding properties on `$GitPromptSettings`.
+
+For example, a status of `[master ≡ +0 ~2 -1 | +1 ~1 -0]` corresponds to the following `git status`:
+
+ # On branch master
+ #
+ # Changes to be committed:
+ # (use "git reset HEAD ..." to unstage)
+ #
+ # modified: this-changed.txt
+ # modified: this-too.txt
+ # deleted: gone.ps1
+ #
+ # Changed but not updated:
+ # (use "git add ..." to update what will be committed)
+ # (use "git checkout -- ..." to discard changes in working directory)
+ #
+ # modified: not-staged.ps1
+ #
+ # Untracked files:
+ # (use "git add ..." to include in what will be committed)
+ #
+ # new.file
+
+## Based on work by:
+
+ - Keith Dahlby, http://solutionizing.net/
+ - Mark Embling, http://www.markembling.info/
+ - Jeremy Skinner, http://www.jeremyskinner.co.uk/
diff --git a/chocolatey/tests/InstallChocolatey.Tests.ps1 b/chocolatey/tests/InstallChocolatey.Tests.ps1
index 9c4c8b0aa..fe470feec 100644
--- a/chocolatey/tests/InstallChocolatey.Tests.ps1
+++ b/chocolatey/tests/InstallChocolatey.Tests.ps1
@@ -1,210 +1,210 @@
-$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($env:chocolatey_bin_root -ne $null){$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](Dir "$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](Dir "$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
- Pushd 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
-
- Popd
- $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
- Pushd 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
-
- Popd
- $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
- Pushd 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
- Popd
- $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
- Pushd 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
- Popd
- $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}
- }
- }
-
-}
+$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($env:chocolatey_bin_root -ne $null){$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](Dir "$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](Dir "$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
+ Pushd 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
+
+ Popd
+ $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
+ Pushd 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
+
+ Popd
+ $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
+ Pushd 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
+ Popd
+ $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
+ Pushd 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
+ Popd
+ $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}
+ }
+ }
+
+}
diff --git a/chocolatey/tools/chocolateyInstall.ps1 b/chocolatey/tools/chocolateyInstall.ps1
index 0f6caf308..f51c0f998 100644
--- a/chocolatey/tools/chocolateyInstall.ps1
+++ b/chocolatey/tools/chocolateyInstall.ps1
@@ -1,50 +1,50 @@
-try {
- $binRoot = Get-BinRoot
- $poshgitPath = join-path $binRoot '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'"
- }
- 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
-}
-
+try {
+ $binRoot = Get-BinRoot
+ $poshgitPath = join-path $binRoot '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'"
+ }
+ 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
+}
+
diff --git a/chocolatey/tools/chocolateyUninstall.ps1 b/chocolatey/tools/chocolateyUninstall.ps1
index 311fb9878..30ab3bba4 100644
--- a/chocolatey/tools/chocolateyUninstall.ps1
+++ b/chocolatey/tools/chocolateyUninstall.ps1
@@ -1,44 +1,44 @@
-try {
- $binRoot = Get-BinRoot
- $poshgitPath = join-path $binRoot '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
-}
-
+try {
+ $binRoot = Get-BinRoot
+ $poshgitPath = join-path $binRoot '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
+}
+
diff --git a/install.ps1 b/install.ps1
index bff83440a..c54135317 100644
--- a/install.ps1
+++ b/install.ps1
@@ -1,6 +1,6 @@
-param([switch]$WhatIf = $false, [switch]$Force = $false)
-
-$installDir = Split-Path $MyInvocation.MyCommand.Path -Parent
-
-Import-Module $installDir\src\posh-git.psd1
-Add-PoshGitToProfile -WhatIf:$WhatIf -Force:$Force
+param([switch]$WhatIf = $false, [switch]$Force = $false)
+
+$installDir = Split-Path $MyInvocation.MyCommand.Path -Parent
+
+Import-Module $installDir\src\posh-git.psd1
+Add-PoshGitToProfile -WhatIf:$WhatIf -Force:$Force
diff --git a/profile.example.ps1 b/profile.example.ps1
index 5adcad9ed..fe86c74b8 100644
--- a/profile.example.ps1
+++ b/profile.example.ps1
@@ -1,20 +1,20 @@
-# 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"
-
-Start-SshAgent -Quiet
-
-Write-Warning "posh-git's profile.example.ps1 will be removed in a future version. To avoid a change in behavior, copy its contents into your $PROFILE."
+# 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"
+
+Start-SshAgent -Quiet
+
+Write-Warning "posh-git's profile.example.ps1 will be removed in a future version. To avoid a change in behavior, copy its contents into your $PROFILE."
diff --git a/src/CheckVersion.ps1 b/src/CheckVersion.ps1
index 002f4d08a..99e1506f2 100644
--- a/src/CheckVersion.ps1
+++ b/src/CheckVersion.ps1
@@ -1,18 +1,18 @@
-$Global:GitMissing = $false
-
-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
-}
-
-$requiredVersion = [Version]'1.7.2'
-if ([String](git --version 2> $null) -match '(?\d+(?:\.\d+)+)') {
- $version = [Version]$Matches['ver']
-}
-if ($version -lt $requiredVersion) {
- Write-Warning "posh-git requires Git $requiredVersion or better. You have $version."
- $false
-} else {
- $true
-}
+$Global:GitMissing = $false
+
+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
+}
+
+$requiredVersion = [Version]'1.7.2'
+if ([String](git --version 2> $null) -match '(?\d+(?:\.\d+)+)') {
+ $version = [Version]$Matches['ver']
+}
+if ($version -lt $requiredVersion) {
+ Write-Warning "posh-git requires Git $requiredVersion or better. You have $version."
+ $false
+} else {
+ $true
+}
diff --git a/src/GitParamTabExpansion.ps1 b/src/GitParamTabExpansion.ps1
index 058be9fc1..1b29aa3f7 100644
--- a/src/GitParamTabExpansion.ps1
+++ b/src/GitParamTabExpansion.ps1
@@ -1,167 +1,167 @@
-# Variable is used in GitTabExpansion.ps1
-[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')]
-$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'
- 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'
- tag = 'a s u f d v n l m F'
- whatchanged = 'p'
-}
-
-# Variable is used in GitTabExpansion.ps1
-[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')]
-$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'
- 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 ammend 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'
- 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 '
- 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'
- 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'
- 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= notes no-notes show-notes no-standard-notes standard-notes show-signature'
- 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'
- tag = 'annotate sign local-user force delete verify list sort column no-column contains points-at message file cleanup'
- whatchanged = 'since'
-}
-
-# Variable is used in GitTabExpansion.ps1
-[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')]
-$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 = 'oneline short medium full fuller email raw'
- 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'
- }
- revert = @{
- strategy = 'resolve recursive octopus ours subtree'
- }
- show = @{
- pretty = 'oneline short medium full fuller email raw'
- format = 'oneline short medium full fuller email raw'
- encoding = 'utf-8'
- }
- status = @{
- 'untracked-files' = 'no normal all'
- 'ignore-submodules' = 'none untracked dirty all'
- }
-}
+# Variable is used in GitTabExpansion.ps1
+[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')]
+$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'
+ 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'
+ tag = 'a s u f d v n l m F'
+ whatchanged = 'p'
+}
+
+# Variable is used in GitTabExpansion.ps1
+[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')]
+$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'
+ 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 ammend 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'
+ 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 '
+ 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'
+ 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'
+ 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= notes no-notes show-notes no-standard-notes standard-notes show-signature'
+ 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'
+ tag = 'annotate sign local-user force delete verify list sort column no-column contains points-at message file cleanup'
+ whatchanged = 'since'
+}
+
+# Variable is used in GitTabExpansion.ps1
+[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')]
+$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 = 'oneline short medium full fuller email raw'
+ 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'
+ }
+ revert = @{
+ strategy = 'resolve recursive octopus ours subtree'
+ }
+ show = @{
+ pretty = 'oneline short medium full fuller email raw'
+ format = 'oneline short medium full fuller email raw'
+ encoding = 'utf-8'
+ }
+ status = @{
+ 'untracked-files' = 'no normal all'
+ 'ignore-submodules' = 'none untracked dirty all'
+ }
+}
diff --git a/src/GitPrompt.ps1 b/src/GitPrompt.ps1
index c2bef5319..ce3f9b2bd 100644
--- a/src/GitPrompt.ps1
+++ b/src/GitPrompt.ps1
@@ -1,316 +1,316 @@
-# Inspired by Mark Embling
-# http://www.markembling.info/view/my-ideal-powershell-prompt-with-git-integration
-
-$global:GitPromptSettings = [pscustomobject]@{
- DefaultForegroundColor = $Host.UI.RawUI.ForegroundColor
-
- BeforeText = ' ['
- BeforeForegroundColor = [ConsoleColor]::Yellow
- BeforeBackgroundColor = $Host.UI.RawUI.BackgroundColor
-
- DelimText = ' |'
- DelimForegroundColor = [ConsoleColor]::Yellow
- DelimBackgroundColor = $Host.UI.RawUI.BackgroundColor
-
- AfterText = ']'
- AfterForegroundColor = [ConsoleColor]::Yellow
- AfterBackgroundColor = $Host.UI.RawUI.BackgroundColor
-
- FileAddedText = '+'
- FileModifiedText = '~'
- FileRemovedText = '-'
- FileConflictedText = '!'
-
- LocalDefaultStatusSymbol = $null
- LocalDefaultStatusForegroundColor = [ConsoleColor]::DarkGreen
- LocalDefaultStatusForegroundBrightColor = [ConsoleColor]::Green
- LocalDefaultStatusBackgroundColor = $Host.UI.RawUI.BackgroundColor
-
- LocalWorkingStatusSymbol = '!'
- LocalWorkingStatusForegroundColor = [ConsoleColor]::DarkRed
- LocalWorkingStatusForegroundBrightColor = [ConsoleColor]::Red
- LocalWorkingStatusBackgroundColor = $Host.UI.RawUI.BackgroundColor
-
- LocalStagedStatusSymbol = '~'
- LocalStagedStatusForegroundColor = [ConsoleColor]::Cyan
- LocalStagedStatusBackgroundColor = $Host.UI.RawUI.BackgroundColor
-
- BranchUntrackedSymbol = $null
- BranchForegroundColor = [ConsoleColor]::Cyan
- BranchBackgroundColor = $Host.UI.RawUI.BackgroundColor
-
- BranchGoneStatusSymbol = [char]0x00D7 # × Multiplication sign
- BranchGoneStatusForegroundColor = [ConsoleColor]::DarkCyan
- BranchGoneStatusBackgroundColor = $Host.UI.RawUI.BackgroundColor
-
- BranchIdenticalStatusToSymbol = [char]0x2261 # ≡ Three horizontal lines
- BranchIdenticalStatusToForegroundColor = [ConsoleColor]::Cyan
- BranchIdenticalStatusToBackgroundColor = $Host.UI.RawUI.BackgroundColor
-
- BranchAheadStatusSymbol = [char]0x2191 # ↑ Up arrow
- BranchAheadStatusForegroundColor = [ConsoleColor]::Green
- BranchAheadStatusBackgroundColor = $Host.UI.RawUI.BackgroundColor
-
- BranchBehindStatusSymbol = [char]0x2193 # ↓ Down arrow
- BranchBehindStatusForegroundColor = [ConsoleColor]::Red
- BranchBehindStatusBackgroundColor = $Host.UI.RawUI.BackgroundColor
-
- BranchBehindAndAheadStatusSymbol = [char]0x2195 # ↕ Up & Down arrow
- BranchBehindAndAheadStatusForegroundColor = [ConsoleColor]::Yellow
- BranchBehindAndAheadStatusBackgroundColor = $Host.UI.RawUI.BackgroundColor
-
- BeforeIndexText = ""
- BeforeIndexForegroundColor = [ConsoleColor]::DarkGreen
- BeforeIndexForegroundBrightColor = [ConsoleColor]::Green
- BeforeIndexBackgroundColor = $Host.UI.RawUI.BackgroundColor
-
- IndexForegroundColor = [ConsoleColor]::DarkGreen
- IndexForegroundBrightColor = [ConsoleColor]::Green
- IndexBackgroundColor = $Host.UI.RawUI.BackgroundColor
-
- WorkingForegroundColor = [ConsoleColor]::DarkRed
- WorkingForegroundBrightColor = [ConsoleColor]::Red
- WorkingBackgroundColor = $Host.UI.RawUI.BackgroundColor
-
- EnableStashStatus = $false
- BeforeStashText = ' ('
- BeforeStashBackgroundColor = $Host.UI.RawUI.BackgroundColor
- BeforeStashForegroundColor = [ConsoleColor]::Red
- AfterStashText = ')'
- AfterStashBackgroundColor = $Host.UI.RawUI.BackgroundColor
- AfterStashForegroundColor = [ConsoleColor]::Red
- StashBackgroundColor = $Host.UI.RawUI.BackgroundColor
- StashForegroundColor = [ConsoleColor]::Red
-
- ShowStatusWhenZero = $true
-
- AutoRefreshIndex = $true
-
- # Valid values are "Full", "Compact", and "Minimal"
- BranchBehindAndAheadDisplay = "Full"
-
- EnablePromptStatus = !$Global:GitMissing
- EnableFileStatus = $true
- EnableFileStatusFromCache = $null
- RepositoriesInWhichToDisableFileStatus = @( ) # Array of repository paths
- DescribeStyle = ''
-
- EnableWindowTitle = 'posh~git ~ '
-
- DefaultPromptPrefix = ''
- DefaultPromptSuffix = '$(''>'' * ($nestedPromptLevel + 1)) '
- DefaultPromptDebugSuffix = ' [DBG]$(''>'' * ($nestedPromptLevel + 1)) '
- DefaultPromptEnableTiming = $false
- DefaultPromptAbbreviateHomeDirectory = $false
-
- Debug = $false
-
- BranchNameLimit = 0
- TruncatedBranchSuffix = '...'
-}
-
-# PowerShell 5.x only runs on Windows so use .NET types to determine isAdminProcess
-# Or if we are on v6 or higher, check the $IsWindows pre-defined variable.
-if (($PSVersionTable.PSVersion.Major -le 5) -or $IsWindows) {
- $currentUser = [Security.Principal.WindowsPrincipal]([Security.Principal.WindowsIdentity]::GetCurrent())
- $isAdminProcess = $currentUser.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
-}
-else {
- # Must be Linux or OSX, so use the id util. Root has userid of 0.
- $isAdminProcess = 0 -eq (id -u)
-}
-
-$adminHeader = if ($isAdminProcess) { 'Administrator: ' } else { '' }
-
-$WindowTitleSupported = $true
-if (Get-Module NuGet) {
- $WindowTitleSupported = $false
-}
-
-function Write-Prompt($Object, $ForegroundColor, $BackgroundColor = -1) {
- if ($BackgroundColor -lt 0) {
- Write-Host $Object -NoNewLine -ForegroundColor $ForegroundColor
- } else {
- Write-Host $Object -NoNewLine -ForegroundColor $ForegroundColor -BackgroundColor $BackgroundColor
- }
-}
-
-function Format-BranchName($branchName){
- $s = $global:GitPromptSettings
-
- if($s.BranchNameLimit -gt 0 -and $branchName.Length -gt $s.BranchNameLimit)
- {
- $branchName = "{0}{1}" -f $branchName.Substring(0,$s.BranchNameLimit), $s.TruncatedBranchSuffix
- }
-
- return $branchName
-}
-
-function Write-GitStatus($status) {
- $s = $global:GitPromptSettings
- if ($status -and $s) {
- Write-Prompt $s.BeforeText -BackgroundColor $s.BeforeBackgroundColor -ForegroundColor $s.BeforeForegroundColor
-
- $branchStatusText = $null
- $branchStatusBackgroundColor = $s.BranchBackgroundColor
- $branchStatusForegroundColor = $s.BranchForegroundColor
-
- if (!$status.Upstream) {
- $branchStatusText = $s.BranchUntrackedSymbol
- } elseif ($status.UpstreamGone -eq $true) {
- # Upstream branch is gone
- $branchStatusText = $s.BranchGoneStatusSymbol
- $branchStatusBackgroundColor = $s.BranchGoneStatusBackgroundColor
- $branchStatusForegroundColor = $s.BranchGoneStatusForegroundColor
- } elseif ($status.BehindBy -eq 0 -and $status.AheadBy -eq 0) {
- # We are aligned with remote
- $branchStatusText = $s.BranchIdenticalStatusToSymbol
- $branchStatusBackgroundColor = $s.BranchIdenticalStatusToBackgroundColor
- $branchStatusForegroundColor = $s.BranchIdenticalStatusToForegroundColor
- } elseif ($status.BehindBy -ge 1 -and $status.AheadBy -ge 1) {
- # We are both behind and ahead of remote
- if ($s.BranchBehindAndAheadDisplay -eq "Full") {
- $branchStatusText = ("{0}{1} {2}{3}" -f $s.BranchBehindStatusSymbol, $status.BehindBy, $s.BranchAheadStatusSymbol, $status.AheadBy)
- } elseif ($s.BranchBehindAndAheadDisplay -eq "Compact") {
- $branchStatusText = ("{0}{1}{2}" -f $status.BehindBy, $s.BranchBehindAndAheadStatusSymbol, $status.AheadBy)
- } else {
- $branchStatusText = $s.BranchBehindAndAheadStatusSymbol
- }
- $branchStatusBackgroundColor = $s.BranchBehindAndAheadStatusBackgroundColor
- $branchStatusForegroundColor = $s.BranchBehindAndAheadStatusForegroundColor
- } elseif ($status.BehindBy -ge 1) {
- # We are behind remote
- if ($s.BranchBehindAndAheadDisplay -eq "Full" -Or $s.BranchBehindAndAheadDisplay -eq "Compact") {
- $branchStatusText = ("{0}{1}" -f $s.BranchBehindStatusSymbol, $status.BehindBy)
- } else {
- $branchStatusText = $s.BranchBehindStatusSymbol
- }
- $branchStatusBackgroundColor = $s.BranchBehindStatusBackgroundColor
- $branchStatusForegroundColor = $s.BranchBehindStatusForegroundColor
- } elseif ($status.AheadBy -ge 1) {
- # We are ahead of remote
- if ($s.BranchBehindAndAheadDisplay -eq "Full" -Or $s.BranchBehindAndAheadDisplay -eq "Compact") {
- $branchStatusText = ("{0}{1}" -f $s.BranchAheadStatusSymbol, $status.AheadBy)
- } else {
- $branchStatusText = $s.BranchAheadStatusSymbol
- }
- $branchStatusBackgroundColor = $s.BranchAheadStatusBackgroundColor
- $branchStatusForegroundColor = $s.BranchAheadStatusForegroundColor
- } else {
- # This condition should not be possible but defaulting the variables to be safe
- $branchStatusText = "?"
- }
-
- Write-Prompt (Format-BranchName($status.Branch)) -BackgroundColor $branchStatusBackgroundColor -ForegroundColor $branchStatusForegroundColor
-
- if ($branchStatusText) {
- Write-Prompt (" {0}" -f $branchStatusText) -BackgroundColor $branchStatusBackgroundColor -ForegroundColor $branchStatusForegroundColor
- }
-
- if($s.EnableFileStatus -and $status.HasIndex) {
- Write-Prompt $s.BeforeIndexText -BackgroundColor $s.BeforeIndexBackgroundColor -ForegroundColor $s.BeforeIndexForegroundColor
-
- if($s.ShowStatusWhenZero -or $status.Index.Added) {
- Write-Prompt (" $($s.FileAddedText)$($status.Index.Added.Count)") -BackgroundColor $s.IndexBackgroundColor -ForegroundColor $s.IndexForegroundColor
- }
- if($s.ShowStatusWhenZero -or $status.Index.Modified) {
- Write-Prompt (" $($s.FileModifiedText)$($status.Index.Modified.Count)") -BackgroundColor $s.IndexBackgroundColor -ForegroundColor $s.IndexForegroundColor
- }
- if($s.ShowStatusWhenZero -or $status.Index.Deleted) {
- Write-Prompt (" $($s.FileRemovedText)$($status.Index.Deleted.Count)") -BackgroundColor $s.IndexBackgroundColor -ForegroundColor $s.IndexForegroundColor
- }
-
- if ($status.Index.Unmerged) {
- Write-Prompt (" $($s.FileConflictedText)$($status.Index.Unmerged.Count)") -BackgroundColor $s.IndexBackgroundColor -ForegroundColor $s.IndexForegroundColor
- }
-
- if($status.HasWorking) {
- Write-Prompt $s.DelimText -BackgroundColor $s.DelimBackgroundColor -ForegroundColor $s.DelimForegroundColor
- }
- }
-
- if($s.EnableFileStatus -and $status.HasWorking) {
- if($s.ShowStatusWhenZero -or $status.Working.Added) {
- Write-Prompt (" $($s.FileAddedText)$($status.Working.Added.Count)") -BackgroundColor $s.WorkingBackgroundColor -ForegroundColor $s.WorkingForegroundColor
- }
- if($s.ShowStatusWhenZero -or $status.Working.Modified) {
- Write-Prompt (" $($s.FileModifiedText)$($status.Working.Modified.Count)") -BackgroundColor $s.WorkingBackgroundColor -ForegroundColor $s.WorkingForegroundColor
- }
- if($s.ShowStatusWhenZero -or $status.Working.Deleted) {
- Write-Prompt (" $($s.FileRemovedText)$($status.Working.Deleted.Count)") -BackgroundColor $s.WorkingBackgroundColor -ForegroundColor $s.WorkingForegroundColor
- }
-
- if ($status.Working.Unmerged) {
- Write-Prompt (" $($s.FileConflictedText)$($status.Working.Unmerged.Count)") -BackgroundColor $s.WorkingBackgroundColor -ForegroundColor $s.WorkingForegroundColor
- }
- }
-
- if ($status.HasWorking) {
- # We have un-staged files in the working tree
- $localStatusSymbol = $s.LocalWorkingStatusSymbol
- $localStatusBackgroundColor = $s.LocalWorkingStatusBackgroundColor
- $localStatusForegroundColor = $s.LocalWorkingStatusForegroundColor
- } elseif ($status.HasIndex) {
- # We have staged but uncommited files
- $localStatusSymbol = $s.LocalStagedStatusSymbol
- $localStatusBackgroundColor = $s.LocalStagedStatusBackgroundColor
- $localStatusForegroundColor = $s.LocalStagedStatusForegroundColor
- } else {
- # No uncommited changes
- $localStatusSymbol = $s.LocalDefaultStatusSymbol
- $localStatusBackgroundColor = $s.LocalDefaultStatusBackgroundColor
- $localStatusForegroundColor = $s.LocalDefaultStatusForegroundColor
- }
-
- if ($localStatusSymbol) {
- Write-Prompt (" {0}" -f $localStatusSymbol) -BackgroundColor $localStatusBackgroundColor -ForegroundColor $localStatusForegroundColor
- }
-
- if ($s.EnableStashStatus -and ($status.StashCount -gt 0)) {
- Write-Prompt $s.BeforeStashText -BackgroundColor $s.BeforeStashBackgroundColor -ForegroundColor $s.BeforeStashForegroundColor
- Write-Prompt $status.StashCount -BackgroundColor $s.StashBackgroundColor -ForegroundColor $s.StashForegroundColor
- Write-Prompt $s.AfterStashText -BackgroundColor $s.AfterStashBackgroundColor -ForegroundColor $s.AfterStashForegroundColor
- }
-
- Write-Prompt $s.AfterText -BackgroundColor $s.AfterBackgroundColor -ForegroundColor $s.AfterForegroundColor
-
- if ($WindowTitleSupported -and $s.EnableWindowTitle) {
- if( -not $Global:PreviousWindowTitle ) {
- $Global:PreviousWindowTitle = $Host.UI.RawUI.WindowTitle
- }
- $repoName = Split-Path -Leaf (Split-Path $status.GitDir)
- $prefix = if ($s.EnableWindowTitle -is [string]) { $s.EnableWindowTitle } else { '' }
- $Host.UI.RawUI.WindowTitle = "$script:adminHeader$prefix$repoName [$($status.Branch)]"
- }
- } elseif ( $Global:PreviousWindowTitle ) {
- $Host.UI.RawUI.WindowTitle = $Global:PreviousWindowTitle
- }
-}
-
-if(!(Test-Path Variable:Global:VcsPromptStatuses)) {
- $Global:VcsPromptStatuses = @()
-}
-$s = $global:GitPromptSettings
-
-# Override some of the normal colors if the background color is set to the default DarkMagenta.
-if ($Host.UI.RawUI.BackgroundColor -eq [ConsoleColor]::DarkMagenta) {
- $s.LocalDefaultStatusForegroundColor = $s.LocalDefaultStatusForegroundBrightColor
- $s.LocalWorkingStatusForegroundColor = $s.LocalWorkingStatusForegroundBrightColor
-
- $s.BeforeIndexForegroundColor = $s.BeforeIndexForegroundBrightColor
- $s.IndexForegroundColor = $s.IndexForegroundBrightColor
-
- $s.WorkingForegroundColor = $s.WorkingForegroundBrightColor
-}
-
-function Global:Write-VcsStatus {
- $Global:VcsPromptStatuses | ForEach-Object { & $_ }
-}
-
-# Add scriptblock that will execute for Write-VcsStatus
-$PoshGitVcsPrompt = {
- $Global:GitStatus = Get-GitStatus
- Write-GitStatus $GitStatus
-}
-
-$Global:VcsPromptStatuses += $PoshGitVcsPrompt
+# Inspired by Mark Embling
+# http://www.markembling.info/view/my-ideal-powershell-prompt-with-git-integration
+
+$global:GitPromptSettings = [pscustomobject]@{
+ DefaultForegroundColor = $Host.UI.RawUI.ForegroundColor
+
+ BeforeText = ' ['
+ BeforeForegroundColor = [ConsoleColor]::Yellow
+ BeforeBackgroundColor = $Host.UI.RawUI.BackgroundColor
+
+ DelimText = ' |'
+ DelimForegroundColor = [ConsoleColor]::Yellow
+ DelimBackgroundColor = $Host.UI.RawUI.BackgroundColor
+
+ AfterText = ']'
+ AfterForegroundColor = [ConsoleColor]::Yellow
+ AfterBackgroundColor = $Host.UI.RawUI.BackgroundColor
+
+ FileAddedText = '+'
+ FileModifiedText = '~'
+ FileRemovedText = '-'
+ FileConflictedText = '!'
+
+ LocalDefaultStatusSymbol = $null
+ LocalDefaultStatusForegroundColor = [ConsoleColor]::DarkGreen
+ LocalDefaultStatusForegroundBrightColor = [ConsoleColor]::Green
+ LocalDefaultStatusBackgroundColor = $Host.UI.RawUI.BackgroundColor
+
+ LocalWorkingStatusSymbol = '!'
+ LocalWorkingStatusForegroundColor = [ConsoleColor]::DarkRed
+ LocalWorkingStatusForegroundBrightColor = [ConsoleColor]::Red
+ LocalWorkingStatusBackgroundColor = $Host.UI.RawUI.BackgroundColor
+
+ LocalStagedStatusSymbol = '~'
+ LocalStagedStatusForegroundColor = [ConsoleColor]::Cyan
+ LocalStagedStatusBackgroundColor = $Host.UI.RawUI.BackgroundColor
+
+ BranchUntrackedSymbol = $null
+ BranchForegroundColor = [ConsoleColor]::Cyan
+ BranchBackgroundColor = $Host.UI.RawUI.BackgroundColor
+
+ BranchGoneStatusSymbol = [char]0x00D7 # × Multiplication sign
+ BranchGoneStatusForegroundColor = [ConsoleColor]::DarkCyan
+ BranchGoneStatusBackgroundColor = $Host.UI.RawUI.BackgroundColor
+
+ BranchIdenticalStatusToSymbol = [char]0x2261 # ≡ Three horizontal lines
+ BranchIdenticalStatusToForegroundColor = [ConsoleColor]::Cyan
+ BranchIdenticalStatusToBackgroundColor = $Host.UI.RawUI.BackgroundColor
+
+ BranchAheadStatusSymbol = [char]0x2191 # ↑ Up arrow
+ BranchAheadStatusForegroundColor = [ConsoleColor]::Green
+ BranchAheadStatusBackgroundColor = $Host.UI.RawUI.BackgroundColor
+
+ BranchBehindStatusSymbol = [char]0x2193 # ↓ Down arrow
+ BranchBehindStatusForegroundColor = [ConsoleColor]::Red
+ BranchBehindStatusBackgroundColor = $Host.UI.RawUI.BackgroundColor
+
+ BranchBehindAndAheadStatusSymbol = [char]0x2195 # ↕ Up & Down arrow
+ BranchBehindAndAheadStatusForegroundColor = [ConsoleColor]::Yellow
+ BranchBehindAndAheadStatusBackgroundColor = $Host.UI.RawUI.BackgroundColor
+
+ BeforeIndexText = ""
+ BeforeIndexForegroundColor = [ConsoleColor]::DarkGreen
+ BeforeIndexForegroundBrightColor = [ConsoleColor]::Green
+ BeforeIndexBackgroundColor = $Host.UI.RawUI.BackgroundColor
+
+ IndexForegroundColor = [ConsoleColor]::DarkGreen
+ IndexForegroundBrightColor = [ConsoleColor]::Green
+ IndexBackgroundColor = $Host.UI.RawUI.BackgroundColor
+
+ WorkingForegroundColor = [ConsoleColor]::DarkRed
+ WorkingForegroundBrightColor = [ConsoleColor]::Red
+ WorkingBackgroundColor = $Host.UI.RawUI.BackgroundColor
+
+ EnableStashStatus = $false
+ BeforeStashText = ' ('
+ BeforeStashBackgroundColor = $Host.UI.RawUI.BackgroundColor
+ BeforeStashForegroundColor = [ConsoleColor]::Red
+ AfterStashText = ')'
+ AfterStashBackgroundColor = $Host.UI.RawUI.BackgroundColor
+ AfterStashForegroundColor = [ConsoleColor]::Red
+ StashBackgroundColor = $Host.UI.RawUI.BackgroundColor
+ StashForegroundColor = [ConsoleColor]::Red
+
+ ShowStatusWhenZero = $true
+
+ AutoRefreshIndex = $true
+
+ # Valid values are "Full", "Compact", and "Minimal"
+ BranchBehindAndAheadDisplay = "Full"
+
+ EnablePromptStatus = !$Global:GitMissing
+ EnableFileStatus = $true
+ EnableFileStatusFromCache = $null
+ RepositoriesInWhichToDisableFileStatus = @( ) # Array of repository paths
+ DescribeStyle = ''
+
+ EnableWindowTitle = 'posh~git ~ '
+
+ DefaultPromptPrefix = ''
+ DefaultPromptSuffix = '$(''>'' * ($nestedPromptLevel + 1)) '
+ DefaultPromptDebugSuffix = ' [DBG]$(''>'' * ($nestedPromptLevel + 1)) '
+ DefaultPromptEnableTiming = $false
+ DefaultPromptAbbreviateHomeDirectory = $false
+
+ Debug = $false
+
+ BranchNameLimit = 0
+ TruncatedBranchSuffix = '...'
+}
+
+# PowerShell 5.x only runs on Windows so use .NET types to determine isAdminProcess
+# Or if we are on v6 or higher, check the $IsWindows pre-defined variable.
+if (($PSVersionTable.PSVersion.Major -le 5) -or $IsWindows) {
+ $currentUser = [Security.Principal.WindowsPrincipal]([Security.Principal.WindowsIdentity]::GetCurrent())
+ $isAdminProcess = $currentUser.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
+}
+else {
+ # Must be Linux or OSX, so use the id util. Root has userid of 0.
+ $isAdminProcess = 0 -eq (id -u)
+}
+
+$adminHeader = if ($isAdminProcess) { 'Administrator: ' } else { '' }
+
+$WindowTitleSupported = $true
+if (Get-Module NuGet) {
+ $WindowTitleSupported = $false
+}
+
+function Write-Prompt($Object, $ForegroundColor, $BackgroundColor = -1) {
+ if ($BackgroundColor -lt 0) {
+ Write-Host $Object -NoNewLine -ForegroundColor $ForegroundColor
+ } else {
+ Write-Host $Object -NoNewLine -ForegroundColor $ForegroundColor -BackgroundColor $BackgroundColor
+ }
+}
+
+function Format-BranchName($branchName){
+ $s = $global:GitPromptSettings
+
+ if($s.BranchNameLimit -gt 0 -and $branchName.Length -gt $s.BranchNameLimit)
+ {
+ $branchName = "{0}{1}" -f $branchName.Substring(0,$s.BranchNameLimit), $s.TruncatedBranchSuffix
+ }
+
+ return $branchName
+}
+
+function Write-GitStatus($status) {
+ $s = $global:GitPromptSettings
+ if ($status -and $s) {
+ Write-Prompt $s.BeforeText -BackgroundColor $s.BeforeBackgroundColor -ForegroundColor $s.BeforeForegroundColor
+
+ $branchStatusText = $null
+ $branchStatusBackgroundColor = $s.BranchBackgroundColor
+ $branchStatusForegroundColor = $s.BranchForegroundColor
+
+ if (!$status.Upstream) {
+ $branchStatusText = $s.BranchUntrackedSymbol
+ } elseif ($status.UpstreamGone -eq $true) {
+ # Upstream branch is gone
+ $branchStatusText = $s.BranchGoneStatusSymbol
+ $branchStatusBackgroundColor = $s.BranchGoneStatusBackgroundColor
+ $branchStatusForegroundColor = $s.BranchGoneStatusForegroundColor
+ } elseif ($status.BehindBy -eq 0 -and $status.AheadBy -eq 0) {
+ # We are aligned with remote
+ $branchStatusText = $s.BranchIdenticalStatusToSymbol
+ $branchStatusBackgroundColor = $s.BranchIdenticalStatusToBackgroundColor
+ $branchStatusForegroundColor = $s.BranchIdenticalStatusToForegroundColor
+ } elseif ($status.BehindBy -ge 1 -and $status.AheadBy -ge 1) {
+ # We are both behind and ahead of remote
+ if ($s.BranchBehindAndAheadDisplay -eq "Full") {
+ $branchStatusText = ("{0}{1} {2}{3}" -f $s.BranchBehindStatusSymbol, $status.BehindBy, $s.BranchAheadStatusSymbol, $status.AheadBy)
+ } elseif ($s.BranchBehindAndAheadDisplay -eq "Compact") {
+ $branchStatusText = ("{0}{1}{2}" -f $status.BehindBy, $s.BranchBehindAndAheadStatusSymbol, $status.AheadBy)
+ } else {
+ $branchStatusText = $s.BranchBehindAndAheadStatusSymbol
+ }
+ $branchStatusBackgroundColor = $s.BranchBehindAndAheadStatusBackgroundColor
+ $branchStatusForegroundColor = $s.BranchBehindAndAheadStatusForegroundColor
+ } elseif ($status.BehindBy -ge 1) {
+ # We are behind remote
+ if ($s.BranchBehindAndAheadDisplay -eq "Full" -Or $s.BranchBehindAndAheadDisplay -eq "Compact") {
+ $branchStatusText = ("{0}{1}" -f $s.BranchBehindStatusSymbol, $status.BehindBy)
+ } else {
+ $branchStatusText = $s.BranchBehindStatusSymbol
+ }
+ $branchStatusBackgroundColor = $s.BranchBehindStatusBackgroundColor
+ $branchStatusForegroundColor = $s.BranchBehindStatusForegroundColor
+ } elseif ($status.AheadBy -ge 1) {
+ # We are ahead of remote
+ if ($s.BranchBehindAndAheadDisplay -eq "Full" -Or $s.BranchBehindAndAheadDisplay -eq "Compact") {
+ $branchStatusText = ("{0}{1}" -f $s.BranchAheadStatusSymbol, $status.AheadBy)
+ } else {
+ $branchStatusText = $s.BranchAheadStatusSymbol
+ }
+ $branchStatusBackgroundColor = $s.BranchAheadStatusBackgroundColor
+ $branchStatusForegroundColor = $s.BranchAheadStatusForegroundColor
+ } else {
+ # This condition should not be possible but defaulting the variables to be safe
+ $branchStatusText = "?"
+ }
+
+ Write-Prompt (Format-BranchName($status.Branch)) -BackgroundColor $branchStatusBackgroundColor -ForegroundColor $branchStatusForegroundColor
+
+ if ($branchStatusText) {
+ Write-Prompt (" {0}" -f $branchStatusText) -BackgroundColor $branchStatusBackgroundColor -ForegroundColor $branchStatusForegroundColor
+ }
+
+ if($s.EnableFileStatus -and $status.HasIndex) {
+ Write-Prompt $s.BeforeIndexText -BackgroundColor $s.BeforeIndexBackgroundColor -ForegroundColor $s.BeforeIndexForegroundColor
+
+ if($s.ShowStatusWhenZero -or $status.Index.Added) {
+ Write-Prompt (" $($s.FileAddedText)$($status.Index.Added.Count)") -BackgroundColor $s.IndexBackgroundColor -ForegroundColor $s.IndexForegroundColor
+ }
+ if($s.ShowStatusWhenZero -or $status.Index.Modified) {
+ Write-Prompt (" $($s.FileModifiedText)$($status.Index.Modified.Count)") -BackgroundColor $s.IndexBackgroundColor -ForegroundColor $s.IndexForegroundColor
+ }
+ if($s.ShowStatusWhenZero -or $status.Index.Deleted) {
+ Write-Prompt (" $($s.FileRemovedText)$($status.Index.Deleted.Count)") -BackgroundColor $s.IndexBackgroundColor -ForegroundColor $s.IndexForegroundColor
+ }
+
+ if ($status.Index.Unmerged) {
+ Write-Prompt (" $($s.FileConflictedText)$($status.Index.Unmerged.Count)") -BackgroundColor $s.IndexBackgroundColor -ForegroundColor $s.IndexForegroundColor
+ }
+
+ if($status.HasWorking) {
+ Write-Prompt $s.DelimText -BackgroundColor $s.DelimBackgroundColor -ForegroundColor $s.DelimForegroundColor
+ }
+ }
+
+ if($s.EnableFileStatus -and $status.HasWorking) {
+ if($s.ShowStatusWhenZero -or $status.Working.Added) {
+ Write-Prompt (" $($s.FileAddedText)$($status.Working.Added.Count)") -BackgroundColor $s.WorkingBackgroundColor -ForegroundColor $s.WorkingForegroundColor
+ }
+ if($s.ShowStatusWhenZero -or $status.Working.Modified) {
+ Write-Prompt (" $($s.FileModifiedText)$($status.Working.Modified.Count)") -BackgroundColor $s.WorkingBackgroundColor -ForegroundColor $s.WorkingForegroundColor
+ }
+ if($s.ShowStatusWhenZero -or $status.Working.Deleted) {
+ Write-Prompt (" $($s.FileRemovedText)$($status.Working.Deleted.Count)") -BackgroundColor $s.WorkingBackgroundColor -ForegroundColor $s.WorkingForegroundColor
+ }
+
+ if ($status.Working.Unmerged) {
+ Write-Prompt (" $($s.FileConflictedText)$($status.Working.Unmerged.Count)") -BackgroundColor $s.WorkingBackgroundColor -ForegroundColor $s.WorkingForegroundColor
+ }
+ }
+
+ if ($status.HasWorking) {
+ # We have un-staged files in the working tree
+ $localStatusSymbol = $s.LocalWorkingStatusSymbol
+ $localStatusBackgroundColor = $s.LocalWorkingStatusBackgroundColor
+ $localStatusForegroundColor = $s.LocalWorkingStatusForegroundColor
+ } elseif ($status.HasIndex) {
+ # We have staged but uncommited files
+ $localStatusSymbol = $s.LocalStagedStatusSymbol
+ $localStatusBackgroundColor = $s.LocalStagedStatusBackgroundColor
+ $localStatusForegroundColor = $s.LocalStagedStatusForegroundColor
+ } else {
+ # No uncommited changes
+ $localStatusSymbol = $s.LocalDefaultStatusSymbol
+ $localStatusBackgroundColor = $s.LocalDefaultStatusBackgroundColor
+ $localStatusForegroundColor = $s.LocalDefaultStatusForegroundColor
+ }
+
+ if ($localStatusSymbol) {
+ Write-Prompt (" {0}" -f $localStatusSymbol) -BackgroundColor $localStatusBackgroundColor -ForegroundColor $localStatusForegroundColor
+ }
+
+ if ($s.EnableStashStatus -and ($status.StashCount -gt 0)) {
+ Write-Prompt $s.BeforeStashText -BackgroundColor $s.BeforeStashBackgroundColor -ForegroundColor $s.BeforeStashForegroundColor
+ Write-Prompt $status.StashCount -BackgroundColor $s.StashBackgroundColor -ForegroundColor $s.StashForegroundColor
+ Write-Prompt $s.AfterStashText -BackgroundColor $s.AfterStashBackgroundColor -ForegroundColor $s.AfterStashForegroundColor
+ }
+
+ Write-Prompt $s.AfterText -BackgroundColor $s.AfterBackgroundColor -ForegroundColor $s.AfterForegroundColor
+
+ if ($WindowTitleSupported -and $s.EnableWindowTitle) {
+ if( -not $Global:PreviousWindowTitle ) {
+ $Global:PreviousWindowTitle = $Host.UI.RawUI.WindowTitle
+ }
+ $repoName = Split-Path -Leaf (Split-Path $status.GitDir)
+ $prefix = if ($s.EnableWindowTitle -is [string]) { $s.EnableWindowTitle } else { '' }
+ $Host.UI.RawUI.WindowTitle = "$script:adminHeader$prefix$repoName [$($status.Branch)]"
+ }
+ } elseif ( $Global:PreviousWindowTitle ) {
+ $Host.UI.RawUI.WindowTitle = $Global:PreviousWindowTitle
+ }
+}
+
+if(!(Test-Path Variable:Global:VcsPromptStatuses)) {
+ $Global:VcsPromptStatuses = @()
+}
+$s = $global:GitPromptSettings
+
+# Override some of the normal colors if the background color is set to the default DarkMagenta.
+if ($Host.UI.RawUI.BackgroundColor -eq [ConsoleColor]::DarkMagenta) {
+ $s.LocalDefaultStatusForegroundColor = $s.LocalDefaultStatusForegroundBrightColor
+ $s.LocalWorkingStatusForegroundColor = $s.LocalWorkingStatusForegroundBrightColor
+
+ $s.BeforeIndexForegroundColor = $s.BeforeIndexForegroundBrightColor
+ $s.IndexForegroundColor = $s.IndexForegroundBrightColor
+
+ $s.WorkingForegroundColor = $s.WorkingForegroundBrightColor
+}
+
+function Global:Write-VcsStatus {
+ $Global:VcsPromptStatuses | ForEach-Object { & $_ }
+}
+
+# Add scriptblock that will execute for Write-VcsStatus
+$PoshGitVcsPrompt = {
+ $Global:GitStatus = Get-GitStatus
+ Write-GitStatus $GitStatus
+}
+
+$Global:VcsPromptStatuses += $PoshGitVcsPrompt
diff --git a/src/GitTabExpansion.ps1 b/src/GitTabExpansion.ps1
index 5b6b74187..ed824b556 100644
--- a/src/GitTabExpansion.ps1
+++ b/src/GitTabExpansion.ps1
@@ -1,410 +1,410 @@
-# 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
-}
-
-$subcommands = @{
- bisect = 'start bad good skip reset visualize replay log run'
- notes = 'edit show'
- reflog = 'expire delete show'
- remote = 'add rename rm set-head show prune update'
- stash = 'list show drop pop apply branch save clear create'
- submodule = 'add status init update summary foreach sync'
- svn = 'init fetch clone rebase dcommit branch tag log blame find-rev set-tree create-ignore show-ignore mkdirs commit-diff info proplist propget show-externals gc reset'
- tfs = 'bootstrap checkin checkintool ct cleanup cleanup-workspaces clone diagnostics fetch help init pull quick-clone rcheckin shelve shelve-list unshelve verify'
- flow = 'init feature bugfix release hotfix support help version config finish delete publish rebase'
- worktree = 'add list prune'
-}
-
-$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 -split ' ' | 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','revert','rm',
- 'shortlog','show','stash','status','submodule','svn','tag','whatchanged', 'worktree')
-
-$script:gitCommandsWithLongParams = $longGitParams.Keys -join '|'
-$script:gitCommandsWithShortParams = $shortGitParams.Keys -join '|'
-$script:gitCommandsWithParamValues = $gitParamValues.Keys -join '|'
-
-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: $_"
-}
-
-function script:gitCommands($filter, $includeAliases) {
- $cmdList = @()
- if (-not $global:GitTabSettings.AllCommands) {
- $cmdList += $someCommands -like "$filter*"
- }
- else {
- $cmdList += git help --all |
- Where-Object { $_ -match '^ \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*" }
-}
-
-function script:gitBranches($filter, $includeHEAD = $false, $prefix = '') {
- if ($filter -match "^(?\S*\.{2,3})(?.*)") {
- $prefix += $matches['from']
- $filter = $matches['to']
- }
-
- $branches = @(git branch --no-color | ForEach-Object { if (($_ -notmatch "^\* \(HEAD detached .+\)$") -and ($_ -match "^\*?\s*(?[.*)")) { $matches['ref'] } }) +
- @(git branch --no-color -r | ForEach-Object { if ($_ -match "^ (?][\S+)(?: -> .+)?") { $matches['ref'] } }) +
- @(if ($includeHEAD) { 'HEAD','FETCH_HEAD','ORIG_HEAD','MERGE_HEAD' })
-
- $branches |
- Where-Object { $_ -ne '(no branch)' -and $_ -like "$filter*" } |
- ForEach-Object { $prefix + $_ }
-}
-
-function script:gitRemoteUniqueBranches($filter) {
- git branch --no-color -r |
- ForEach-Object { if ($_ -match "^ (?[^/]+)/(?\S+)(?! -> .+)?$") { $matches['branch'] } } |
- Group-Object -NoElement |
- Where-Object { $_.Count -eq 1 } |
- Select-Object -ExpandProperty Name |
- Where-Object { $_ -like "$filter*" }
-}
-
-function script:gitTags($filter, $prefix = '') {
- git tag |
- Where-Object { $_ -like "$filter*" } |
- ForEach-Object { $prefix + $_ }
-}
-
-function script:gitFeatures($filter, $command){
- $featurePrefix = git config --local --get "gitflow.prefix.$command"
- $branches = @(git branch --no-color | ForEach-Object { if ($_ -match "^\*?\s*$featurePrefix(?][.*)") { $matches['ref'] } })
- $branches |
- Where-Object { $_ -ne '(no branch)' -and $_ -like "$filter*" } |
- ForEach-Object { $prefix + $_ }
-}
-
-function script:gitRemoteBranches($remote, $ref, $filter, $prefix = '') {
- git branch --no-color -r |
- Where-Object { $_ -like " $remote/$filter*" } |
- ForEach-Object { $prefix + $ref + ($_ -replace " $remote/","") }
-}
-
-function script:gitStashes($filter) {
- (git stash list) -replace ':.*','' |
- Where-Object { $_ -like "$filter*" } |
- ForEach-Object { "'$_'" }
-}
-
-function script:gitTfsShelvesets($filter) {
- (git tfs shelve-list) |
- Where-Object { $_ -like "$filter*" } |
- ForEach-Object { "'$_'" }
-}
-
-function script:gitFiles($filter, $files) {
- $files | Sort-Object |
- Where-Object { $_ -like "$filter*" } |
- ForEach-Object { if ($_ -like '* *') { "'$_'" } else { $_ } }
-}
-
-function script:gitIndex($filter) {
- gitFiles $filter $GitStatus.Index
-}
-
-function script:gitAddFiles($filter) {
- gitFiles $filter (@($GitStatus.Working.Unmerged) + @($GitStatus.Working.Modified) + @($GitStatus.Working.Added))
-}
-
-function script:gitCheckoutFiles($filter) {
- gitFiles $filter (@($GitStatus.Working.Unmerged) + @($GitStatus.Working.Modified) + @($GitStatus.Working.Deleted))
-}
-
-function script:gitDiffFiles($filter, $staged) {
- if ($staged) {
- gitFiles $filter $GitStatus.Index.Modified
- }
- else {
- gitFiles $filter (@($GitStatus.Working.Unmerged) + @($GitStatus.Working.Modified) + @($GitStatus.Index.Modified))
- }
-}
-
-function script:gitMergeFiles($filter) {
- gitFiles $filter $GitStatus.Working.Unmerged
-}
-
-function script:gitDeleted($filter) {
- gitFiles $filter $GitStatus.Working.Deleted
-}
-
-function script:gitAliases($filter) {
- git config --get-regexp ^alias\. | ForEach-Object{
- if ($_ -match "^alias\.(?\S+) .*") {
- $alias = $Matches['alias']
- if ($alias -like "$filter*") {
- $alias
- }
- }
- } | Sort-Object
-}
-
-function script:expandGitAlias($cmd, $rest) {
- if ((git config --get-regexp "^alias\.$cmd`$") -match "^alias\.$cmd (?[^!].*)`$") {
- return "git $($Matches['cmd'])$rest"
- }
- else {
- return "git $cmd$rest"
- }
-}
-
-function script:expandLongParams($cmd, $filter) {
- $longGitParams[$cmd] -split ' ' |
- Where-Object { $_ -like "$filter*" } |
- Sort-Object |
- ForEach-Object { -join ("--", $_) }
-}
-
-function script:expandShortParams($cmd, $filter) {
- $shortGitParams[$cmd] -split ' ' |
- Where-Object { $_ -like "$filter*" } |
- Sort-Object |
- ForEach-Object { -join ("-", $_) }
-}
-
-function script:expandParamValues($cmd, $param, $filter) {
- $gitParamValues[$cmd][$param] -split ' ' |
- Where-Object { $_ -like "$filter*" } |
- Sort-Object |
- ForEach-Object { -join ("--", $param, "=", $_) }
-}
-
-function GitTabExpansion($lastBlock) {
- $res = Invoke-Utf8ConsoleCommand { GitTabExpansionInternal $lastBlock }
- $res
-}
-
-function GitTabExpansionInternal($lastBlock) {
- $ignoreGitParams = '(?\s+-(?:[aA-zZ0-9]+|-[aA-zZ0-9][aA-zZ0-9-]*)(?:=\S+)?)*'
-
- if ($lastBlock -match "^$(Get-AliasPattern git) (?\S+)(? .*)$") {
- $lastBlock = expandGitAlias $Matches['cmd'] $Matches['args']
- }
-
- # Handles tgit (tortoisegit)
- if ($lastBlock -match "^$(Get-AliasPattern tgit) (?\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).* (?][\S*)$"){
- return gitBranches $matches['ref'] $true
- }
-
- switch -regex ($lastBlock -replace "^$(Get-AliasPattern git) ","") {
-
- # Handles git
- "^(?$($subcommands.Keys -join '|'))\s+(?\S*)$" {
- gitCmdOperations $subcommands $matches['cmd'] $matches['op']
- }
-
- # Handles git flow
- "^flow (?$($gitflowsubcommands.Keys -join '|'))\s+(?\S*)$" {
- gitCmdOperations $gitflowsubcommands $matches['cmd'] $matches['op']
- }
-
- # Handles git flow
- "^flow (?\S*)\s+(?\S*)\s+(?\S*)$" {
- gitFeatures $matches['name'] $matches['command']
- }
-
- # Handles git remote (rename|rm|set-head|set-branches|set-url|show|prune)
- "^remote.* (?:rename|rm|set-head|set-branches|set-url|show|prune).* (?\S*)$" {
- gitRemotes $matches['remote']
- }
-
- # Handles git stash (show|apply|drop|pop|branch)
- "^stash (?:show|apply|drop|pop|branch).* (?\S*)$" {
- gitStashes $matches['stash']
- }
-
- # Handles git bisect (bad|good|reset|skip) ][
- "^bisect (?:bad|good|reset|skip).* (?][\S*)$" {
- gitBranches $matches['ref'] $true
- }
-
- # Handles git tfs unshelve
- "^tfs +unshelve.* (?\S*)$" {
- gitTfsShelvesets $matches['shelveset']
- }
-
- # Handles git branch -d|-D|-m|-M
- # Handles git branch
- "^branch.* (?\S*)$" {
- gitBranches $matches['branch']
- }
-
- # Handles git (commands & aliases)
- "^(?\S*)$" {
- gitCommands $matches['cmd'] $TRUE
- }
-
- # Handles git help (commands only)
- "^help (?\S*)$" {
- gitCommands $matches['cmd'] $FALSE
- }
-
- # Handles git push remote ][:
- # Handles git push remote +][:
- "^push${ignoreGitParams}\s+(?[^\s-]\S*).*\s+(?\+?)(?][[^\s\:]*\:)(?\S*)$" {
- gitRemoteBranches $matches['remote'] $matches['ref'] $matches['branch'] -prefix $matches['force']
- }
-
- # Handles git push remote ][
- # Handles git push remote +][
- # Handles git pull remote ][
- "^(?:push|pull)${ignoreGitParams}\s+(?[^\s-]\S*).*\s+(?\+?)(?][[^\s\:]*)$" {
- gitBranches $matches['ref'] -prefix $matches['force']
- gitTags $matches['ref'] -prefix $matches['force']
- }
-
- # Handles git pull
- # Handles git push
- # Handles git fetch
- "^(?:push|pull|fetch)${ignoreGitParams}\s+(?\S*)$" {
- gitRemotes $matches['remote']
- }
-
- # Handles git reset HEAD
- # Handles git reset HEAD --
- "^reset.* HEAD(?:\s+--)? (?\S*)$" {
- gitIndex $matches['path']
- }
-
- # Handles git ][
- "^commit.*-C\s+(?][\S*)$" {
- gitBranches $matches['ref'] $true
- }
-
- # Handles git add
- "^add.* (?\S*)$" {
- gitAddFiles $matches['files']
- }
-
- # Handles git checkout --
- "^checkout.* -- (?\S*)$" {
- gitCheckoutFiles $matches['files']
- }
-
- # Handles git rm
- "^rm.* (?\S*)$" {
- gitDeleted $matches['index']
- }
-
- # Handles git diff/difftool
- "^(?:diff|difftool)(?:.* (?(?:--cached|--staged))|.*) (?\S*)$" {
- gitDiffFiles $matches['files'] $matches['staged']
- }
-
- # Handles git merge/mergetool
- "^(?:merge|mergetool).* (?\S*)$" {
- gitMergeFiles $matches['files']
- }
-
- # Handles git checkout ][
- "^(?:checkout).* (?][\S*)$" {
- gitBranches $matches['ref'] $true
- gitRemoteUniqueBranches $matches['ref']
- gitTags $matches['ref']
- }
-
- # Handles git worktree add ][
- "^worktree add.* (?\S+) (?][\S*)$" {
- gitBranches $matches['ref']
- }
-
- # Handles git ][
- "^(?:cherry|cherry-pick|diff|difftool|log|merge|rebase|reflog\s+show|reset|revert|show).* (?][\S*)$" {
- gitBranches $matches['ref'] $true
- gitTags $matches['ref']
- }
-
- # Handles git --=
- "^(?$gitCommandsWithParamValues).* --(?[^=]+)=(?\S*)$" {
- expandParamValues $matches['cmd'] $matches['param'] $matches['value']
- }
-
- # Handles git --
- "^(?$gitCommandsWithLongParams).* --(?\S*)$" {
- expandLongParams $matches['cmd'] $matches['param']
- }
-
- # Handles git -
- "^(?$gitCommandsWithShortParams).* -(?\S*)$" {
- expandShortParams $matches['cmd'] $matches['shortparam']
- }
- }
-}
-
-$PowerTab_RegisterTabExpansion = if (Get-Module -Name powertab) { Get-Command Register-TabExpansion -Module powertab -ErrorAction SilentlyContinue }
-if ($PowerTab_RegisterTabExpansion) {
- & $PowerTab_RegisterTabExpansion "git.exe" -Type Command {
- param($Context, [ref]$TabExpansionHasOutput, [ref]$QuoteSpaces) # 1:
-
- $line = $Context.Line
- $lastBlock = [regex]::Split($line, '[|;]')[-1].TrimStart()
- $TabExpansionHasOutput.Value = $true
- GitTabExpansion $lastBlock
- }
- return
-}
-
-if (Test-Path Function:\TabExpansion) {
- Rename-Item Function:\TabExpansion TabExpansionBackup
-}
-
-function TabExpansion($line, $lastWord) {
- $lastBlock = [regex]::Split($line, '[|;]')[-1].TrimStart()
-
- switch -regex ($lastBlock) {
- # Execute git tab completion for all git-related commands
- "^$(Get-AliasPattern git) (.*)" { GitTabExpansion $lastBlock }
- "^$(Get-AliasPattern tgit) (.*)" { GitTabExpansion $lastBlock }
- "^$(Get-AliasPattern gitk) (.*)" { GitTabExpansion $lastBlock }
-
- # Fall back on existing tab expansion
- default {
- if (Test-Path Function:\TabExpansionBackup) {
- TabExpansionBackup $line $lastWord
- }
- }
- }
-}
+# 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
+}
+
+$subcommands = @{
+ bisect = 'start bad good skip reset visualize replay log run'
+ notes = 'edit show'
+ reflog = 'expire delete show'
+ remote = 'add rename rm set-head show prune update'
+ stash = 'list show drop pop apply branch save clear create'
+ submodule = 'add status init update summary foreach sync'
+ svn = 'init fetch clone rebase dcommit branch tag log blame find-rev set-tree create-ignore show-ignore mkdirs commit-diff info proplist propget show-externals gc reset'
+ tfs = 'bootstrap checkin checkintool ct cleanup cleanup-workspaces clone diagnostics fetch help init pull quick-clone rcheckin shelve shelve-list unshelve verify'
+ flow = 'init feature bugfix release hotfix support help version config finish delete publish rebase'
+ worktree = 'add list prune'
+}
+
+$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 -split ' ' | 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','revert','rm',
+ 'shortlog','show','stash','status','submodule','svn','tag','whatchanged', 'worktree')
+
+$script:gitCommandsWithLongParams = $longGitParams.Keys -join '|'
+$script:gitCommandsWithShortParams = $shortGitParams.Keys -join '|'
+$script:gitCommandsWithParamValues = $gitParamValues.Keys -join '|'
+
+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: $_"
+}
+
+function script:gitCommands($filter, $includeAliases) {
+ $cmdList = @()
+ if (-not $global:GitTabSettings.AllCommands) {
+ $cmdList += $someCommands -like "$filter*"
+ }
+ else {
+ $cmdList += git help --all |
+ Where-Object { $_ -match '^ \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*" }
+}
+
+function script:gitBranches($filter, $includeHEAD = $false, $prefix = '') {
+ if ($filter -match "^(?\S*\.{2,3})(?.*)") {
+ $prefix += $matches['from']
+ $filter = $matches['to']
+ }
+
+ $branches = @(git branch --no-color | ForEach-Object { if (($_ -notmatch "^\* \(HEAD detached .+\)$") -and ($_ -match "^\*?\s*(?][.*)")) { $matches['ref'] } }) +
+ @(git branch --no-color -r | ForEach-Object { if ($_ -match "^ (?][\S+)(?: -> .+)?") { $matches['ref'] } }) +
+ @(if ($includeHEAD) { 'HEAD','FETCH_HEAD','ORIG_HEAD','MERGE_HEAD' })
+
+ $branches |
+ Where-Object { $_ -ne '(no branch)' -and $_ -like "$filter*" } |
+ ForEach-Object { $prefix + $_ }
+}
+
+function script:gitRemoteUniqueBranches($filter) {
+ git branch --no-color -r |
+ ForEach-Object { if ($_ -match "^ (?[^/]+)/(?\S+)(?! -> .+)?$") { $matches['branch'] } } |
+ Group-Object -NoElement |
+ Where-Object { $_.Count -eq 1 } |
+ Select-Object -ExpandProperty Name |
+ Where-Object { $_ -like "$filter*" }
+}
+
+function script:gitTags($filter, $prefix = '') {
+ git tag |
+ Where-Object { $_ -like "$filter*" } |
+ ForEach-Object { $prefix + $_ }
+}
+
+function script:gitFeatures($filter, $command){
+ $featurePrefix = git config --local --get "gitflow.prefix.$command"
+ $branches = @(git branch --no-color | ForEach-Object { if ($_ -match "^\*?\s*$featurePrefix(?][.*)") { $matches['ref'] } })
+ $branches |
+ Where-Object { $_ -ne '(no branch)' -and $_ -like "$filter*" } |
+ ForEach-Object { $prefix + $_ }
+}
+
+function script:gitRemoteBranches($remote, $ref, $filter, $prefix = '') {
+ git branch --no-color -r |
+ Where-Object { $_ -like " $remote/$filter*" } |
+ ForEach-Object { $prefix + $ref + ($_ -replace " $remote/","") }
+}
+
+function script:gitStashes($filter) {
+ (git stash list) -replace ':.*','' |
+ Where-Object { $_ -like "$filter*" } |
+ ForEach-Object { "'$_'" }
+}
+
+function script:gitTfsShelvesets($filter) {
+ (git tfs shelve-list) |
+ Where-Object { $_ -like "$filter*" } |
+ ForEach-Object { "'$_'" }
+}
+
+function script:gitFiles($filter, $files) {
+ $files | Sort-Object |
+ Where-Object { $_ -like "$filter*" } |
+ ForEach-Object { if ($_ -like '* *') { "'$_'" } else { $_ } }
+}
+
+function script:gitIndex($filter) {
+ gitFiles $filter $GitStatus.Index
+}
+
+function script:gitAddFiles($filter) {
+ gitFiles $filter (@($GitStatus.Working.Unmerged) + @($GitStatus.Working.Modified) + @($GitStatus.Working.Added))
+}
+
+function script:gitCheckoutFiles($filter) {
+ gitFiles $filter (@($GitStatus.Working.Unmerged) + @($GitStatus.Working.Modified) + @($GitStatus.Working.Deleted))
+}
+
+function script:gitDiffFiles($filter, $staged) {
+ if ($staged) {
+ gitFiles $filter $GitStatus.Index.Modified
+ }
+ else {
+ gitFiles $filter (@($GitStatus.Working.Unmerged) + @($GitStatus.Working.Modified) + @($GitStatus.Index.Modified))
+ }
+}
+
+function script:gitMergeFiles($filter) {
+ gitFiles $filter $GitStatus.Working.Unmerged
+}
+
+function script:gitDeleted($filter) {
+ gitFiles $filter $GitStatus.Working.Deleted
+}
+
+function script:gitAliases($filter) {
+ git config --get-regexp ^alias\. | ForEach-Object{
+ if ($_ -match "^alias\.(?\S+) .*") {
+ $alias = $Matches['alias']
+ if ($alias -like "$filter*") {
+ $alias
+ }
+ }
+ } | Sort-Object
+}
+
+function script:expandGitAlias($cmd, $rest) {
+ if ((git config --get-regexp "^alias\.$cmd`$") -match "^alias\.$cmd (?[^!].*)`$") {
+ return "git $($Matches['cmd'])$rest"
+ }
+ else {
+ return "git $cmd$rest"
+ }
+}
+
+function script:expandLongParams($cmd, $filter) {
+ $longGitParams[$cmd] -split ' ' |
+ Where-Object { $_ -like "$filter*" } |
+ Sort-Object |
+ ForEach-Object { -join ("--", $_) }
+}
+
+function script:expandShortParams($cmd, $filter) {
+ $shortGitParams[$cmd] -split ' ' |
+ Where-Object { $_ -like "$filter*" } |
+ Sort-Object |
+ ForEach-Object { -join ("-", $_) }
+}
+
+function script:expandParamValues($cmd, $param, $filter) {
+ $gitParamValues[$cmd][$param] -split ' ' |
+ Where-Object { $_ -like "$filter*" } |
+ Sort-Object |
+ ForEach-Object { -join ("--", $param, "=", $_) }
+}
+
+function GitTabExpansion($lastBlock) {
+ $res = Invoke-Utf8ConsoleCommand { GitTabExpansionInternal $lastBlock }
+ $res
+}
+
+function GitTabExpansionInternal($lastBlock) {
+ $ignoreGitParams = '(?\s+-(?:[aA-zZ0-9]+|-[aA-zZ0-9][aA-zZ0-9-]*)(?:=\S+)?)*'
+
+ if ($lastBlock -match "^$(Get-AliasPattern git) (?\S+)(? .*)$") {
+ $lastBlock = expandGitAlias $Matches['cmd'] $Matches['args']
+ }
+
+ # Handles tgit (tortoisegit)
+ if ($lastBlock -match "^$(Get-AliasPattern tgit) (?\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).* (?][\S*)$"){
+ return gitBranches $matches['ref'] $true
+ }
+
+ switch -regex ($lastBlock -replace "^$(Get-AliasPattern git) ","") {
+
+ # Handles git
+ "^(?$($subcommands.Keys -join '|'))\s+(?\S*)$" {
+ gitCmdOperations $subcommands $matches['cmd'] $matches['op']
+ }
+
+ # Handles git flow
+ "^flow (?$($gitflowsubcommands.Keys -join '|'))\s+(?\S*)$" {
+ gitCmdOperations $gitflowsubcommands $matches['cmd'] $matches['op']
+ }
+
+ # Handles git flow
+ "^flow (?\S*)\s+(?\S*)\s+(?\S*)$" {
+ gitFeatures $matches['name'] $matches['command']
+ }
+
+ # Handles git remote (rename|rm|set-head|set-branches|set-url|show|prune)
+ "^remote.* (?:rename|rm|set-head|set-branches|set-url|show|prune).* (?\S*)$" {
+ gitRemotes $matches['remote']
+ }
+
+ # Handles git stash (show|apply|drop|pop|branch)
+ "^stash (?:show|apply|drop|pop|branch).* (?\S*)$" {
+ gitStashes $matches['stash']
+ }
+
+ # Handles git bisect (bad|good|reset|skip) ][
+ "^bisect (?:bad|good|reset|skip).* (?][\S*)$" {
+ gitBranches $matches['ref'] $true
+ }
+
+ # Handles git tfs unshelve
+ "^tfs +unshelve.* (?\S*)$" {
+ gitTfsShelvesets $matches['shelveset']
+ }
+
+ # Handles git branch -d|-D|-m|-M
+ # Handles git branch
+ "^branch.* (?\S*)$" {
+ gitBranches $matches['branch']
+ }
+
+ # Handles git (commands & aliases)
+ "^(?\S*)$" {
+ gitCommands $matches['cmd'] $TRUE
+ }
+
+ # Handles git help (commands only)
+ "^help (?\S*)$" {
+ gitCommands $matches['cmd'] $FALSE
+ }
+
+ # Handles git push remote ][:
+ # Handles git push remote +][:
+ "^push${ignoreGitParams}\s+(?[^\s-]\S*).*\s+(?\+?)(?][[^\s\:]*\:)(?\S*)$" {
+ gitRemoteBranches $matches['remote'] $matches['ref'] $matches['branch'] -prefix $matches['force']
+ }
+
+ # Handles git push remote ][
+ # Handles git push remote +][
+ # Handles git pull remote ][
+ "^(?:push|pull)${ignoreGitParams}\s+(?[^\s-]\S*).*\s+(?\+?)(?][[^\s\:]*)$" {
+ gitBranches $matches['ref'] -prefix $matches['force']
+ gitTags $matches['ref'] -prefix $matches['force']
+ }
+
+ # Handles git pull
+ # Handles git push
+ # Handles git fetch
+ "^(?:push|pull|fetch)${ignoreGitParams}\s+(?\S*)$" {
+ gitRemotes $matches['remote']
+ }
+
+ # Handles git reset HEAD
+ # Handles git reset HEAD --
+ "^reset.* HEAD(?:\s+--)? (?\S*)$" {
+ gitIndex $matches['path']
+ }
+
+ # Handles git ][
+ "^commit.*-C\s+(?][\S*)$" {
+ gitBranches $matches['ref'] $true
+ }
+
+ # Handles git add
+ "^add.* (?\S*)$" {
+ gitAddFiles $matches['files']
+ }
+
+ # Handles git checkout --
+ "^checkout.* -- (?\S*)$" {
+ gitCheckoutFiles $matches['files']
+ }
+
+ # Handles git rm
+ "^rm.* (?\S*)$" {
+ gitDeleted $matches['index']
+ }
+
+ # Handles git diff/difftool
+ "^(?:diff|difftool)(?:.* (?(?:--cached|--staged))|.*) (?\S*)$" {
+ gitDiffFiles $matches['files'] $matches['staged']
+ }
+
+ # Handles git merge/mergetool
+ "^(?:merge|mergetool).* (?\S*)$" {
+ gitMergeFiles $matches['files']
+ }
+
+ # Handles git checkout ][
+ "^(?:checkout).* (?][\S*)$" {
+ gitBranches $matches['ref'] $true
+ gitRemoteUniqueBranches $matches['ref']
+ gitTags $matches['ref']
+ }
+
+ # Handles git worktree add ][
+ "^worktree add.* (?\S+) (?][\S*)$" {
+ gitBranches $matches['ref']
+ }
+
+ # Handles git ][
+ "^(?:cherry|cherry-pick|diff|difftool|log|merge|rebase|reflog\s+show|reset|revert|show).* (?][\S*)$" {
+ gitBranches $matches['ref'] $true
+ gitTags $matches['ref']
+ }
+
+ # Handles git --=
+ "^(?$gitCommandsWithParamValues).* --(?[^=]+)=(?\S*)$" {
+ expandParamValues $matches['cmd'] $matches['param'] $matches['value']
+ }
+
+ # Handles git --
+ "^(?$gitCommandsWithLongParams).* --(?\S*)$" {
+ expandLongParams $matches['cmd'] $matches['param']
+ }
+
+ # Handles git -
+ "^(?$gitCommandsWithShortParams).* -(?\S*)$" {
+ expandShortParams $matches['cmd'] $matches['shortparam']
+ }
+ }
+}
+
+$PowerTab_RegisterTabExpansion = if (Get-Module -Name powertab) { Get-Command Register-TabExpansion -Module powertab -ErrorAction SilentlyContinue }
+if ($PowerTab_RegisterTabExpansion) {
+ & $PowerTab_RegisterTabExpansion "git.exe" -Type Command {
+ param($Context, [ref]$TabExpansionHasOutput, [ref]$QuoteSpaces) # 1:
+
+ $line = $Context.Line
+ $lastBlock = [regex]::Split($line, '[|;]')[-1].TrimStart()
+ $TabExpansionHasOutput.Value = $true
+ GitTabExpansion $lastBlock
+ }
+ return
+}
+
+if (Test-Path Function:\TabExpansion) {
+ Rename-Item Function:\TabExpansion TabExpansionBackup
+}
+
+function TabExpansion($line, $lastWord) {
+ $lastBlock = [regex]::Split($line, '[|;]')[-1].TrimStart()
+
+ switch -regex ($lastBlock) {
+ # Execute git tab completion for all git-related commands
+ "^$(Get-AliasPattern git) (.*)" { GitTabExpansion $lastBlock }
+ "^$(Get-AliasPattern tgit) (.*)" { GitTabExpansion $lastBlock }
+ "^$(Get-AliasPattern gitk) (.*)" { GitTabExpansion $lastBlock }
+
+ # Fall back on existing tab expansion
+ default {
+ if (Test-Path Function:\TabExpansionBackup) {
+ TabExpansionBackup $line $lastWord
+ }
+ }
+ }
+}
diff --git a/src/GitUtils.ps1 b/src/GitUtils.ps1
index 36f7c2519..6848953dd 100644
--- a/src/GitUtils.ps1
+++ b/src/GitUtils.ps1
@@ -1,581 +1,581 @@
-# 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 $pathInfo -Force
- while ($currentDir) {
- $gitDirPath = Join-Path $currentDir.FullName .git
- if (Test-Path -LiteralPath $gitDirPath -PathType Container) {
- 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($gitDir = $(Get-GitDirectory), [Diagnostics.Stopwatch]$sw) {
- if (!$gitDir) { return }
-
- Invoke-Utf8ConsoleCommand {
- dbg 'Finding branch' $sw
- $r = ''; $b = ''; $c = ''
- if (Test-Path $gitDir\rebase-merge\interactive) {
- dbg 'Found rebase-merge\interactive' $sw
- $r = '|REBASE-i'
- $b = "$(Get-Content $gitDir\rebase-merge\head-name)"
- }
- elseif (Test-Path $gitDir\rebase-merge) {
- dbg 'Found rebase-merge' $sw
- $r = '|REBASE-m'
- $b = "$(Get-Content $gitDir\rebase-merge\head-name)"
- }
- else {
- if (Test-Path $gitDir\rebase-apply) {
- dbg 'Found rebase-apply' $sw
- 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 {
- dbg 'Found rebase-apply' $sw
- $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\BISECT_LOG) {
- dbg 'Found BISECT_LOG' $sw
- $r = '|BISECTING'
- }
-
- $b = Invoke-NullCoalescing `
- { dbg 'Trying symbolic-ref' $sw; git symbolic-ref HEAD -q 2>$null } `
- { '({0})' -f (Invoke-NullCoalescing `
- {
- dbg 'Trying describe' $sw
- switch ($Global:GitPromptSettings.DescribeStyle) {
- 'contains' { git describe --contains HEAD 2>$null }
- 'branch' { git describe --contains --all HEAD 2>$null }
- 'describe' { git describe HEAD 2>$null }
- default { git 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 rev-parse HEAD 2>$null
- }
-
- if ($ref -match 'ref: (?][.+)') {
- return $Matches['ref']
- }
- elseif ($ref -and $ref.Length -ge 7) {
- return $ref.Substring(0,7)+'...'
- }
- else {
- return 'unknown'
- }
- }
- ) }
- }
-
- dbg 'Inside git directory?' $sw
- if ('true' -eq $(git rev-parse --is-inside-git-dir 2>$null)) {
- dbg 'Inside git directory' $sw
- if ('true' -eq $(git rev-parse --is-bare-repository 2>$null)) {
- $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])
-
-function Get-GitStatus($gitDir = (Get-GitDirectory)) {
- $settings = $Global:GitPromptSettings
- $enabled = (-not $settings) -or $settings.EnablePromptStatus
- if ($enabled -and $gitDir) {
- if($settings.Debug) {
- $sw = [Diagnostics.Stopwatch]::StartNew(); Write-Host ''
- }
- else {
- $sw = $null
- }
-
- $branch = $null
- $aheadBy = 0
- $behindBy = 0
- $gone = $false
- $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
-
- if($settings.EnableFileStatus -and !$(InDotGitOrBareRepoDir $gitDir) -and !$(InDisabledRepository)) {
- if ($settings.EnableFileStatusFromCache -eq $null) {
- $settings.EnableFileStatusFromCache = (Get-Module GitStatusCachePoshClient) -ne $null
- }
-
- if ($settings.EnableFileStatusFromCache) {
- dbg 'Getting status from cache' $sw
- $cacheResponse = Get-GitStatusFromCache
- 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 ($cacheResponse.Stashes) { $stashCount = $cacheResponse.Stashes.Length }
- if ($cacheResponse.State) { $branch += "|" + $cacheResponse.State }
- } else {
- dbg 'Getting status' $sw
- $status = Invoke-Utf8ConsoleCommand { git -c color.status=false status --short --branch 2>$null }
- if($settings.EnableStashStatus) {
- dbg 'Getting stash count' $sw
- $stashCount = $null | git stash list 2>$null | measure-object | Select-Object -expand Count
- }
-
- dbg 'Parsing status' $sw
- switch -regex ($status) {
- '^(?[^#])(?.) (?.*?)(?: -> (?.*))?$' {
- if ($sw) { dbg "Status: $_" $sw }
-
- switch ($matches['index']) {
- 'A' { $null = $indexAdded.Add($matches['path1']); break }
- 'M' { $null = $indexModified.Add($matches['path1']); break }
- 'R' { $null = $indexModified.Add($matches['path1']); break }
- 'C' { $null = $indexModified.Add($matches['path1']); break }
- 'D' { $null = $indexDeleted.Add($matches['path1']); break }
- 'U' { $null = $indexUnmerged.Add($matches['path1']); break }
- }
- switch ($matches['working']) {
- '?' { $null = $filesAdded.Add($matches['path1']); break }
- 'A' { $null = $filesAdded.Add($matches['path1']); break }
- 'M' { $null = $filesModified.Add($matches['path1']); break }
- 'D' { $null = $filesDeleted.Add($matches['path1']); break }
- 'U' { $null = $filesUnmerged.Add($matches['path1']); break }
- }
- continue
- }
-
- '^## (?\S+?)(?:\.\.\.(?\S+))?(?: \[(?:ahead (?\d+))?(?:, )?(?:behind (?\d+))?(?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 (?\S+)$' {
- if ($sw) { dbg "Status: $_" $sw }
-
- $branch = $matches['branch']
- continue
- }
-
- default { if ($sw) { dbg "Status: $_" $sw } }
-
- }
- }
- }
-
- if(!$branch) { $branch = Get-GitBranch $gitDir $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 -PassThru NoteProperty Added $indexAdded.ToArray() |
- Add-Member -PassThru NoteProperty Modified $indexModified.ToArray() |
- Add-Member -PassThru NoteProperty Deleted $indexDeleted.ToArray() |
- Add-Member -PassThru NoteProperty Unmerged $indexUnmerged.ToArray()
-
- $working = (,$workingPaths) |
- Add-Member -PassThru NoteProperty Added $filesAdded |
- Add-Member -PassThru NoteProperty Modified $filesModified.ToArray() |
- Add-Member -PassThru NoteProperty Deleted $filesDeleted.ToArray() |
- Add-Member -PassThru NoteProperty Unmerged $filesUnmerged.ToArray()
-
- $result = New-Object PSObject -Property @{
- GitDir = $gitDir
- 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 }
- $res = $currentPath.StartsWith($GitDir, (Get-PathStringComparison))
- $res
-}
-
-function Enable-GitColors {
- Write-Warning 'Enable-GitColors is Obsolete and will be removed in a future version of posh-git.'
-}
-
-function Get-AliasPattern($exe) {
- $aliases = @($exe) + @(Get-Alias | Where-Object { $_.Definition -eq $exe } | Select-Object -Exp Name)
- "($($aliases -join '|'))"
-}
-
-function setenv($key, $value) {
- [void][Environment]::SetEnvironmentVariable($key, $value)
- Set-TempEnv $key $value
-}
-
-function Get-TempEnv($key) {
- $path = Get-TempEnvPath($key)
- if (Test-Path $path) {
- $value = Get-Content $path
- [void][Environment]::SetEnvironmentVariable($key, $value)
- }
-}
-
-function Set-TempEnv($key, $value) {
- $path = Get-TempEnvPath($key)
- if ($value -eq $null) {
- if (Test-Path $path) {
- Remove-Item $path
- }
- }
- else {
- New-Item $path -Force -ItemType File > $null
- $value | Out-File -FilePath $path -Encoding ascii -Force
- }
-}
-
-function Get-TempEnvPath($key){
- $path = Join-Path ([System.IO.Path]::GetTempPath()) ".ssh\$key.env"
- return $path
-}
-
-# Retrieve the current SSH agent PID (or zero). Can be used to determine if there
-# is a running agent.
-function Get-SshAgent() {
- if ($env:GIT_SSH -imatch 'plink') {
- $pageantPid = Get-Process | Where-Object { $_.Name -eq 'pageant' } | Select-Object -ExpandProperty Id -First 1
- if ($null -ne $pageantPid) { return $pageantPid }
- }
- else {
- $agentPid = $Env:SSH_AGENT_PID
- if ($agentPid) {
- $sshAgentProcess = Get-Process | Where-Object { ($_.Id -eq $agentPid) -and ($_.Name -eq 'ssh-agent') }
- if ($null -ne $sshAgentProcess) {
- return $agentPid
- }
- else {
- setenv 'SSH_AGENT_PID' $null
- setenv 'SSH_AUTH_SOCK' $null
- }
- }
- }
-
- return 0
-}
-
-# Attempt to guess Pageant's location
-function Find-Pageant() {
- Write-Verbose "Pageant not in path. Trying to guess location."
-
- $gitSsh = $env:GIT_SSH
- if ($gitSsh -and (test-path $gitSsh)) {
- $pageant = join-path (split-path $gitSsh) pageant
- }
-
- if (!(get-command $pageant -Erroraction SilentlyContinue)) {
- return # Guessing failed.
- }
- else {
- return $pageant
- }
-}
-
-# Attempt to guess $program's location. For ssh-agent/ssh-add.
-function Find-Ssh($program = 'ssh-agent') {
- Write-Verbose "$program not in path. Trying to guess location."
- $gitItem = Get-Command git -Erroraction SilentlyContinue | Get-Item
- if ($null -eq $gitItem) {
- Write-Warning 'git not in path'
- return
- }
-
- $sshLocation = join-path $gitItem.directory.parent.fullname bin/$program
- if (get-command $sshLocation -Erroraction SilentlyContinue) {
- return $sshLocation
- }
-
- $sshLocation = join-path $gitItem.directory.parent.fullname usr/bin/$program
- if (get-command $sshLocation -Erroraction SilentlyContinue) {
- return $sshLocation
- }
-}
-
-# Loosely based on bash script from http://help.github.com/ssh-key-passphrases/
-function Start-SshAgent([switch]$Quiet) {
- [int]$agentPid = Get-SshAgent
- if ($agentPid -gt 0) {
- if (!$Quiet) {
- $agentName = Get-Process -Id $agentPid | Select-Object -ExpandProperty Name
- if (!$agentName) { $agentName = "SSH Agent" }
- Write-Host "$agentName is already running (pid $($agentPid))"
- }
- return
- }
-
- if ($env:GIT_SSH -imatch 'plink') {
- Write-Host "GIT_SSH set to $($env:GIT_SSH), using Pageant as SSH agent."
-
- $pageant = Get-Command pageant -TotalCount 1 -Erroraction SilentlyContinue
- $pageant = if ($pageant) { $pageant } else { Find-Pageant }
- if (!$pageant) {
- Write-Warning "Could not find Pageant."
- return
- }
-
- Start-Process -NoNewWindow $pageant
- }
- else {
- $sshAgent = Get-Command ssh-agent -TotalCount 1 -ErrorAction SilentlyContinue
- $sshAgent = if ($sshAgent) { $sshAgent } else { Find-Ssh('ssh-agent') }
- if (!$sshAgent) {
- Write-Warning 'Could not find ssh-agent'
- return
- }
-
- & $sshAgent | ForEach-Object {
- if ($_ -match '(?[^=]+)=(?[^;]+);') {
- setenv $Matches['key'] $Matches['value']
- }
- }
- }
-
- Add-SshKey
-}
-
-function Get-SshPath($File = 'id_rsa') {
- # Avoid paths with path separator char since it is different on Linux/macOS.
- # Also avoid ~ as it is invalid if the user is cd'd into say cert:\ or hklm:\.
- # Also, apparently using the PowerShell built-in $HOME variable may not cut it for msysGit with has different
- # ideas about the path to the user's home dir e.g. /c/Users/Keith
- $homePath = Invoke-NullCoalescing $Env:HOME $Home
- Join-Path $homePath (Join-Path .ssh $File)
-}
-
-<#
-.SYNOPSIS
- Add a key to the SSH agent
-.DESCRIPTION
- Adds one or more SSH keys to the SSH agent.
-.EXAMPLE
- PS C:\> Add-SshKey
- Adds ~\.ssh\id_rsa to the SSH agent.
-.EXAMPLE
- PS C:\> Add-SshKey ~\.ssh\mykey, ~\.ssh\myotherkey
- Adds ~\.ssh\mykey and ~\.ssh\myotherkey to the SSH agent.
-.INPUTS
- None.
- You cannot pipe input to this cmdlet.
-#>
-function Add-SshKey() {
- if ($env:GIT_SSH -imatch 'plink') {
- $pageant = Get-Command pageant -Erroraction SilentlyContinue | Select-Object -First 1 -ExpandProperty Name
- $pageant = if ($pageant) { $pageant } else { Find-Pageant }
- if (!$pageant) {
- Write-Warning 'Could not find Pageant'
- return
- }
-
- if ($args.Count -eq 0) {
- $keyPath = Join-Path $Env:HOME .ssh
- $keys = Get-ChildItem $keyPath/*.ppk -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName
- & $pageant $keys
- }
- else {
- foreach ($value in $args) {
- & $pageant $value
- }
- }
- }
- else {
- $sshAdd = Get-Command ssh-add -TotalCount 1 -ErrorAction SilentlyContinue
- $sshAdd = if ($sshAdd) { $sshAdd } else { Find-Ssh('ssh-add') }
- if (!$sshAdd) {
- Write-Warning 'Could not find ssh-add'
- return
- }
-
- if ($args.Count -eq 0) {
- & $sshAdd
- }
- else {
- foreach ($value in $args) {
- & $sshAdd $value
- }
- }
- }
-}
-
-# Stop a running SSH agent
-function Stop-SshAgent() {
- [int]$agentPid = Get-SshAgent
- if ($agentPid -gt 0) {
- # Stop agent process
- $proc = Get-Process -Id $agentPid -ErrorAction SilentlyContinue
- if ($null -ne $proc) {
- Stop-Process $agentPid
- }
-
- setenv 'SSH_AGENT_PID' $null
- setenv 'SSH_AUTH_SOCK' $null
- }
-}
-
-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
-}
+# 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 $pathInfo -Force
+ while ($currentDir) {
+ $gitDirPath = Join-Path $currentDir.FullName .git
+ if (Test-Path -LiteralPath $gitDirPath -PathType Container) {
+ 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($gitDir = $(Get-GitDirectory), [Diagnostics.Stopwatch]$sw) {
+ if (!$gitDir) { return }
+
+ Invoke-Utf8ConsoleCommand {
+ dbg 'Finding branch' $sw
+ $r = ''; $b = ''; $c = ''
+ if (Test-Path $gitDir\rebase-merge\interactive) {
+ dbg 'Found rebase-merge\interactive' $sw
+ $r = '|REBASE-i'
+ $b = "$(Get-Content $gitDir\rebase-merge\head-name)"
+ }
+ elseif (Test-Path $gitDir\rebase-merge) {
+ dbg 'Found rebase-merge' $sw
+ $r = '|REBASE-m'
+ $b = "$(Get-Content $gitDir\rebase-merge\head-name)"
+ }
+ else {
+ if (Test-Path $gitDir\rebase-apply) {
+ dbg 'Found rebase-apply' $sw
+ 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 {
+ dbg 'Found rebase-apply' $sw
+ $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\BISECT_LOG) {
+ dbg 'Found BISECT_LOG' $sw
+ $r = '|BISECTING'
+ }
+
+ $b = Invoke-NullCoalescing `
+ { dbg 'Trying symbolic-ref' $sw; git symbolic-ref HEAD -q 2>$null } `
+ { '({0})' -f (Invoke-NullCoalescing `
+ {
+ dbg 'Trying describe' $sw
+ switch ($Global:GitPromptSettings.DescribeStyle) {
+ 'contains' { git describe --contains HEAD 2>$null }
+ 'branch' { git describe --contains --all HEAD 2>$null }
+ 'describe' { git describe HEAD 2>$null }
+ default { git 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 rev-parse HEAD 2>$null
+ }
+
+ if ($ref -match 'ref: (?][.+)') {
+ return $Matches['ref']
+ }
+ elseif ($ref -and $ref.Length -ge 7) {
+ return $ref.Substring(0,7)+'...'
+ }
+ else {
+ return 'unknown'
+ }
+ }
+ ) }
+ }
+
+ dbg 'Inside git directory?' $sw
+ if ('true' -eq $(git rev-parse --is-inside-git-dir 2>$null)) {
+ dbg 'Inside git directory' $sw
+ if ('true' -eq $(git rev-parse --is-bare-repository 2>$null)) {
+ $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])
+
+function Get-GitStatus($gitDir = (Get-GitDirectory)) {
+ $settings = $Global:GitPromptSettings
+ $enabled = (-not $settings) -or $settings.EnablePromptStatus
+ if ($enabled -and $gitDir) {
+ if($settings.Debug) {
+ $sw = [Diagnostics.Stopwatch]::StartNew(); Write-Host ''
+ }
+ else {
+ $sw = $null
+ }
+
+ $branch = $null
+ $aheadBy = 0
+ $behindBy = 0
+ $gone = $false
+ $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
+
+ if($settings.EnableFileStatus -and !$(InDotGitOrBareRepoDir $gitDir) -and !$(InDisabledRepository)) {
+ if ($settings.EnableFileStatusFromCache -eq $null) {
+ $settings.EnableFileStatusFromCache = (Get-Module GitStatusCachePoshClient) -ne $null
+ }
+
+ if ($settings.EnableFileStatusFromCache) {
+ dbg 'Getting status from cache' $sw
+ $cacheResponse = Get-GitStatusFromCache
+ 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 ($cacheResponse.Stashes) { $stashCount = $cacheResponse.Stashes.Length }
+ if ($cacheResponse.State) { $branch += "|" + $cacheResponse.State }
+ } else {
+ dbg 'Getting status' $sw
+ $status = Invoke-Utf8ConsoleCommand { git -c color.status=false status --short --branch 2>$null }
+ if($settings.EnableStashStatus) {
+ dbg 'Getting stash count' $sw
+ $stashCount = $null | git stash list 2>$null | measure-object | Select-Object -expand Count
+ }
+
+ dbg 'Parsing status' $sw
+ switch -regex ($status) {
+ '^(?[^#])(?.) (?.*?)(?: -> (?.*))?$' {
+ if ($sw) { dbg "Status: $_" $sw }
+
+ switch ($matches['index']) {
+ 'A' { $null = $indexAdded.Add($matches['path1']); break }
+ 'M' { $null = $indexModified.Add($matches['path1']); break }
+ 'R' { $null = $indexModified.Add($matches['path1']); break }
+ 'C' { $null = $indexModified.Add($matches['path1']); break }
+ 'D' { $null = $indexDeleted.Add($matches['path1']); break }
+ 'U' { $null = $indexUnmerged.Add($matches['path1']); break }
+ }
+ switch ($matches['working']) {
+ '?' { $null = $filesAdded.Add($matches['path1']); break }
+ 'A' { $null = $filesAdded.Add($matches['path1']); break }
+ 'M' { $null = $filesModified.Add($matches['path1']); break }
+ 'D' { $null = $filesDeleted.Add($matches['path1']); break }
+ 'U' { $null = $filesUnmerged.Add($matches['path1']); break }
+ }
+ continue
+ }
+
+ '^## (?\S+?)(?:\.\.\.(?\S+))?(?: \[(?:ahead (?\d+))?(?:, )?(?:behind (?\d+))?(?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 (?\S+)$' {
+ if ($sw) { dbg "Status: $_" $sw }
+
+ $branch = $matches['branch']
+ continue
+ }
+
+ default { if ($sw) { dbg "Status: $_" $sw } }
+
+ }
+ }
+ }
+
+ if(!$branch) { $branch = Get-GitBranch $gitDir $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 -PassThru NoteProperty Added $indexAdded.ToArray() |
+ Add-Member -PassThru NoteProperty Modified $indexModified.ToArray() |
+ Add-Member -PassThru NoteProperty Deleted $indexDeleted.ToArray() |
+ Add-Member -PassThru NoteProperty Unmerged $indexUnmerged.ToArray()
+
+ $working = (,$workingPaths) |
+ Add-Member -PassThru NoteProperty Added $filesAdded |
+ Add-Member -PassThru NoteProperty Modified $filesModified.ToArray() |
+ Add-Member -PassThru NoteProperty Deleted $filesDeleted.ToArray() |
+ Add-Member -PassThru NoteProperty Unmerged $filesUnmerged.ToArray()
+
+ $result = New-Object PSObject -Property @{
+ GitDir = $gitDir
+ 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 }
+ $res = $currentPath.StartsWith($GitDir, (Get-PathStringComparison))
+ $res
+}
+
+function Enable-GitColors {
+ Write-Warning 'Enable-GitColors is Obsolete and will be removed in a future version of posh-git.'
+}
+
+function Get-AliasPattern($exe) {
+ $aliases = @($exe) + @(Get-Alias | Where-Object { $_.Definition -eq $exe } | Select-Object -Exp Name)
+ "($($aliases -join '|'))"
+}
+
+function setenv($key, $value) {
+ [void][Environment]::SetEnvironmentVariable($key, $value)
+ Set-TempEnv $key $value
+}
+
+function Get-TempEnv($key) {
+ $path = Get-TempEnvPath($key)
+ if (Test-Path $path) {
+ $value = Get-Content $path
+ [void][Environment]::SetEnvironmentVariable($key, $value)
+ }
+}
+
+function Set-TempEnv($key, $value) {
+ $path = Get-TempEnvPath($key)
+ if ($value -eq $null) {
+ if (Test-Path $path) {
+ Remove-Item $path
+ }
+ }
+ else {
+ New-Item $path -Force -ItemType File > $null
+ $value | Out-File -FilePath $path -Encoding ascii -Force
+ }
+}
+
+function Get-TempEnvPath($key){
+ $path = Join-Path ([System.IO.Path]::GetTempPath()) ".ssh\$key.env"
+ return $path
+}
+
+# Retrieve the current SSH agent PID (or zero). Can be used to determine if there
+# is a running agent.
+function Get-SshAgent() {
+ if ($env:GIT_SSH -imatch 'plink') {
+ $pageantPid = Get-Process | Where-Object { $_.Name -eq 'pageant' } | Select-Object -ExpandProperty Id -First 1
+ if ($null -ne $pageantPid) { return $pageantPid }
+ }
+ else {
+ $agentPid = $Env:SSH_AGENT_PID
+ if ($agentPid) {
+ $sshAgentProcess = Get-Process | Where-Object { ($_.Id -eq $agentPid) -and ($_.Name -eq 'ssh-agent') }
+ if ($null -ne $sshAgentProcess) {
+ return $agentPid
+ }
+ else {
+ setenv 'SSH_AGENT_PID' $null
+ setenv 'SSH_AUTH_SOCK' $null
+ }
+ }
+ }
+
+ return 0
+}
+
+# Attempt to guess Pageant's location
+function Find-Pageant() {
+ Write-Verbose "Pageant not in path. Trying to guess location."
+
+ $gitSsh = $env:GIT_SSH
+ if ($gitSsh -and (test-path $gitSsh)) {
+ $pageant = join-path (split-path $gitSsh) pageant
+ }
+
+ if (!(get-command $pageant -Erroraction SilentlyContinue)) {
+ return # Guessing failed.
+ }
+ else {
+ return $pageant
+ }
+}
+
+# Attempt to guess $program's location. For ssh-agent/ssh-add.
+function Find-Ssh($program = 'ssh-agent') {
+ Write-Verbose "$program not in path. Trying to guess location."
+ $gitItem = Get-Command git -Erroraction SilentlyContinue | Get-Item
+ if ($null -eq $gitItem) {
+ Write-Warning 'git not in path'
+ return
+ }
+
+ $sshLocation = join-path $gitItem.directory.parent.fullname bin/$program
+ if (get-command $sshLocation -Erroraction SilentlyContinue) {
+ return $sshLocation
+ }
+
+ $sshLocation = join-path $gitItem.directory.parent.fullname usr/bin/$program
+ if (get-command $sshLocation -Erroraction SilentlyContinue) {
+ return $sshLocation
+ }
+}
+
+# Loosely based on bash script from http://help.github.com/ssh-key-passphrases/
+function Start-SshAgent([switch]$Quiet) {
+ [int]$agentPid = Get-SshAgent
+ if ($agentPid -gt 0) {
+ if (!$Quiet) {
+ $agentName = Get-Process -Id $agentPid | Select-Object -ExpandProperty Name
+ if (!$agentName) { $agentName = "SSH Agent" }
+ Write-Host "$agentName is already running (pid $($agentPid))"
+ }
+ return
+ }
+
+ if ($env:GIT_SSH -imatch 'plink') {
+ Write-Host "GIT_SSH set to $($env:GIT_SSH), using Pageant as SSH agent."
+
+ $pageant = Get-Command pageant -TotalCount 1 -Erroraction SilentlyContinue
+ $pageant = if ($pageant) { $pageant } else { Find-Pageant }
+ if (!$pageant) {
+ Write-Warning "Could not find Pageant."
+ return
+ }
+
+ Start-Process -NoNewWindow $pageant
+ }
+ else {
+ $sshAgent = Get-Command ssh-agent -TotalCount 1 -ErrorAction SilentlyContinue
+ $sshAgent = if ($sshAgent) { $sshAgent } else { Find-Ssh('ssh-agent') }
+ if (!$sshAgent) {
+ Write-Warning 'Could not find ssh-agent'
+ return
+ }
+
+ & $sshAgent | ForEach-Object {
+ if ($_ -match '(?[^=]+)=(?[^;]+);') {
+ setenv $Matches['key'] $Matches['value']
+ }
+ }
+ }
+
+ Add-SshKey
+}
+
+function Get-SshPath($File = 'id_rsa') {
+ # Avoid paths with path separator char since it is different on Linux/macOS.
+ # Also avoid ~ as it is invalid if the user is cd'd into say cert:\ or hklm:\.
+ # Also, apparently using the PowerShell built-in $HOME variable may not cut it for msysGit with has different
+ # ideas about the path to the user's home dir e.g. /c/Users/Keith
+ $homePath = Invoke-NullCoalescing $Env:HOME $Home
+ Join-Path $homePath (Join-Path .ssh $File)
+}
+
+<#
+.SYNOPSIS
+ Add a key to the SSH agent
+.DESCRIPTION
+ Adds one or more SSH keys to the SSH agent.
+.EXAMPLE
+ PS C:\> Add-SshKey
+ Adds ~\.ssh\id_rsa to the SSH agent.
+.EXAMPLE
+ PS C:\> Add-SshKey ~\.ssh\mykey, ~\.ssh\myotherkey
+ Adds ~\.ssh\mykey and ~\.ssh\myotherkey to the SSH agent.
+.INPUTS
+ None.
+ You cannot pipe input to this cmdlet.
+#>
+function Add-SshKey() {
+ if ($env:GIT_SSH -imatch 'plink') {
+ $pageant = Get-Command pageant -Erroraction SilentlyContinue | Select-Object -First 1 -ExpandProperty Name
+ $pageant = if ($pageant) { $pageant } else { Find-Pageant }
+ if (!$pageant) {
+ Write-Warning 'Could not find Pageant'
+ return
+ }
+
+ if ($args.Count -eq 0) {
+ $keyPath = Join-Path $Env:HOME .ssh
+ $keys = Get-ChildItem $keyPath/*.ppk -ErrorAction SilentlyContinue | Select-Object -ExpandProperty FullName
+ & $pageant $keys
+ }
+ else {
+ foreach ($value in $args) {
+ & $pageant $value
+ }
+ }
+ }
+ else {
+ $sshAdd = Get-Command ssh-add -TotalCount 1 -ErrorAction SilentlyContinue
+ $sshAdd = if ($sshAdd) { $sshAdd } else { Find-Ssh('ssh-add') }
+ if (!$sshAdd) {
+ Write-Warning 'Could not find ssh-add'
+ return
+ }
+
+ if ($args.Count -eq 0) {
+ & $sshAdd
+ }
+ else {
+ foreach ($value in $args) {
+ & $sshAdd $value
+ }
+ }
+ }
+}
+
+# Stop a running SSH agent
+function Stop-SshAgent() {
+ [int]$agentPid = Get-SshAgent
+ if ($agentPid -gt 0) {
+ # Stop agent process
+ $proc = Get-Process -Id $agentPid -ErrorAction SilentlyContinue
+ if ($null -ne $proc) {
+ Stop-Process $agentPid
+ }
+
+ setenv 'SSH_AGENT_PID' $null
+ setenv 'SSH_AUTH_SOCK' $null
+ }
+}
+
+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
+}
diff --git a/src/TortoiseGit.ps1 b/src/TortoiseGit.ps1
index 961e9ba35..27d03c00a 100644
--- a/src/TortoiseGit.ps1
+++ b/src/TortoiseGit.ps1
@@ -1,85 +1,85 @@
-# TortoiseGit
-
-function private:Get-TortoiseGitPath {
- if ((Test-Path "C:\Program Files\TortoiseGit\bin\TortoiseGitProc.exe") -eq $true) {
- # TortoiseGit 1.8.0 renamed TortoiseProc to TortoiseGitProc.
- return "C:\Program Files\TortoiseGit\bin\TortoiseGitProc.exe"
- }
-
- return "C:\Program Files\TortoiseGit\bin\TortoiseProc.exe"
-}
-
-$Global:TortoiseGitSettings = new-object PSObject -Property @{
- TortoiseGitPath = (Get-TortoiseGitPath)
- TortoiseGitCommands = @{
- "about" = "about";
- "add" = "add";
- "blame" = "blame";
- "cat" = "cat";
- "cleanup" = "cleanup";
- "clean" = "cleanup";
- "commit" = "commit";
- "conflicteditor" = "conflicteditor";
- "createpatch" = "createpatch";
- "patch" = "createpatch";
- "diff" = "diff";
- "export" = "export";
- "help" = "help";
- "ignore" = "ignore";
- "log" = "log";
- "merge" = "merge";
- "pull" = "pull";
- "push" = "push";
- "rebase" = "rebase";
- "refbrowse" = "refbrowse";
- "reflog" = "reflog";
- "remove" = "remove";
- "rm" = "remove";
- "rename" = "rename";
- "mv" = "rename";
- "repocreate" = "repocreate";
- "init" = "repocreate";
- "repostatus" = "repostatus";
- "status" = "repostatus";
- "resolve" = "resolve";
- "revert" = "revert";
- "settings" = "settings";
- "config" = "settings";
- "stash" = "stash";
- "stashapply" = "stashapply";
- "stashsave" = "stashsave";
- "subadd" = "subadd";
- "subsync" = "subsync";
- "subupdate" = "subupdate";
- "switch" = "switch";
- "checkout" = "switch";
- "fetch" = "sync";
- "sync" = "sync";
- }
-}
-
-function tgit {
- if($args) {
- # Replace any aliases with actual TortoiseGit commands
- if ($Global:TortoiseGitSettings.TortoiseGitCommands.ContainsKey($args[0])) {
- $args[0] = $Global:TortoiseGitSettings.TortoiseGitCommands.Get_Item($args[0])
- }
-
- if($args[0] -eq "help") {
- # Replace the built-in help behaviour with just a list of commands
- $Global:TortoiseGitSettings.TortoiseGitCommands.Values.GetEnumerator() | Sort-Object | Get-Unique
- return
- }
-
- $newArgs = @()
- $newArgs += "/command:" + $args[0]
-
- $cmd = $args[0]
-
- if($args.length -gt 1) {
- $args[1..$args.length] | ForEach-Object { $newArgs += $_ }
- }
-
- & $Global:TortoiseGitSettings.TortoiseGitPath $newArgs
- }
-}
+# TortoiseGit
+
+function private:Get-TortoiseGitPath {
+ if ((Test-Path "C:\Program Files\TortoiseGit\bin\TortoiseGitProc.exe") -eq $true) {
+ # TortoiseGit 1.8.0 renamed TortoiseProc to TortoiseGitProc.
+ return "C:\Program Files\TortoiseGit\bin\TortoiseGitProc.exe"
+ }
+
+ return "C:\Program Files\TortoiseGit\bin\TortoiseProc.exe"
+}
+
+$Global:TortoiseGitSettings = new-object PSObject -Property @{
+ TortoiseGitPath = (Get-TortoiseGitPath)
+ TortoiseGitCommands = @{
+ "about" = "about";
+ "add" = "add";
+ "blame" = "blame";
+ "cat" = "cat";
+ "cleanup" = "cleanup";
+ "clean" = "cleanup";
+ "commit" = "commit";
+ "conflicteditor" = "conflicteditor";
+ "createpatch" = "createpatch";
+ "patch" = "createpatch";
+ "diff" = "diff";
+ "export" = "export";
+ "help" = "help";
+ "ignore" = "ignore";
+ "log" = "log";
+ "merge" = "merge";
+ "pull" = "pull";
+ "push" = "push";
+ "rebase" = "rebase";
+ "refbrowse" = "refbrowse";
+ "reflog" = "reflog";
+ "remove" = "remove";
+ "rm" = "remove";
+ "rename" = "rename";
+ "mv" = "rename";
+ "repocreate" = "repocreate";
+ "init" = "repocreate";
+ "repostatus" = "repostatus";
+ "status" = "repostatus";
+ "resolve" = "resolve";
+ "revert" = "revert";
+ "settings" = "settings";
+ "config" = "settings";
+ "stash" = "stash";
+ "stashapply" = "stashapply";
+ "stashsave" = "stashsave";
+ "subadd" = "subadd";
+ "subsync" = "subsync";
+ "subupdate" = "subupdate";
+ "switch" = "switch";
+ "checkout" = "switch";
+ "fetch" = "sync";
+ "sync" = "sync";
+ }
+}
+
+function tgit {
+ if($args) {
+ # Replace any aliases with actual TortoiseGit commands
+ if ($Global:TortoiseGitSettings.TortoiseGitCommands.ContainsKey($args[0])) {
+ $args[0] = $Global:TortoiseGitSettings.TortoiseGitCommands.Get_Item($args[0])
+ }
+
+ if($args[0] -eq "help") {
+ # Replace the built-in help behaviour with just a list of commands
+ $Global:TortoiseGitSettings.TortoiseGitCommands.Values.GetEnumerator() | Sort-Object | Get-Unique
+ return
+ }
+
+ $newArgs = @()
+ $newArgs += "/command:" + $args[0]
+
+ $cmd = $args[0]
+
+ if($args.length -gt 1) {
+ $args[1..$args.length] | ForEach-Object { $newArgs += $_ }
+ }
+
+ & $Global:TortoiseGitSettings.TortoiseGitPath $newArgs
+ }
+}
diff --git a/src/Utils.ps1 b/src/Utils.ps1
index 0db595a54..3a9aa4c09 100644
--- a/src/Utils.ps1
+++ b/src/Utils.ps1
@@ -1,255 +1,255 @@
-# Need this variable as long as we support PS v2
-$ModuleBasePath = Split-Path $MyInvocation.MyCommand.Path -Parent
-
-# Store error records generated by stderr output when invoking an executable
-# This can be accessed from the user's session by executing:
-# PS> $m = Get-Module posh-git
-# PS> & $m Get-Variable invokeErrors -ValueOnly
-$invokeErrors = New-Object System.Collections.ArrayList 256
-
-# General Utility Functions
-
-function Invoke-NullCoalescing {
- $result = $null
- foreach($arg in $args) {
- if ($arg -is [ScriptBlock]) {
- $result = & $arg
- }
- else {
- $result = $arg
- }
- if ($result) { break }
- }
- $result
-}
-
-Set-Alias ?? Invoke-NullCoalescing -Force
-
-function Invoke-Utf8ConsoleCommand([ScriptBlock]$cmd) {
- $currentEncoding = [Console]::OutputEncoding
- $errorCount = $global:Error.Count
- try {
- # A native executable that writes to stderr AND has its stderr redirected will generate non-terminating
- # error records if the user has set $ErrorActionPreference to Stop. Override that value in this scope.
- $ErrorActionPreference = 'Continue'
- if ($currentEncoding.IsSingleByte) {
- [Console]::OutputEncoding = [Text.Encoding]::UTF8
- }
- & $cmd
- }
- finally {
- if ($currentEncoding.IsSingleByte) {
- [Console]::OutputEncoding = $currentEncoding
- }
-
- # Clear out stderr output that was added to the $Error collection, putting those errors in a module variable
- if ($global:Error.Count -gt $errorCount) {
- $numNewErrors = $global:Error.Count - $errorCount
- $invokeErrors.InsertRange(0, $global:Error.GetRange(0, $numNewErrors))
- if ($invokeErrors.Count -gt 256) {
- $invokeErrors.RemoveRange(256, ($invokeErrors.Count - 256))
- }
- $global:Error.RemoveRange(0, $numNewErrors)
- }
- }
-}
-
-<#
-.SYNOPSIS
- Configures your PowerShell profile (startup) script to import the posh-git
- module when PowerShell starts.
-.DESCRIPTION
- Checks if your PowerShell profile script is not already importing posh-git
- and if not, adds a command to import the posh-git module. This will cause
- PowerShell to load posh-git whenever PowerShell starts.
-.PARAMETER AllHosts
- By default, this command modifies the CurrentUserCurrentHost profile
- script. By specifying the AllHosts switch, the command updates the
- CurrentUserAllHosts profile.
-.PARAMETER Force
- Do not check if the specified profile script is already importing
- posh-git. Just add Import-Module posh-git command.
-.EXAMPLE
- PS C:\> Add-PoshGitToProfile
- Updates your profile script for the current PowerShell host to import the
- posh-git module when the current PowerShell host starts.
-.EXAMPLE
- PS C:\> Add-PoshGitToProfile -AllHost
- Updates your profile script for all PowerShell hosts to import the posh-git
- module whenever any PowerShell host starts.
-.INPUTS
- None.
-.OUTPUTS
- None.
-#>
-function Add-PoshGitToProfile([switch]$AllHosts, [switch]$Force, [switch]$WhatIf) {
- $underTest = $false
-
- $profilePath = if ($AllHosts) { $PROFILE.CurrentUserAllHosts } else { $PROFILE.CurrentUserCurrentHost }
-
- # Under test, we override some variables using $args as a backdoor.
- # TODO: Can we just turn these into optional parameters with well-defined behavior?
- if (($args.Count -gt 0) -and ($args[0] -is [string])) {
- $profilePath = [string]$args[0]
- $underTest = $true
- if ($args.Count -gt 1) {
- $ModuleBasePath = [string]$args[1]
- }
- }
-
- if (!$profilePath) { $profilePath = $PROFILE }
-
- if (!$Force) {
- # Search the user's profiles to see if any are using posh-git already, there is an extra search
- # ($profilePath) taking place to accomodate the Pester tests.
- $importedInProfile = Test-PoshGitImportedInScript $profilePath
- if (!$importedInProfile -and !$underTest) {
- $importedInProfile = Test-PoshGitImportedInScript $PROFILE
- }
- if (!$importedInProfile -and !$underTest) {
- $importedInProfile = Test-PoshGitImportedInScript $PROFILE.CurrentUserCurrentHost
- }
- if (!$importedInProfile -and !$underTest) {
- $importedInProfile = Test-PoshGitImportedInScript $PROFILE.CurrentUserAllHosts
- }
- if (!$importedInProfile -and !$underTest) {
- $importedInProfile = Test-PoshGitImportedInScript $PROFILE.AllUsersCurrentHost
- }
- if (!$importedInProfile -and !$underTest) {
- $importedInProfile = Test-PoshGitImportedInScript $PROFILE.AllUsersAllHosts
- }
-
- if ($importedInProfile) {
- Write-Warning "Skipping add of posh-git import to file '$profilePath'."
- Write-Warning "posh-git appears to already be imported in one of your profile scripts."
- Write-Warning "If you want to force the add, use the -Force parameter."
- return
- }
- }
-
- if (!$profilePath) {
- Write-Warning "Skipping add of posh-git import; no profile found."
- Write-Verbose "`$profilePath = '$profilePath'"
- Write-Verbose "`$PROFILE = '$PROFILE'"
- Write-Verbose "CurrentUserCurrentHost = '$($PROFILE.CurrentUserCurrentHost)'"
- Write-Verbose "CurrentUserAllHosts = '$($PROFILE.CurrentUserAllHosts)'"
- Write-Verbose "AllUsersCurrentHost = '$($PROFILE.AllUsersCurrentHost)'"
- Write-Verbose "AllUsersAllHosts = '$($PROFILE.AllUsersAllHosts)'"
- return
- }
-
- # Check if the location of this module file is in the PSModulePath
- if (Test-InPSModulePath $ModuleBasePath) {
- $profileContent = "`nImport-Module posh-git"
- }
- else {
- $profileContent = "`nImport-Module '$ModuleBasePath\posh-git.psd1'"
- }
-
- Add-Content -LiteralPath $profilePath -Value $profileContent -Encoding UTF8 -WhatIf:$WhatIf
-}
-
-<#
-.SYNOPSIS
- Gets the file encoding of the specified file.
-.DESCRIPTION
- Gets the file encoding of the specified file.
-.PARAMETER Path
- Path to the file to check. The file must exist.
-.EXAMPLE
- PS C:\> Get-FileEncoding $profile
- Get's the file encoding of the profile file.
-.INPUTS
- None.
-.OUTPUTS
- [System.String]
-.NOTES
- Adapted from http://www.west-wind.com/Weblog/posts/197245.aspx
-#>
-function Get-FileEncoding($Path) {
- $bytes = [byte[]](Get-Content $Path -Encoding byte -ReadCount 4 -TotalCount 4)
-
- if (!$bytes) { return 'utf8' }
-
- switch -regex ('{0:x2}{1:x2}{2:x2}{3:x2}' -f $bytes[0],$bytes[1],$bytes[2],$bytes[3]) {
- '^efbbbf' { return 'utf8' }
- '^2b2f76' { return 'utf7' }
- '^fffe' { return 'unicode' }
- '^feff' { return 'bigendianunicode' }
- '^0000feff' { return 'utf32' }
- default { return 'ascii' }
- }
-}
-
-<#
-.SYNOPSIS
- Gets a StringComparison enum value appropriate for comparing paths on the OS platform.
-.DESCRIPTION
- Gets a StringComparison enum value appropriate for comparing paths on the OS platform.
-.EXAMPLE
- PS C:\> $pathStringComparison = Get-PathStringComparison
-.INPUTS
- None
-.OUTPUTS
- [System.StringComparison]
-#>
-function Get-PathStringComparison {
- # File system paths are case-sensitive on Linux and case-insensitive on Windows and macOS
- if (($PSVersionTable.PSVersion.Major -ge 6) -and $IsLinux) {
- [System.StringComparison]::Ordinal
- }
- else {
- [System.StringComparison]::OrdinalIgnoreCase
- }
-}
-
-function Get-PSModulePath {
- $modulePaths = $Env:PSModulePath -split ';'
- $modulePaths
-}
-
-function Test-InPSModulePath {
- param (
- [Parameter(Position=0, Mandatory=$true)]
- [ValidateNotNull()]
- [string]
- $Path
- )
-
- $modulePaths = Get-PSModulePath
- if (!$modulePaths) { return $false }
-
- $pathStringComparison = Get-PathStringComparison
- $Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path)
- $inModulePath = @($modulePaths | Where-Object { $Path.StartsWith($_.TrimEnd([System.IO.Path]::DirectorySeparatorChar), $pathStringComparison) }).Count -gt 0
-
- if ($inModulePath -and ('src' -eq (Split-Path $Path -Leaf))) {
- Write-Warning 'posh-git repository structure is incompatible with %PSModulePath%.'
- Write-Warning 'Importing with absolute path instead.'
- return $false
- }
-
- $inModulePath
-}
-
-function Test-PoshGitImportedInScript {
- param (
- [Parameter(Position=0)]
- [string]
- $Path
- )
-
- if (!$Path -or !(Test-Path -LiteralPath $Path)) {
- return $false
- }
-
- $match = (@(Get-Content $Path -ErrorAction SilentlyContinue) -match 'posh-git').Count -gt 0
- if ($match) { Write-Verbose "posh-git found in '$Path'" }
- $match
-}
-
-function dbg($Message, [Diagnostics.Stopwatch]$Stopwatch) {
- if ($Stopwatch) {
- Write-Verbose ('{0:00000}:{1}' -f $Stopwatch.ElapsedMilliseconds,$Message) -Verbose # -ForegroundColor Yellow
- }
-}
+# Need this variable as long as we support PS v2
+$ModuleBasePath = Split-Path $MyInvocation.MyCommand.Path -Parent
+
+# Store error records generated by stderr output when invoking an executable
+# This can be accessed from the user's session by executing:
+# PS> $m = Get-Module posh-git
+# PS> & $m Get-Variable invokeErrors -ValueOnly
+$invokeErrors = New-Object System.Collections.ArrayList 256
+
+# General Utility Functions
+
+function Invoke-NullCoalescing {
+ $result = $null
+ foreach($arg in $args) {
+ if ($arg -is [ScriptBlock]) {
+ $result = & $arg
+ }
+ else {
+ $result = $arg
+ }
+ if ($result) { break }
+ }
+ $result
+}
+
+Set-Alias ?? Invoke-NullCoalescing -Force
+
+function Invoke-Utf8ConsoleCommand([ScriptBlock]$cmd) {
+ $currentEncoding = [Console]::OutputEncoding
+ $errorCount = $global:Error.Count
+ try {
+ # A native executable that writes to stderr AND has its stderr redirected will generate non-terminating
+ # error records if the user has set $ErrorActionPreference to Stop. Override that value in this scope.
+ $ErrorActionPreference = 'Continue'
+ if ($currentEncoding.IsSingleByte) {
+ [Console]::OutputEncoding = [Text.Encoding]::UTF8
+ }
+ & $cmd
+ }
+ finally {
+ if ($currentEncoding.IsSingleByte) {
+ [Console]::OutputEncoding = $currentEncoding
+ }
+
+ # Clear out stderr output that was added to the $Error collection, putting those errors in a module variable
+ if ($global:Error.Count -gt $errorCount) {
+ $numNewErrors = $global:Error.Count - $errorCount
+ $invokeErrors.InsertRange(0, $global:Error.GetRange(0, $numNewErrors))
+ if ($invokeErrors.Count -gt 256) {
+ $invokeErrors.RemoveRange(256, ($invokeErrors.Count - 256))
+ }
+ $global:Error.RemoveRange(0, $numNewErrors)
+ }
+ }
+}
+
+<#
+.SYNOPSIS
+ Configures your PowerShell profile (startup) script to import the posh-git
+ module when PowerShell starts.
+.DESCRIPTION
+ Checks if your PowerShell profile script is not already importing posh-git
+ and if not, adds a command to import the posh-git module. This will cause
+ PowerShell to load posh-git whenever PowerShell starts.
+.PARAMETER AllHosts
+ By default, this command modifies the CurrentUserCurrentHost profile
+ script. By specifying the AllHosts switch, the command updates the
+ CurrentUserAllHosts profile.
+.PARAMETER Force
+ Do not check if the specified profile script is already importing
+ posh-git. Just add Import-Module posh-git command.
+.EXAMPLE
+ PS C:\> Add-PoshGitToProfile
+ Updates your profile script for the current PowerShell host to import the
+ posh-git module when the current PowerShell host starts.
+.EXAMPLE
+ PS C:\> Add-PoshGitToProfile -AllHost
+ Updates your profile script for all PowerShell hosts to import the posh-git
+ module whenever any PowerShell host starts.
+.INPUTS
+ None.
+.OUTPUTS
+ None.
+#>
+function Add-PoshGitToProfile([switch]$AllHosts, [switch]$Force, [switch]$WhatIf) {
+ $underTest = $false
+
+ $profilePath = if ($AllHosts) { $PROFILE.CurrentUserAllHosts } else { $PROFILE.CurrentUserCurrentHost }
+
+ # Under test, we override some variables using $args as a backdoor.
+ # TODO: Can we just turn these into optional parameters with well-defined behavior?
+ if (($args.Count -gt 0) -and ($args[0] -is [string])) {
+ $profilePath = [string]$args[0]
+ $underTest = $true
+ if ($args.Count -gt 1) {
+ $ModuleBasePath = [string]$args[1]
+ }
+ }
+
+ if (!$profilePath) { $profilePath = $PROFILE }
+
+ if (!$Force) {
+ # Search the user's profiles to see if any are using posh-git already, there is an extra search
+ # ($profilePath) taking place to accomodate the Pester tests.
+ $importedInProfile = Test-PoshGitImportedInScript $profilePath
+ if (!$importedInProfile -and !$underTest) {
+ $importedInProfile = Test-PoshGitImportedInScript $PROFILE
+ }
+ if (!$importedInProfile -and !$underTest) {
+ $importedInProfile = Test-PoshGitImportedInScript $PROFILE.CurrentUserCurrentHost
+ }
+ if (!$importedInProfile -and !$underTest) {
+ $importedInProfile = Test-PoshGitImportedInScript $PROFILE.CurrentUserAllHosts
+ }
+ if (!$importedInProfile -and !$underTest) {
+ $importedInProfile = Test-PoshGitImportedInScript $PROFILE.AllUsersCurrentHost
+ }
+ if (!$importedInProfile -and !$underTest) {
+ $importedInProfile = Test-PoshGitImportedInScript $PROFILE.AllUsersAllHosts
+ }
+
+ if ($importedInProfile) {
+ Write-Warning "Skipping add of posh-git import to file '$profilePath'."
+ Write-Warning "posh-git appears to already be imported in one of your profile scripts."
+ Write-Warning "If you want to force the add, use the -Force parameter."
+ return
+ }
+ }
+
+ if (!$profilePath) {
+ Write-Warning "Skipping add of posh-git import; no profile found."
+ Write-Verbose "`$profilePath = '$profilePath'"
+ Write-Verbose "`$PROFILE = '$PROFILE'"
+ Write-Verbose "CurrentUserCurrentHost = '$($PROFILE.CurrentUserCurrentHost)'"
+ Write-Verbose "CurrentUserAllHosts = '$($PROFILE.CurrentUserAllHosts)'"
+ Write-Verbose "AllUsersCurrentHost = '$($PROFILE.AllUsersCurrentHost)'"
+ Write-Verbose "AllUsersAllHosts = '$($PROFILE.AllUsersAllHosts)'"
+ return
+ }
+
+ # Check if the location of this module file is in the PSModulePath
+ if (Test-InPSModulePath $ModuleBasePath) {
+ $profileContent = "`nImport-Module posh-git"
+ }
+ else {
+ $profileContent = "`nImport-Module '$ModuleBasePath\posh-git.psd1'"
+ }
+
+ Add-Content -LiteralPath $profilePath -Value $profileContent -Encoding UTF8 -WhatIf:$WhatIf
+}
+
+<#
+.SYNOPSIS
+ Gets the file encoding of the specified file.
+.DESCRIPTION
+ Gets the file encoding of the specified file.
+.PARAMETER Path
+ Path to the file to check. The file must exist.
+.EXAMPLE
+ PS C:\> Get-FileEncoding $profile
+ Get's the file encoding of the profile file.
+.INPUTS
+ None.
+.OUTPUTS
+ [System.String]
+.NOTES
+ Adapted from http://www.west-wind.com/Weblog/posts/197245.aspx
+#>
+function Get-FileEncoding($Path) {
+ $bytes = [byte[]](Get-Content $Path -Encoding byte -ReadCount 4 -TotalCount 4)
+
+ if (!$bytes) { return 'utf8' }
+
+ switch -regex ('{0:x2}{1:x2}{2:x2}{3:x2}' -f $bytes[0],$bytes[1],$bytes[2],$bytes[3]) {
+ '^efbbbf' { return 'utf8' }
+ '^2b2f76' { return 'utf7' }
+ '^fffe' { return 'unicode' }
+ '^feff' { return 'bigendianunicode' }
+ '^0000feff' { return 'utf32' }
+ default { return 'ascii' }
+ }
+}
+
+<#
+.SYNOPSIS
+ Gets a StringComparison enum value appropriate for comparing paths on the OS platform.
+.DESCRIPTION
+ Gets a StringComparison enum value appropriate for comparing paths on the OS platform.
+.EXAMPLE
+ PS C:\> $pathStringComparison = Get-PathStringComparison
+.INPUTS
+ None
+.OUTPUTS
+ [System.StringComparison]
+#>
+function Get-PathStringComparison {
+ # File system paths are case-sensitive on Linux and case-insensitive on Windows and macOS
+ if (($PSVersionTable.PSVersion.Major -ge 6) -and $IsLinux) {
+ [System.StringComparison]::Ordinal
+ }
+ else {
+ [System.StringComparison]::OrdinalIgnoreCase
+ }
+}
+
+function Get-PSModulePath {
+ $modulePaths = $Env:PSModulePath -split ';'
+ $modulePaths
+}
+
+function Test-InPSModulePath {
+ param (
+ [Parameter(Position=0, Mandatory=$true)]
+ [ValidateNotNull()]
+ [string]
+ $Path
+ )
+
+ $modulePaths = Get-PSModulePath
+ if (!$modulePaths) { return $false }
+
+ $pathStringComparison = Get-PathStringComparison
+ $Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path)
+ $inModulePath = @($modulePaths | Where-Object { $Path.StartsWith($_.TrimEnd([System.IO.Path]::DirectorySeparatorChar), $pathStringComparison) }).Count -gt 0
+
+ if ($inModulePath -and ('src' -eq (Split-Path $Path -Leaf))) {
+ Write-Warning 'posh-git repository structure is incompatible with %PSModulePath%.'
+ Write-Warning 'Importing with absolute path instead.'
+ return $false
+ }
+
+ $inModulePath
+}
+
+function Test-PoshGitImportedInScript {
+ param (
+ [Parameter(Position=0)]
+ [string]
+ $Path
+ )
+
+ if (!$Path -or !(Test-Path -LiteralPath $Path)) {
+ return $false
+ }
+
+ $match = (@(Get-Content $Path -ErrorAction SilentlyContinue) -match 'posh-git').Count -gt 0
+ if ($match) { Write-Verbose "posh-git found in '$Path'" }
+ $match
+}
+
+function dbg($Message, [Diagnostics.Stopwatch]$Stopwatch) {
+ if ($Stopwatch) {
+ Write-Verbose ('{0:00000}:{1}' -f $Stopwatch.ElapsedMilliseconds,$Message) -Verbose # -ForegroundColor Yellow
+ }
+}
diff --git a/src/en-US/about_posh-git.help.txt b/src/en-US/about_posh-git.help.txt
index 7303418c9..b5dbcf95c 100644
--- a/src/en-US/about_posh-git.help.txt
+++ b/src/en-US/about_posh-git.help.txt
@@ -1,178 +1,178 @@
-TOPIC
- posh-git
-
-SHORT DESCRIPTION
- posh-git integrates Git and PowerShell providing tab completion of Git
- commands, branch names, paths and more. It also provides Git status
- summary information that can be displayed in the PowerShell prompt.
-
-LONG DESCRIPTION
- posh-git integrates Git and PowerShell. Tab completion is supported for
- Git subcommands, branch and remote names. Git also provides commands to
- display colored Git status summary information. If you would like fine
- grained control over how the Git status summary information is displayed
- in your prompt function, you can get the raw status summary information
- via the Get-GitStatus command. Then you can display the information in
- your prompt however you would like.
-
- posh-git will install a prompt function if it detects the user does not
- have their own, customized prompt. This prompt displays Git status summary
- information when the current directory is located in a Git repository.
-
-GIT TAB COMPLETION
- You can tab complete most common Git subcommands e.g.:
-
- C:\GitHub\posh-git> git ch --> git checkout
-
- You can also tab complete branch names and even remote names such as
- origin and upstream. For instance, type the following inside of a Git
- repo to see tab completion in action:
-
- C:\GitHub\posh-git> git fe or ma
-
- The above will expand to:
-
- C:\GitHub\posh-git> git fetch origin master
-
- And like tab completion in other parts of PowerShell, you can press tab
- multiple times to cycle through all matches. For instance, type
- "git ch" and press the tab key multiple times to cycle through "checkout",
- "cherry" and "cherry-pick".
-
-POWERSHELL PROMPT
- PowerShell generates its prompt by executing a function named "prompt", if
- one exists. posh-git will install its prompt function if it detects the
- user does not have their own, customized prompt function. This prompt
- displays the current working directory followed by git status summary
- information if the current directory is located in a Git repository, e.g.:
-
- C:\GitHub\posh-git [master ≡]>
-
- You can customize the posh-git prompt with the following settings:
-
- $GitPromptSettings.DefaultPromptPrefix
- $GitPromptSettings.DefaultPromptSuffix
- $GitPromptSettings.DefaultPromptDebugSuffix
- $GitPromptSettings.DefaultPromptEnableTiming
- $GitPromptSettings.DefaultPromptAbbreviateHomeDirectory
-
- For more information on customizing the posh-git prompt or creating your
- own custom PowerShell prompt see:
-
- https://github.com/dahlbyk/posh-git/wiki/Customizing-Your-PowerShell-Prompt
-
-GIT STATUS SUMMARY
- [{HEAD-name} S +A ~B -C !D | +E ~F -G !H W]
-
- * [ (BeforeText)
- * {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 remote (tracked origin) branch
- * ≡ = Local branch is at the same commit level as the remote
- branch (BranchIdenticalStatus).
- * ↑ = 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).
- * ↓ = Local branch is behind the remote branch by the specified
- number of commits; a 'git pull' is required to update the
- local branch (BranchBehindStatus).
- * ↕= Local branch is both ahead of the remote branch by the
- specified number of commits (]