diff --git a/src/Utils.ps1 b/src/Utils.ps1 index 3756a84d6..2d660343d 100644 --- a/src/Utils.ps1 +++ b/src/Utils.ps1 @@ -216,6 +216,123 @@ function Add-PoshGitToProfile { } } +<# +.SYNOPSIS + Modifies your PowerShell profile (startup) script so that it does not import + the posh-git module when PowerShell starts. +.DESCRIPTION + Checks if your PowerShell profile script is importing posh-git and if it does, + removes the command to import the posh-git module. This will cause PowerShell + to no longer 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 (or AllUsersAllHosts, given -AllUsers). +.PARAMETER AllUsers + By default, this command modifies the CurrentUserCurrentHost profile + script. By specifying the AllUsers switch, the command updates the + AllUsersCurrentHost profile (or AllUsersAllHosts, given -AllHosts). + Requires elevated permissions. +.EXAMPLE + PS C:\> Remove-PoshGitFromProfile + Updates your profile script for the current PowerShell host to stop importing + the posh-git module when the current PowerShell host starts. +.EXAMPLE + PS C:\> Remove-PoshGitFromProfile -AllHosts + Updates your profile script for all PowerShell hosts to no longer import the + posh-git module whenever any PowerShell host starts. +.INPUTS + None. +.OUTPUTS + None. +#> +function Remove-PoshGitFromProfile { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter()] + [switch] + $AllHosts, + + [Parameter()] + [switch] + $AllUsers, + + [Parameter(ValueFromRemainingArguments)] + [psobject[]] + $TestParams + ) + + if ($AllUsers -and !(Test-Administrator)) { + throw 'Removing posh-git from an AllUsers profile requires an elevated host.' + } + + $underTest = $false + + $profileName = $(if ($AllUsers) { 'AllUsers' } else { 'CurrentUser' }) ` + + $(if ($AllHosts) { 'AllHosts' } else { 'CurrentHost' }) + Write-Verbose "`$profileName = '$profileName'" + + $profilePath = $PROFILE.$profileName + Write-Verbose "`$profilePath = '$profilePath'" + + # Under test, we override some variables using $args as a backdoor. + if (($TestParams.Count -gt 0) -and ($TestParams[0] -is [string])) { + $profilePath = [string]$TestParams[0] + $underTest = $true + if ($TestParams.Count -gt 1) { + $ModuleBasePath = [string]$TestParams[1] + } + } + + if (!$profilePath) { $profilePath = $PROFILE } + + if (!$profilePath) { + Write-Warning "Skipping add of posh-git import to profile; no profile found." + 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 + } + + if (Test-Path -LiteralPath $profilePath) { + # If the profile script exists and is signed, then we should not modify it + if (!(Get-Command Get-AuthenticodeSignature -ErrorAction SilentlyContinue)) + { + Write-Verbose "Platform doesn't support script signing, skipping test for signed profile." + } + else { + $sig = Get-AuthenticodeSignature $profilePath + if ($null -ne $sig.SignerCertificate) { + Write-Warning "Skipping add of posh-git import to profile; '$profilePath' appears to be signed." + Write-Warning "Add the command 'Import-Module posh-git' to your profile and resign it." + return + } + } + + $oldProfile = @(Get-Content $profilePath) + + . $currentVersionPath\src\Utils.ps1 + $oldProfileEncoding = Get-FileEncoding $profilePath + + $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 *\posh-git.psd1*') { + continue; + } + $newProfile += $line + } + Set-Content -path $profilePath -value $newProfile -Force -Encoding $oldProfileEncoding + } +} + <# .SYNOPSIS Gets the file encoding of the specified file. diff --git a/src/posh-git.psd1 b/src/posh-git.psd1 index 72b760e7c..50c63728d 100644 --- a/src/posh-git.psd1 +++ b/src/posh-git.psd1 @@ -33,6 +33,7 @@ FunctionsToExport = @( 'Get-PromptPath', 'New-GitPromptSettings', 'Remove-GitBranch', + 'Remove-PoshGitFromProfile', 'Update-AllBranches', 'Write-GitStatus', 'Write-GitBranchName', diff --git a/src/posh-git.psm1 b/src/posh-git.psm1 index 7324774fd..fad6ca185 100644 --- a/src/posh-git.psm1 +++ b/src/posh-git.psm1 @@ -171,6 +171,7 @@ $exportModuleMemberParams = @{ 'Get-PromptPath', 'New-GitPromptSettings', 'Remove-GitBranch', + 'Remove-PoshGitFromProfile', 'Update-AllBranches', 'Write-GitStatus', 'Write-GitBranchName', diff --git a/test/Utils.Tests.ps1 b/test/Utils.Tests.ps1 index 3360a4781..80be899f8 100644 --- a/test/Utils.Tests.ps1 +++ b/test/Utils.Tests.ps1 @@ -101,6 +101,27 @@ New-Alias pscore C:\Users\Keith\GitHub\rkeithhill\PowerShell\src\powershell-win- $expectedContent += "${newLine}${newLine}Import-Module '$(Join-Path $moduleBasePath posh-git).psd1'" $content -join $newLine | Should -BeExactly $expectedContent } + It 'Removes import from the profile correctly' { + $profileContent = @' +Import-Module PSCX +'@ + Set-Content $profilePath -Value $profileContent -Encoding Ascii + + $moduleBasePath = Split-Path $profilePath -Parent + Add-PoshGitToProfile $profilePath $moduleBasePath + + $output = Remove-PoshGitFromProfile $profilePath 3>&1 + + Write-Host "output: $output" + $output.Length | Should -Be 0 + Get-FileEncoding $profilePath | Should -Be 'ascii' + $content = Get-Content $profilePath + $content.Count | Should -Be 2 + $content[0] | Should -BeExactly $profileContent + $content[1] | Should -BeExactly '' + $expectedContent = Convert-NativeLineEnding $profileContent + $content -join "" | Should -BeExactly $expectedContent + } } Context 'Get-PromptConnectionInfo' {