Repository: flofreud/posh-gvm Branch: master Commit: 7101f92684fe Files: 14 Total size: 112.3 KB Directory structure: gitextract_9qyeor5j/ ├── CHANGELOG.md ├── Commands.Tests.ps1 ├── Commands.ps1 ├── GetPoshGvm.ps1 ├── Init.Tests.ps1 ├── Init.ps1 ├── LICENSE ├── README.md ├── TabExpansion.ps1 ├── TestUtils.ps1 ├── Utils.Tests.ps1 ├── Utils.ps1 ├── VERSION.txt └── posh-gvm.psm1 ================================================ FILE CONTENTS ================================================ ================================================ FILE: CHANGELOG.md ================================================ ### Version 1.3.0 * BUGFIX: update url to API endpoint * BUGFIX: support for symlink handling in Win10 * IMPROVE: use 7zip for archive extraction if available on path * BUGFIX: walkaround for rare ACCESS_DENIED error on SDK installation * BUGFIX: always show correct download file sizes ### Version 1.2.2 * BUGFIX: explicitly handle a missing version definition for uninstall * BUGFIX: added -Force for Remove-Item in the uninstall process ### Version 1.2.1 * BUGFIX: fixed wrong url construction for broadcast api ### Version 1.2.0 * IMPROVE: update to the new broadcast api for GVM ### Version 1.1.4 * IMPROVE: version check requests where executed on module import and took some time, these checks will now be executed on first gvm-call ### Version 1.1.3 * IMPROVE: the new version messaging ### Version 1.1.2 * BUGFIX: installation routine in GetPoshGvm.ps1 broken ### Version 1.1.1 * BUGFIX: default of $Global:PGVM_AUTO_SELFUPDATE was $true but should have been $false ### Version 1.1.0 * FEATURE: use unzip.exe if available on path for better install performance * FEATURE: self-update * FEATURE: automatic check for new posh-gvm versions ### Version 1.0.0 * posh-gvm before it has self-update functionality ================================================ FILE: Commands.Tests.ps1 ================================================ . .\Commands.ps1 . .\Utils.ps1 . .\Init.ps1 . .\TestUtils.ps1 Describe 'gvm' { Context 'No posh-gvm dir available'{ $Script:GVM_FORCE_OFFLINE = $true Mock-PGVM-Dir Remove-Item $global:PGVM_DIR -Recurse Mock Init-Posh-Gvm -verifiable Mock Init-Candidate-Cache -verifiable Mock Show-Help gvm It 'initalize posh-gvm' { Assert-VerifiableMocks } It 'prints help' { Assert-MockCalled Show-Help 1 } Reset-PGVM-Dir } Context 'Posh-gvm dir available'{ $Script:GVM_FORCE_OFFLINE = $true Mock-PGVM-Dir Mock Init-Posh-Gvm Mock Init-Candidate-Cache -verifiable Mock Show-Help gvm It 'initalize posh-gvm' { Assert-VerifiableMocks } It 'does not init again' { Assert-MockCalled Init-Posh-Gvm 0 } It 'prints help' { Assert-MockCalled Show-Help 1 } } Context 'posh-gvm is forced offline' { Mock-PGVM-DIR Mock Init-Candidate-Cache -verifiable Mock Check-Available-Broadcast Mock Show-Help -verifiable $Script:GVM_FORCE_OFFLINE = $true gvm It 'does not load broadcast message from api' { Assert-MockCalled Check-Available-Broadcast 0 } It 'performs default command actions' { Assert-VerifiableMocks } Reset-PGVM-DIR } Context 'posh-gvm offline command called' { Mock-PGVM-DIR Mock Init-Candidate-Cache -verifiable Mock Check-Available-Broadcast Mock Set-Offline-Mode -verifiable $Script:GVM_FORCE_OFFLINE = $false gvm offline It 'does not load broadcast message from api' { Assert-MockCalled Check-Available-Broadcast 0 } It 'performs offline command actions' { Assert-VerifiableMocks } Reset-PGVM-DIR } Context 'posh-gvm online and command i called' { Mock-Dispatcher-Test Mock Install-Candidate-Version -verifiable -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '2.2.2' -and $InstallPath -eq '\bla' } gvm i grails 2.2.2 \bla It 'checks for new broadcast, inits the Candidate-Cache and calls install-command' { Assert-VerifiableMocks } Reset-Dispatcher-Test } Context 'posh-gvm online and command install called' { Mock-Dispatcher-Test Mock Install-Candidate-Version -verifiable -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '2.2.2' -and $InstallPath -eq '' } gvm install grails 2.2.2 It 'checks for new broadcast, inits the Candidate-Cache and calls install-command' { Assert-VerifiableMocks } Reset-Dispatcher-Test } Context 'posh-gvm online and command uninstall called' { Mock-Dispatcher-Test Mock Uninstall-Candidate-Version -verifiable -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '2.2.2' } gvm uninstall grails 2.2.2 It 'checks for new broadcast, inits the Candidate-Cache and calls uninstall-command' { Assert-VerifiableMocks } Reset-Dispatcher-Test } Context 'posh-gvm online and command rm called' { Mock-Dispatcher-Test Mock Uninstall-Candidate-Version -verifiable -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '2.2.1' } gvm rm grails 2.2.1 It 'checks for new broadcast, inits the Candidate-Cache and calls uninstall-command' { Assert-VerifiableMocks } Reset-Dispatcher-Test } Context 'posh-gvm online and command ls called' { Mock-Dispatcher-Test Mock List-Candidate-Versions -verifiable -parameterFilter { $Candidate -eq 'grails' } gvm ls grails It 'checks for new broadcast, inits the Candidate-Cache and calls list-command' { Assert-VerifiableMocks } Reset-Dispatcher-Test } Context 'posh-gvm online and command list called' { Mock-Dispatcher-Test Mock List-Candidate-Versions -verifiable -parameterFilter { $Candidate -eq 'grails' } gvm list grails It 'checks for new broadcast, inits the Candidate-Cache and calls list-command' { Assert-VerifiableMocks } Reset-Dispatcher-Test } Context 'posh-gvm online and command u called' { Mock-Dispatcher-Test Mock Use-Candidate-Version -verifiable -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '2.2.1' } gvm u grails 2.2.1 It 'checks for new broadcast, inits the Candidate-Cache and calls use-command' { Assert-VerifiableMocks } Reset-Dispatcher-Test } Context 'posh-gvm online and command use called' { Mock-Dispatcher-Test Mock Use-Candidate-Version -verifiable -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '2.2.1' } gvm use grails 2.2.1 It 'checks for new broadcast, inits the Candidate-Cache and calls use-command' { Assert-VerifiableMocks } Reset-Dispatcher-Test } Context 'posh-gvm online and command d called' { Mock-Dispatcher-Test Mock Set-Default-Version -verifiable -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '2.2.1' } gvm d grails 2.2.1 It 'checks for new broadcast, inits the Candidate-Cache and calls default-command' { Assert-VerifiableMocks } Reset-Dispatcher-Test } Context 'posh-gvm online and command default called' { Mock-Dispatcher-Test Mock Set-Default-Version -verifiable -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '2.2.1' } gvm default grails 2.2.1 It 'checks for new broadcast, inits the Candidate-Cache and calls default-command' { Assert-VerifiableMocks } Reset-Dispatcher-Test } Context 'posh-gvm online and command c called' { Mock-Dispatcher-Test Mock Show-Current-Version -verifiable -parameterFilter { $Candidate -eq 'grails' } gvm c grails It 'checks for new broadcast, inits the Candidate-Cache and calls current-command' { Assert-VerifiableMocks } Reset-Dispatcher-Test } Context 'posh-gvm online and command current called' { Mock-Dispatcher-Test Mock Show-Current-Version -verifiable -parameterFilter { $Candidate -eq 'grails' } gvm current grails It 'checks for new broadcast, inits the Candidate-Cache and calls current-command' { Assert-VerifiableMocks } Reset-Dispatcher-Test } Context 'posh-gvm online and command v called' { Mock-Dispatcher-Test Mock Show-Posh-Gvm-Version -verifiable gvm v It 'checks for new broadcast, inits the Candidate-Cache and calls version-command' { Assert-VerifiableMocks } Reset-Dispatcher-Test } Context 'posh-gvm online and command version called' { Mock-Dispatcher-Test Mock Show-Posh-Gvm-Version -verifiable gvm version It 'checks for new broadcast, inits the Candidate-Cache and calls version-command' { Assert-VerifiableMocks } Reset-Dispatcher-Test } Context 'posh-gvm online and command b called' { Mock-Dispatcher-Test Mock Show-Broadcast-Message -verifiable gvm b It 'checks for new broadcast, inits the Candidate-Cache and calls broadcast-command' { Assert-VerifiableMocks } Reset-Dispatcher-Test } Context 'posh-gvm online and command broadcast called' { Mock-Dispatcher-Test Mock Show-Broadcast-Message -verifiable gvm broadcast It 'checks for new broadcast, inits the Candidate-Cache and calls broadcast-command' { Assert-VerifiableMocks } Reset-Dispatcher-Test } Context 'posh-gvm online and command h called' { Mock-Dispatcher-Test Mock Show-Help -verifiable gvm h It 'checks for new broadcast, inits the Candidate-Cache and calls help-command' { Assert-VerifiableMocks } Reset-Dispatcher-Test } Context 'posh-gvm online and command help called' { Mock-Dispatcher-Test Mock Show-Help -verifiable gvm help It 'checks for new broadcast, inits the Candidate-Cache and calls help-command' { Assert-VerifiableMocks } Reset-Dispatcher-Test } Context 'posh-gvm online and command offline called' { Mock-Dispatcher-Test -Offline Mock Set-Offline-Mode -verifiable -parameterFilter { $Flag -eq 'enable' } gvm offline enable It 'checks for new broadcast, inits the Candidate-Cache and calls offline-command' { Assert-VerifiableMocks } Reset-Dispatcher-Test } Context 'posh-gvm online and command selfupdate called' { Mock-Dispatcher-Test Mock Invoke-Self-Update -verifiable gvm selfupdate It 'checks for new broadcast, inits the Candidate-Cache and calls selfupdate-command' { Assert-VerifiableMocks } Reset-Dispatcher-Test } Context 'posh-gvm online and command flush called' { Mock-Dispatcher-Test Mock Flush-Cache -verifiable -parameterFilter { $DataType -eq 'version' } gvm flush version It 'checks for new broadcast, inits the Candidate-Cache and calls flush-command' { Assert-VerifiableMocks } Reset-Dispatcher-Test } } Describe 'Install-Candidate-Version' { Context 'Remote Version already installed' { Mock Check-Candidate-Present -verifiable -parameterFilter { $Candidate -eq 'grails' } Mock Check-Candidate-Version-Available { '1.1.1' } -verifiable { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } Mock Is-Candidate-Version-Locally-Available { $true } -verifiable { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } It 'throw an error' { { Install-Candidate-Version grails 1.1.1 } | Should Throw } It 'process precondition checks' { Assert-VerifiableMocks } } Context 'Local Version already installed' { Mock Check-Candidate-Present -verifiable -parameterFilter { $Candidate -eq 'grails' } Mock Check-Candidate-Version-Available { throw 'error' } -verifiable { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } Mock Is-Candidate-Version-Locally-Available { $true } -verifiable { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } It 'throw an error' { { Install-Candidate-Version grails 1.1.1 \bla } | Should Throw } It 'process precondition checks' { Assert-VerifiableMocks } } Context 'Local path but version is remote available already installed' { Mock Check-Candidate-Present -verifiable -parameterFilter { $Candidate -eq 'grails' } Mock Check-Candidate-Version-Available { 1.1.1 } -verifiable { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } It 'throw an error' { { Install-Candidate-Version grails 1.1.1 \bla } | Should Throw } It 'process precondition checks' { Assert-VerifiableMocks } } Context 'Local version installation without defaulting' { $backupAutoAnswer = $Global:PGVM_AUTO_ANSWER $Global:PGVM_AUTO_ANSWER = $false Mock Check-Candidate-Present -verifiable -parameterFilter { $Candidate -eq 'grails' } Mock Check-Candidate-Version-Available { throw 'error' } -verifiable { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } Mock Is-Candidate-Version-Locally-Available { $false } -verifiable { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } Mock Install-Local-Version -verifiable -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '1.1.1' -and $LocalPath -eq '\bla' } Mock Read-Host { 'n' } Mock Set-Linked-Candidate-Version Install-Candidate-Version grails 1.1.1 \bla It 'installs the local version' { Assert-VerifiableMocks } It "does not set default" { Assert-MockCalled Set-Linked-Candidate-Version 0 } $Global:PGVM_AUTO_ANSWER = $backupAutoAnswer } Context 'Local version installation with auto defaulting' { $backupAutoAnswer = $Global:PGVM_AUTO_ANSWER $Global:PGVM_AUTO_ANSWER = $true Mock Check-Candidate-Present -verifiable -parameterFilter { $Candidate -eq 'grails' } Mock Check-Candidate-Version-Available { throw 'error' } -verifiable { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } Mock Is-Candidate-Version-Locally-Available { $false } -verifiable { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } Mock Install-Local-Version -verifiable -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '1.1.1' -and $LocalPath -eq '\bla' } Mock Set-Linked-Candidate-Version -verifiable -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } Mock Write-Output -verifiable Install-Candidate-Version grails 1.1.1 \bla It 'installs the local version' { Assert-VerifiableMocks } $Global:PGVM_AUTO_ANSWER = $backupAutoAnswer } Context 'Remote version installation with prompt defaulting' { $backupAutoAnswer = $Global:PGVM_AUTO_ANSWER $Global:PGVM_AUTO_ANSWER = $false Mock Check-Candidate-Present -verifiable -parameterFilter { $Candidate -eq 'grails' } Mock Check-Candidate-Version-Available { '1.1.1' } -verifiable { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } Mock Is-Candidate-Version-Locally-Available { $false } -verifiable { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } Mock Install-Remote-Version -verifiable -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } Mock Read-Host { 'y' } Mock Set-Linked-Candidate-Version -verifiable -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } Mock Write-Output -verifiable Install-Candidate-Version grails 1.1.1 It 'installs the local version' { Assert-VerifiableMocks } $Global:PGVM_AUTO_ANSWER = $backupAutoAnswer } } Describe 'Uninstall-Candidate-Version' { Context 'No version is provided' { Mock Check-Candidate-Present -verifiable -parameterFilter { $Candidate -eq 'grails' } It 'throws an error' { { Uninstall-Candidate-Version grails } | Should Throw } } Context 'To be uninstalled version is not installed' { Mock Check-Candidate-Present -verifiable -parameterFilter { $Candidate -eq 'grails' } Mock Is-Candidate-Version-Locally-Available { $false } -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '24.3' } It 'throws an error' { { Uninstall-Candidate-Version grails 24.3 } | Should Throw } It 'checks candidate' { Assert-VerifiableMocks } } Context 'To be uninstalled Version is current version' { Mock-PGVM-Dir New-Item -ItemType Directory "$Global:PGVM_DIR\grails\24.3" | Out-Null Set-Linked-Candidate-Version grails 24.3 It 'finds current-junction defined' { Test-Path "$Global:PGVM_DIR\grails\current" | Should Be $true } Mock Check-Candidate-Present -verifiable -parameterFilter { $Candidate -eq 'grails' } Mock Is-Candidate-Version-Locally-Available { $true } -verifiable -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '24.3' } Mock Get-Current-Candidate-Version { '24.3' } -verifiable -parameterFilter { $Candidate -eq 'grails' } Mock Write-Output -verifiable Uninstall-Candidate-Version grails 24.3 It 'delete the current-junction' { Test-Path "$Global:PGVM_DIR\grails\current" | Should Be $false } It 'delete the version' { Test-Path "$Global:PGVM_DIR\grails\24.3" | Should Be $false } It "checks different preconditions correctly" { Assert-VerifiableMocks } Reset-PGVM-Dir } Context 'To be uninstalled version is installed' { Mock-PGVM-Dir New-Item -ItemType Directory "$Global:PGVM_DIR\grails\24.3" | Out-Null Mock Check-Candidate-Present -verifiable -parameterFilter { $Candidate -eq 'grails' } Mock Is-Candidate-Version-Locally-Available { $true } -verifiable -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '24.3'} Mock Get-Current-Candidate-Version { $null } -verifiable -parameterFilter { $Candidate -eq 'grails' } Mock Write-Output -verifiable Uninstall-Candidate-Version grails 24.3 It 'delete the version' { Test-Path "$Global:PGVM_DIR\grails\24.3" | Should Be $false } It "checks different preconditions correctly" { Assert-VerifiableMocks } Reset-PGVM-Dir } } Describe 'List-Candidate-Versions' { Context 'if in online mode' { Mock-Online Mock Check-Candidate-Present -verifiable -parameterFilter { $Candidate -eq 'grails' } Mock Write-Version-List -verifiable -parameterFilter { $Candidate -eq 'grails' } List-Candidate-Versions grails It 'write the version list retrieved from api' { Assert-VerifiableMocks } } Context 'If in offline mode' { Mock-Offline Mock Check-Candidate-Present -verifiable -parameterFilter { $Candidate -eq 'grails' } Mock Write-Offline-Version-List -verifiable -parameterFilter { $Candidate -eq 'grails' } List-Candidate-Versions grails It 'write the version list based on local file structure' { Assert-VerifiableMocks } } } Describe 'Use-Candidate-Version' { Context 'If new use version is already used' { Mock Check-Candidate-Version-Available { '1.1.1' } -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } Mock Get-Env-Candidate-Version { '1.1.1' } -parameterFilter { $Candidate -eq 'grails' } Mock Write-Output -verifiable Mock Check-Candidate-Version-Locally-Available Use-Candidate-Version grails 1.1.1 It 'changes nothing' { Assert-VerifiableMocks } It 'does not test candidate version' { Assert-MockCalled Check-Candidate-Version-Locally-Available 0 } } Context 'If setting a different version as the current version to use' { Mock Check-Candidate-Version-Available { '1.1.1' } -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } Mock Get-Env-Candidate-Version { '1.1.0' } -parameterFilter { $Candidate -eq 'grails' } Mock Write-Output -verifiable Mock Check-Candidate-Version-Locally-Available -verifiable -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } Mock Set-Env-Candidate-Version -verifiable -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } Use-Candidate-Version grails 1.1.1 It 'perform the changes' { Assert-VerifiableMocks } } } Describe 'Set-Default-Version' { Context 'If new default is already default' { Mock Check-Candidate-Version-Available { '1.1.1' } -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } Mock Get-Current-Candidate-Version { '1.1.1' } -parameterFilter { $Candidate -eq 'grails' } Mock Write-Output -verifiable Mock Check-Candidate-Version-Locally-Available Set-Default-Version grails 1.1.1 It 'changes nothing' { Assert-VerifiableMocks } It 'does not test candidate version' { Assert-MockCalled Check-Candidate-Version-Locally-Available 0 } } Context 'If setting a new default' { Mock Check-Candidate-Version-Available { '1.1.1' } -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } Mock Get-Current-Candidate-Version { '1.1.0' } -parameterFilter { $Candidate -eq 'grails' } Mock Write-Output -verifiable Mock Check-Candidate-Version-Locally-Available -verifiable -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } Mock Set-Linked-Candidate-Version -verifiable -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } Set-Default-Version grails 1.1.1 It 'perform the changes' { Assert-VerifiableMocks } } } Describe 'Show-Current-Version' { Context 'If called without candidate' { $Script:GVM_CANDIDATES = @('grails','groovy','bla') Mock Get-Env-Candidate-Version { '1.1.0' } -parameterFilter { $Candidate -eq 'grails' } Mock Get-Env-Candidate-Version { '2.1.0' } -parameterFilter { $Candidate -eq 'groovy' } Mock Get-Env-Candidate-Version { '0.1.0' } -parameterFilter { $Candidate -eq 'bla' } Mock Write-Output -verifiable -parameterFilter { $InputObject -eq 'Using:' } Mock Write-Output -verifiable -parameterFilter { $InputObject -eq 'grails: 1.1.0' } Mock Write-Output -verifiable -parameterFilter { $InputObject -eq 'groovy: 2.1.0' } Mock Write-Output -verifiable -parameterFilter { $InputObject -eq 'bla: 0.1.0' } Show-Current-Version It 'write the version for all currently used candidates' { Assert-VerifiableMocks } } Context 'If called with specifiv candidate and version available' { Mock Check-Candidate-Present -verifiable Mock Get-Env-Candidate-Version { '1.1.0' } -parameterFilter { $Candidate -eq 'grails' } Mock Write-Output -verifiable -parameterFilter { $InputObject -eq 'Using grails version 1.1.0' } Show-Current-Version grails It 'write version info' { Assert-VerifiableMocks } } Context 'If called with specifiv candidate and no version available' { Mock Check-Candidate-Present -verifiable Mock Get-Env-Candidate-Version { $null } -parameterFilter { $Candidate -eq 'grails' } Mock Write-Output -verifiable -parameterFilter { $InputObject -eq 'Not using any version of grails' } Show-Current-Version grails It 'write no version is available' { Assert-VerifiableMocks } } } Describe 'Show-Posh-Gvm-Version' { Context 'When called' { Mock Get-GVM-API-Version -verifiable Mock Get-Posh-Gvm-Version -verifiable Mock Write-Output -verifiable Show-Posh-Gvm-Version It 'write the version message to output' { Assert-VerifiableMocks } } } Describe 'Show-Broadcast-Message' { Context 'When called' { $Script:PGVM_BROADCAST_PATH = 'broadcast' Mock Get-Content { 'broadcast' } -verifiable -parameterFilter { $Path -eq 'broadcast' } Mock Write-Output -verifiable Show-Broadcast-Message It 'Write broadcast message to output' { Assert-VerifiableMocks } } } Describe 'Set-Offline-Mode' { Context 'If called with invalid flag' { It 'throws an error' { { Set-Offline-Mode invalid } | Should Throw } } Context 'If called with enable flag' { $Script:GVM_FORCE_OFFLINE = $false Mock Write-Output -verifiable Set-Offline-Mode enable It "set offline mode" { $Script:GVM_FORCE_OFFLINE | Should Be $true } It "writes info to output" { Assert-VerifiableMocks } } Context 'if called with disable flag' { $Script:GVM_ONLINE = $false $Script:GVM_FORCE_OFFLINE = $true Mock Write-Output -verifiable Set-Offline-Mode disable It "deactivate offline mode" { $Script:GVM_FORCE_OFFLINE | Should Be $false } It "set gvm to online" { $Script:GVM_ONLINE | Should Be $true } It "writes info to output" { Assert-VerifiableMocks } } } Describe 'Flush-Cache' { Context 'Try to delete existing candidates cache' { $Script:PGVM_CANDIDATES_PATH = 'test' Mock Test-Path { $true } -parameterFilter { $Path -eq 'test' } Mock Remove-Item -verifiable -parameterFilter { $Path -eq 'test' } Mock Write-Output -verifiable Flush-Cache candidates It 'deletes the file and writes flush message' { Assert-VerifiableMocks } } Context 'Try to delete non-existing candidates cache' { $Script:PGVM_CANDIDATES_PATH = 'test2' Mock Test-Path { $false } -parameterFilter { $Path -eq 'test2' } Mock Write-Warning -verifiable Flush-Cache candidates It 'writes warning about non existing file' { Assert-VerifiableMocks } } Context 'Try to delete existing broadcast cache' { $Script:PGVM_BROADCAST_PATH = 'test' Mock Test-Path { $true } -parameterFilter { $Path -eq 'test' } Mock Remove-Item -verifiable -parameterFilter { $Path -eq 'test' } Mock Write-Output -verifiable Flush-Cache broadcast It 'deletes the file and writes flush message' { Assert-VerifiableMocks } } Context 'Try to delete non-existing broadcast cache' { $Script:PGVM_BROADCAST_PATH = 'test2' Mock Test-Path { $false } -parameterFilter { $Path -eq 'test2' } Mock Write-Warning -verifiable Flush-Cache broadcast It 'writes warning about non existing file' { Assert-VerifiableMocks } } Context 'Try to delete existing version cache' { $Script:GVM_API_VERSION_PATH = 'test' Mock Test-Path { $true } -parameterFilter { $Path -eq 'test' } Mock Remove-Item -verifiable -parameterFilter { $Path -eq 'test' } Mock Write-Output -verifiable Flush-Cache version It 'deletes the file and writes flush message' { Assert-VerifiableMocks } } Context 'Try to delete non-existing version cache' { $Script:GVM_API_VERSION_PATH = 'test2' Mock Test-Path { $false } -parameterFilter { $Path -eq 'test2' } Mock Write-Warning -verifiable Flush-Cache version It 'writes warning about non existing file' { Assert-VerifiableMocks } } Context 'Cleanup archives directory' { $Script:PGVM_ARCHIVES_PATH = 'archives' Mock Cleanup-Directory -verifiable -parameterFilter { $Path -eq 'archives' } Flush-Cache archives It 'cleanup archives directory' { Assert-VerifiableMocks } } Context 'Cleanup temp directory' { $Script:PGVM_TEMP_PATH = 'temp' Mock Cleanup-Directory -verifiable -parameterFilter { $Path -eq 'temp' } Flush-Cache temp It 'cleanup temp directory' { Assert-VerifiableMocks } } Context 'Cleanup tmp directory' { $Script:PGVM_TEMP_PATH = 'temp' Mock Cleanup-Directory -verifiable -parameterFilter { $Path -eq 'temp' } Flush-Cache tmp It 'cleanup temp directory' { Assert-VerifiableMocks } } Context 'flush invalid parameter' { It 'throws an error' { { Flush-Cache invalid } | Should Throw } } } Describe 'Show-Help' { Context 'If Show-Help is called' { Mock Write-Output -verifiable Show-Help It 'write the help to the output' { Assert-VerifiableMocks } } } ================================================ FILE: Commands.ps1 ================================================ function gvm([string]$Command, [string]$Candidate, [string]$Version, [string]$InstallPath, [switch]$Verbose, [switch]$Force) { $ErrorActionPreference = 'Stop' $ProgressPreference = 'SilentlyContinue' if ($Verbose) { $VerbosePreference = 'Continue' } if ( !( Test-Path $Global:PGVM_DIR ) ) { Write-Warning "$Global:PGVM_DIR does not exists. Reinitialize posh-gvm" Init-Posh-Gvm } $Script:GVM_AVAILABLE = $true if ( !($Script:GVM_FORCE_OFFLINE) -and $Command -ne 'offline' ) { Check-Available-Broadcast $Command if ( $Script:GVM_AVAILABLE ) { if ( $Script:FIRST_RUN ) { Check-GVM-API-Version Check-Posh-Gvm-Version $Script:FIRST_RUN = $false } Write-New-Version-Broadcast } } Init-Candidate-Cache Write-Verbose "Command: $Command" if ($Command -eq '') { $Command = 'help' } try { switch -regex ($Command) { '^i(nstall)?$' { Install-Candidate-Version $Candidate $Version $InstallPath } '^(uninstall|rm)$'{ Uninstall-Candidate-Version $Candidate $Version } '^(ls|list)$' { List-Candidate-Versions $Candidate } '^u(se)?$' { Use-Candidate-Version $Candidate $Version } '^d(efault)?$' { Set-Default-Version $Candidate $Version } '^c(urrent)?$' { Show-Current-Version $Candidate } '^v(ersion)?$' { Show-Posh-Gvm-Version } '^b(roadcast)?$' { Show-Broadcast-Message } '^h(elp)?$' { Show-Help } '^offline$' { Set-Offline-Mode $Candidate } '^selfupdate$' { Invoke-Self-Update($Force) } '^flush$' { Flush-Cache $Candidate } default { Write-Warning "Invalid command: $Command. Check gvm help!" } } } catch { if ( $_.CategoryInfo.Category -eq 'OperationStopped') { Write-Warning $_.CategoryInfo.TargetName } else { throw } } } function Install-Candidate-Version($Candidate, $Version, $InstallPath) { Write-Verbose 'Perform Install-Candidate-Version' Check-Candidate-Present $Candidate $localInstallation = $false if ($Version -and $InstallPath) { #local installation try { $Version = Check-Candidate-Version-Available $Candidate $Version } catch { $localInstallation = $true } if ( !($localInstallation) ) { throw 'Stop! Local installation for $Candidate $Version not possible. It exists remote already.' } } else { $Version = Check-Candidate-Version-Available $Candidate $Version } if ( Is-Candidate-Version-Locally-Available $Candidate $Version ) { throw "Stop! $Candidate $Version is already installed." } if ( $localInstallation ) { Install-Local-Version $Candidate $Version $InstallPath } else { Install-Remote-Version $Candidate $Version } $default = $false if ( !$Global:PGVM_AUTO_ANSWER ) { $default = (Read-Host -Prompt "Do you want $Candidate $Version to be set as default? (Y/n)") -match '(y|\A\z)' } else { $default = $true } if ( $default ) { Write-Output "Setting $Candidate $Version as default." Set-Linked-Candidate-Version $Candidate $Version } } function Uninstall-Candidate-Version($Candidate, $Version) { Write-Verbose 'Perform Uninstall-Candidate-Version' Check-Candidate-Present $Candidate Check-Version-Present $Version if ( !(Is-Candidate-Version-Locally-Available $Candidate $Version) ) { throw "$Candidate $Version is not installed." } $current = Get-Current-Candidate-Version $Candidate if ( $current -eq $Version ) { Write-Output "Unselecting $Candidate $Version..." (Get-Item "$Global:PGVM_DIR\$Candidate\current").Delete() } Write-Output "Uninstalling $Candidate $Version..." Remove-Item -Recurse -Force "$Global:PGVM_DIR\$Candidate\$Version" } function List-Candidate-Versions($Candidate) { Write-Verbose 'Perform List-Candidate-Version' Check-Candidate-Present $Candidate if ( Get-Online-Mode ) { Write-Version-List $Candidate } else { Write-Offline-Version-List $Candidate } } function Use-Candidate-Version($Candidate, $Version) { Write-Verbose 'Perform Use-Candidate-Version' $Version = Check-Candidate-Version-Available $Candidate $Version if ( $Version -eq (Get-Env-Candidate-Version $Candidate) ) { Write-Output "$Candidate $Version is used. Nothing changed." } else { Check-Candidate-Version-Locally-Available $Candidate $Version Set-Env-Candidate-Version $Candidate $Version Write-Output "Using $CANDIDATE version $Version in this shell." } } function Set-Default-Version($Candidate, $Version) { Write-Verbose 'Perform Set-Default-Version' $Version = Check-Candidate-Version-Available $Candidate $Version if ( $Version -eq (Get-Current-Candidate-Version $Candidate) ) { Write-Output "$Candidate $Version is already default. Nothing changed." } else { Check-Candidate-Version-Locally-Available $Candidate $Version Set-Linked-Candidate-Version $Candidate $Version Write-Output "Default $Candidate version set to $Version" } } function Show-Current-Version($Candidate) { Write-Verbose 'Perform Set-Current-Version' if ( !($Candidate) ) { Write-Output 'Using:' foreach ( $c in $Script:GVM_CANDIDATES ) { $v = Get-Env-Candidate-Version $c if ($v) { Write-Output "$c`: $v" } } return } Check-Candidate-Present $Candidate $Version = Get-Env-Candidate-Version $Candidate if ( $Version ) { Write-Output "Using $Candidate version $Version" } else { Write-Output "Not using any version of $Candidate" } } function Show-Posh-Gvm-Version() { $poshGvmVersion = Get-Posh-Gvm-Version $apiVersion = Get-GVM-API-Version Write-Output "posh-gvm (POwer SHell Groovy enVironment Manager) $poshGvmVersion base on GVM $GVM_BASE_VERSION and GVM API $apiVersion" } function Show-Broadcast-Message() { Write-Verbose 'Perform Show-Broadcast-Message' Get-Content $Script:PGVM_BROADCAST_PATH | Write-Output } function Set-Offline-Mode($Flag) { Write-Verbose 'Perform Set-Offline-Mode' switch ($Flag) { 'enable' { $Script:GVM_FORCE_OFFLINE = $true; Write-Output 'Forced offline mode enabled.' } 'disable' { $Script:GVM_FORCE_OFFLINE = $false; $Script:GVM_ONLINE = $true; Write-Output 'Online mode re-enabled!' } default { throw "Stop! $Flag is not a valid offline offline mode." } } } function Flush-Cache($DataType) { Write-Verbose 'Perform Flush-Cache' switch ($DataType) { 'candidates' { if ( Test-Path $Script:PGVM_CANDIDATES_PATH ) { Remove-Item $Script:PGVM_CANDIDATES_PATH Write-Output 'Candidates have been flushed.' } else { Write-Warning 'No candidate list found so not flushed.' } } 'broadcast' { if ( Test-Path $Script:PGVM_BROADCAST_PATH ) { Remove-Item $Script:PGVM_BROADCAST_PATH Write-Output 'Broadcast have been flushed.' } else { Write-Warning 'No prior broadcast found so not flushed.' } } 'version' { if ( Test-Path $Script:GVM_API_VERSION_PATH ) { Remove-Item $Script:GVM_API_VERSION_PATH Write-Output 'Version Token have been flushed.' } else { Write-Warning 'No prior Remote Version found so not flushed.' } } 'archives' { Cleanup-Directory $Script:PGVM_ARCHIVES_PATH } 'temp' { Cleanup-Directory $Script:PGVM_TEMP_PATH } 'tmp' { Cleanup-Directory $Script:PGVM_TEMP_PATH } default { throw 'Stop! Please specify what you want to flush.' } } } function Show-Help() { Write-Output @" Usage: gvm [version] gvm offline commands: install or i [version] uninstall or rm list or ls use or u [version] default or d [version] current or c [candidate] version or v broadcast or b help or h offline selfupdate [-Force] flush candidate : $($Script:GVM_CANDIDATES -join ', ') version : where optional, defaults to latest stable if not provided eg: gvm install groovy "@ } ================================================ FILE: GetPoshGvm.ps1 ================================================ <# Paragon for the installation script is PsGet #> function Install-Posh-Gvm() { $poshGvmZipUrl = 'https://github.com/flofreud/posh-gvm/archive/master.zip' $poshGvmPath = Find-Module-Location try { # create temp dir $tempDir = [guid]::NewGuid().ToString() $tempDir = Join-Path -Path $env:TEMP -ChildPath $tempDir New-Item -ItemType Directory $tempDir | Out-Null # download current version $poshGvmZip = "$tempDir\posh-gvm-master.zip" Write-Output "Downloading posh-gvm from $poshGvmZipUrl" $client = (New-Object Net.WebClient) $client.Proxy.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $client.DownloadFile($poshGvmZipUrl, $poshGvmZip) # unzip archive $shell = New-Object -com shell.application $shell.namespace($tempDir).copyhere($shell.namespace($poshGvmZip).items(), 0x14) # check if unzip successfully if ( Test-Path "$tempDir\posh-gvm-master" ) { if ( !(Test-Path $poshGvmPath) ) { New-Item -ItemType Directory $poshGvmPath | Out-Null } Copy-Item "$tempDir\posh-gvm-master\*" $poshGvmPath -Force -Recurse Write-Output "posh-gvm installed!" Write-Output "Please see https://github.com/flofreud/posh-gvm#usage for details to get started." Write-Warning "Execute 'Import-Module posh-gvm -Force' so changes take effect!" } else { Write-Warning 'Could not unzip archive containing posh-gvm. Most likely the archive is currupt. Please try to install again.' } } finally { # clear temp dir Remove-Item -Recurse -Force $tempDir } } function Find-Module-Location { $moduleDescriptor = Get-Module posh-gvm if ( $moduleDescriptor ) { return (Get-Item ($moduleDescriptor).Path).Directory.FullName } else { $modulePaths = @($Env:PSModulePath -split ';') # set module path to posh default $targetModulePath = Join-Path -Path ([Environment]::GetFolderPath('MyDocuments')) -ChildPath WindowsPowerShell\Modules # if its not use select the first defined if ( $modulePaths -inotcontains $targetModulePath ) { $targetModulePath = $modulePaths | Select-Object -Index 0 } return "$targetModulePath\posh-gvm" } } Install-Posh-Gvm ================================================ FILE: Init.Tests.ps1 ================================================ . .\Utils.ps1 . .\Init.ps1 . .\TestUtils.ps1 Describe 'Init-Posh-Gvm' { Context 'PGVM-Dir with only a grails folder' { Mock-PGVM-Dir Mock Check-JAVA-HOME -verifiable Mock Update-Candidates-Cache -verifiable Mock Init-Candidate-Cache -verifiable Mock Set-Env-Candidate-Version -verifiable -parameterFilter { $Candidate -eq 'grails' -and $Version -eq 'current' } Mock Set-Env-Candidate-Version -verifiable -parameterFilter { $Candidate -eq 'groovy' -and $Version -eq 'current' } Mock Set-Env-Candidate-Version -verifiable -parameterFilter { $Candidate -eq 'bla' -and $Version -eq 'current' } $Script:PGVM_CANDIDATES_PATH = "$Global:PGVM_DIR\.meta\candidates.txt" $Script:GVM_CANDIDATES = 'grails','groovy','bla' Init-Posh-Gvm It "creates .meta" { Test-Path "$Global:PGVM_DIR\.meta" | Should Be $true } It "creates grails" { Test-Path "$Global:PGVM_DIR\grails" | Should Be $true } It "creates groovy" { Test-Path "$Global:PGVM_DIR\groovy" | Should Be $true } It "creates bla" { Test-Path "$Global:PGVM_DIR\bla" | Should Be $true } It "calls methods to test JAVA_HOME, API version, loads candidate cache and setup env variables" { Assert-VerifiableMocks } Reset-PGVM-Dir } Context 'PGVM-Dir with only a grails folder and a candidates list' { Mock-PGVM-Dir Mock Check-JAVA-HOME -verifiable Mock Update-Candidates-Cache Mock Init-Candidate-Cache -verifiable Mock Set-Env-Candidate-Version -verifiable -parameterFilter { $Candidate -eq 'grails' -and $Version -eq 'current' } Mock Set-Env-Candidate-Version -verifiable -parameterFilter { $Candidate -eq 'groovy' -and $Version -eq 'current' } Mock Set-Env-Candidate-Version -verifiable -parameterFilter { $Candidate -eq 'bla' -and $Version -eq 'current' } $Script:PGVM_CANDIDATES_PATH = "$Global:PGVM_DIR\.meta\candidates.txt" New-Item -ItemType Directory "$Global:PGVM_DIR\.meta" | Out-Null New-Item -ItemType File $Script:PGVM_CANDIDATES_PATH | Out-Null $Script:GVM_CANDIDATES = 'grails','groovy','bla' Init-Posh-Gvm It "creates .meta" { Test-Path "$Global:PGVM_DIR\.meta" | Should Be $true } It "creates grails" { Test-Path "$Global:PGVM_DIR\grails" | Should Be $true } It "creates groovy" { Test-Path "$Global:PGVM_DIR\groovy" | Should Be $true } It "creates bla" { Test-Path "$Global:PGVM_DIR\bla" | Should Be $true } It "calls methods to test JAVA_HOME, API version, loads candidate cache and setup env variables" { Assert-VerifiableMocks } It "does not call update-candidates-cache" { Assert-MockCalled Update-Candidates-Cache 0 } Reset-PGVM-Dir } } Describe 'Check-JAVA-HOME' { Context 'JAVA_HOME is set' { Mock Get-Command Mock Test-Path { $true } -parameterFilter { $Path -eq 'env:Java_HOME' } Check-JAVA-HOME It "changes nothing" { Assert-MockCalled Get-Command 0 } } Context 'JAVA_HOME is not set but javac is on path' { $backupJAVAHOME = [Environment]::GetEnvironmentVariable('JAVA_HOME') Mock Test-Path { $false } -parameterFilter { $Path -eq 'env:Java_HOME' } Mock Get-Command { New-Object PSObject -Property @{ Path = (Get-Item 'C:\Windows\explorer.exe') } } -parameterFilter { $Name -eq 'javac' } $expectedNewJAVAHOME = 'C:\' Check-JAVA-HOME It "sets JAVA_HOME to javac parent" { [Environment]::GetEnvironmentVariable('JAVA_HOME') | Should Be $expectedNewJAVAHOME } [Environment]::SetEnvironmentVariable('JAVA_HOME', $backupJAVAHOME) } Context 'JAVA_HOME is not set and javax is not on path' { Mock Test-Path { $false } -parameterFilter { $Path -eq 'env:Java_HOME' } Mock Get-Command { throw 'error' } -parameterFilter { $Name -eq 'javac' } It "throws an error" { { Check-JAVA-HOME } | Should Throw } } } ================================================ FILE: Init.ps1 ================================================ #region Initialization function Init-Posh-Gvm() { Write-Verbose 'Init posh-gvm' $ErrorActionPreference = 'Stop' $ProgressPreference = 'SilentlyContinue' Check-JAVA-HOME # Check if $Global:PGVM_DIR is available, if not create it if ( !( Test-Path "$Global:PGVM_DIR\.meta" ) ) { New-Item -ItemType Directory "$Global:PGVM_DIR\.meta" | Out-Null } # Load candidates cache if ( ! (Test-Path $Script:PGVM_CANDIDATES_PATH) ) { Update-Candidates-Cache } Init-Candidate-Cache #Setup default paths Foreach ( $candidate in $Script:GVM_CANDIDATES ) { if ( !( Test-Path "$Global:PGVM_DIR\$candidate" ) ) { New-Item -ItemType Directory "$Global:PGVM_DIR\$candidate" | Out-Null } Set-Env-Candidate-Version $candidate 'current' } # Check if we can use unzip (which is much faster) Check-Unzip-On-Path } function Check-JAVA-HOME() { # Check for JAVA_HOME, If not set, try to interfere it if ( ! (Test-Path env:JAVA_HOME) ) { try { [Environment]::SetEnvironmentVariable('JAVA_HOME', (Get-Item (Get-Command 'javac').Path).Directory.Parent.FullName) } catch { throw "Could not find java, please set JAVA_HOME" } } } function Check-Unzip-On-Path() { try { Get-Command 'unzip.exe' | Out-Null $Script:UNZIP_ON_PATH = $true } catch { $Script:UNZIP_ON_PATH = $false } try { Get-Command '7z.exe' | Out-Null $Script:SEVENZ_ON_PATH = $true } catch { $Script:SEVENZ_ON_PATH = $false } } #endregion ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS ================================================ FILE: README.md ================================================ The code inside of this repository is broken. If you need the functionality of SDKMAN on Windows consider using Docker or WSL. ================================================ FILE: TabExpansion.ps1 ================================================ # Check if function TabExpansion already exists and backup existing version to # prevent breaking other TabExpansion implementations. # Taken from posh-git https://github.com/dahlbyk/posh-git/blob/master/GitTabExpansion.ps1#L297 $tabExpansionBackup = 'PoshGVM_DefaultTabExpansion' if (Test-Path Function:\TabExpansion) { Rename-Item Function:\TabExpansion $tabExpansionBackup -ErrorAction SilentlyContinue } function TabExpansion($line, $lastWord) { $lastBlock = [regex]::Split($line, '[|;]')[-1].TrimStart() switch -regex ($lastBlock) { # Execute gvm tab expansion for gvm command '^gvm (.*)' { gvmTabExpansion($lastBlock) } # Fall back on existing tab expansion default { if (Test-Path Function:\$tabExpansionBackup) { & $tabExpansionBackup $line $lastWord } } } } $Script:PGVM_TAB_COMMANDS = @('install','uninstall','rm','list','use','default','current','version','broadcast','help','offline','selfupdate','flush') function gvmTabExpansion($lastBlock) { if ( !($lastBlock -match '^gvm\s+(?\S+)?(? .*)?$') ) { return } $command = $Matches['cmd'] $arguments = $Matches['args'] if ( !($arguments) ) { # Try to complete the command return $Script:PGVM_TAB_COMMANDS | Where-Object { $_.StartsWith($command) } } $arguments = $arguments.TrimStart() # Help add correct parameters switch -regex ($command) { '^i(nstall)?' { gvmTabExpandion-Need-Candidate $command $arguments } '^(uninstall|rm)'{ gvmTabExpandion-Need-Candidate $command $arguments } '^(ls|list)' { gvmTabExpandion-Need-Candidate $command $arguments } '^u(se)?' { gvmTabExpandion-Need-Candidate $command $arguments } '^d(efault)?' { gvmTabExpandion-Need-Candidate $command $arguments } '^c(urrent)?' { gvmTabExpandion-Need-Candidate $command $arguments } '^offline' { gvmTabExpansion-Offline $arguments } '^flush' { gvmTabExpansion-Flush $arguments } default {} } } function gvmTabExpandion-Need-Candidate($Command, $LastBlock) { if ( !($LastBlock -match "^(?\S+)?(? .*)?$") ) { return } $candidate = $Matches['candidate'] $arguments = $Matches['args'] Init-Candidate-Cache if ( !($arguments) ) { # Try to complete the command return $Script:GVM_CANDIDATES | Where-Object { $_.StartsWith($candidate) } } if ( !($Script:GVM_CANDIDATES -contains $candidate) ) { return } $arguments = $arguments.TrimStart() # Help add correct parameters switch -regex ($command) { #'^i(nstall)?' { gvmTabExpandion-Need-Version $candidate $arguments } '^(uninstall|rm)'{ gvmTabExpandion-Need-Version $candidate $arguments } '^u(se)?' { gvmTabExpandion-Need-Version $candidate $arguments } '^d(efault)?' { gvmTabExpandion-Need-Version $candidate $arguments } default {} } } function gvmTabExpandion-Need-Version($Candidate, $LastBlock) { Get-Installed-Candidate-Version-List $Candidate | Where-Object { $_.StartsWith($LastBlock) } } function gvmTabExpansion-Offline($Arguments) { @('enable','disable') | Where-Object { ([string]$_).StartsWith($Arguments) } } function gvmTabExpansion-Flush($Arguments) { @('candidates','broadcast','archives','temp') | Where-Object { ([string]$_).StartsWith($Arguments) } } Export-ModuleMember TabExpansion Export-ModuleMember gvmTabExpansion ================================================ FILE: TestUtils.ps1 ================================================ . .\Utils.ps1 function Mock-Check-Candidate-Grails { Mock Check-Candidate-Present -verifiable -parameterFilter { $Candidate -eq 'grails' } } function Mock-Online { Mock Get-Online-Mode { return $true } } function Mock-Offline { Mock Get-Online-Mode { return $false } } function Mock-Grails-1.1.1-Locally-Available($Available) { if ( $Available ) { Mock Is-Candidate-Version-Locally-Available { return $true } -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } } else { Mock Is-Candidate-Version-Locally-Available { return $false } -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '1.1.1' } } } function Mock-Current-Grails-1.2 { Mock Get-Current-Candidate-Version { return 1.2 } -parameterFilter { $Candidate -eq 'grails' } } function Mock-No-Current-Grails { Mock Get-Current-Candidate-Version { return $null } -parameterFilter { $Candidate -eq 'grails' } } function Mock-Api-Call-Default-Grails-2.2 { Mock Invoke-API-Call { return 2.2 } -parameterFilter { $Path -eq 'candidates/grails/default' } } function Mock-Api-Call-Grails-1.1.1-Available($Available) { if ( $Available ) { Mock Invoke-API-Call { return $true } -parameterFilter { $Path -eq 'candidates/grails/1.1.1' } } else { Mock Invoke-API-Call { return $false } -parameterFilter { $Path -eq 'candidates/grails/1.1.1' } } } function Mock-PGVM-Dir { $Script:backup_PGVM_DIR = $Global:PGVM_DIR New-Item -ItemType Directory "TestDrive:.posh-gvm" | Out-Null $Global:PGVM_DIR = (Get-Item "TestDrive:.posh-gvm").FullName New-Item -ItemType Directory "$Global:PGVM_DIR\grails" | Out-Null } function Reset-PGVM-Dir { $link = "$Global:PGVM_DIR\grails\current" if ( Test-Path $link ) { (Get-Item $link).Delete() } $Global:PGVM_DIR = $Script:backup_PGVM_DIR } function Mock-Grails-Home($Version) { $Script:backup_GRAILS_HOME = [System.Environment]::GetEnvironmentVariable('GRAILS_HOME') [System.Environment]::SetEnvironmentVariable('GRAILS_HOME', "$Global:PGVM_DIR\grails\$Version") } function Reset-Grails-Home { [System.Environment]::SetEnvironmentVariable('GRAILS_HOME', $Script:backup_GRAILS_HOME) } function Mock-Dispatcher-Test([switch]$Offline) { Mock-PGVM-Dir $Script:GVM_FORCE_OFFLINE = $false $Script:FIRST_RUN = $false if ( !($Offline) ) { Mock Check-Available-Broadcast -verifiable Write-New-Version-Broadcast -verifiable } Mock Init-Candidate-Cache -verifiable } function Reset-Dispatcher-Test { Reset-PGVM-Dir } ================================================ FILE: Utils.Tests.ps1 ================================================ . .\Utils.ps1 . .\TestUtils.ps1 Describe 'Check-GVM-API-Version' { Context 'API offline' { $Script:GVM_AVAILABLE = $true $Script:GVM_API_NEW_VERSION = $false Mock Get-GVM-API-Version Mock Invoke-API-Call { throw 'error' } -parameterFilter { $Path -eq 'app/Version' } Check-GVM-API-Version It 'the error handling set the app in offline mode' { $Script:GVM_AVAILABLE | Should be $false } It 'does not informs about new version' { $Script:GVM_API_NEW_VERSION | Should Be $false } } Context 'No new version' { $backup_Global_PGVM_AUTO_SELFUPDTE = $Global:PGVM_AUTO_SELFUPDATE $Global:PGVM_AUTO_SELFUPDATE = $true $Script:GVM_API_NEW_VERSION = $false Mock Get-GVM-API-Version { 1.2.2 } Mock Invoke-API-Call { 1.2.2 } -parameterFilter { $Path -eq 'app/Version' } Mock Invoke-Self-Update Check-GVM-API-Version It 'do nothing' { Assert-MockCalled Invoke-Self-Update 0 } It 'does not informs about new version' { $Script:GVM_API_NEW_VERSION | Should Be $false } $Global:PGVM_AUTO_SELFUPDATE = $backup_Global_PGVM_AUTO_SELFUPDTE } Context 'New version and no auto selfupdate' { $backup_Global_PGVM_AUTO_SELFUPDTE = $Global:PGVM_AUTO_SELFUPDATE $Global:PGVM_AUTO_SELFUPDATE = $false $Script:GVM_API_NEW_VERSION = $false Mock Get-GVM-API-Version { '1.2.2' } Mock Invoke-API-Call { '1.2.3' } -parameterFilter { $Path -eq 'app/Version' } Check-GVM-API-Version It 'informs about new version' { $Script:GVM_API_NEW_VERSION | Should Be $true } It 'write a warning about needed update' { Assert-VerifiableMocks } $Global:PGVM_AUTO_SELFUPDATE = $backup_Global_PGVM_AUTO_SELFUPDTE } Context 'New version and auto selfupdate' { $backup_Global_PGVM_AUTO_SELFUPDTE = $Global:PGVM_AUTO_SELFUPDATE $Global:PGVM_AUTO_SELFUPDATE = $true $Script:GVM_API_NEW_VERSION = $false Mock Get-GVM-API-Version { '1.2.2' } Mock Invoke-API-Call { '1.2.3' } -parameterFilter { $Path -eq 'app/Version' } Mock Invoke-Self-Update -verifiable Check-GVM-API-Version It 'updates self' { Assert-VerifiableMocks } It 'does not informs about new version' { $Script:GVM_API_NEW_VERSION | Should Be $false } $Global:PGVM_AUTO_SELFUPDATE = $backup_Global_PGVM_AUTO_SELFUPDTE } } Describe 'Check-Posh-Gvm-Version' { Context 'No new Version' { $backup_Global_PGVM_AUTO_SELFUPDTE = $Global:PGVM_AUTO_SELFUPDATE $Global:PGVM_AUTO_SELFUPDATE = $false $Script:PGVM_NEW_VERSION = $false Mock Is-New-Posh-GVM-Version-Available { $false } Mock Invoke-Self-Update Check-Posh-Gvm-Version It 'does not update itself' { Assert-MockCalled Invoke-Self-Update -Times 0 } It 'does not informs about new version' { $Script:PGVM_NEW_VERSION | Should Be $false } $Global:PGVM_AUTO_SELFUPDATE = $backup_Global_PGVM_AUTO_SELFUPDTE } Context 'New version and no auto selfupdate' { $backup_Global_PGVM_AUTO_SELFUPDTE = $Global:PGVM_AUTO_SELFUPDATE $Global:PGVM_AUTO_SELFUPDATE = $false $Script:PGVM_NEW_VERSION = $false Mock Is-New-Posh-GVM-Version-Available { $true } Mock Invoke-Self-Update Check-Posh-Gvm-Version It 'informs about new version' { $Script:PGVM_NEW_VERSION | Should Be $true } It 'does not update itself' { Assert-MockCalled Invoke-Self-Update -Times 0 } $Global:PGVM_AUTO_SELFUPDATE = $backup_Global_PGVM_AUTO_SELFUPDTE } Context 'New version and auto selfupdate' { $backup_Global_PGVM_AUTO_SELFUPDTE = $Global:PGVM_AUTO_SELFUPDATE $Global:PGVM_AUTO_SELFUPDATE = $true $Script:PGVM_NEW_VERSION = $false Mock Is-New-Posh-GVM-Version-Available { $true } Mock Invoke-Self-Update -verifiable Check-Posh-Gvm-Version It 'updates self' { Assert-VerifiableMocks } It 'does not informs about new version' { $Script:PGVM_NEW_VERSION | Should Be $false } $Global:PGVM_AUTO_SELFUPDATE = $backup_Global_PGVM_AUTO_SELFUPDTE } } Describe 'Is-New-Posh-GVM-Version-Available' { Context 'New version available' { $Script:PGVM_VERSION_SERVICE = 'blub' $Script:PGVM_VERSION_PATH = 'TestDrive:VERSION.txt' Set-Content $Script:PGVM_VERSION_PATH '1.1.1' Mock Invoke-RestMethod { '1.2.1' } -parameterFilter { $Uri -eq 'blub' } $result = Is-New-Posh-GVM-Version-Available It 'returns $true' { $result | Should Be $true } } Context 'No new version available' { $Script:PGVM_VERSION_SERVICE = 'blub' $Script:PGVM_VERSION_PATH = 'TestDrive:VERSION.txt' Set-Content $Script:PGVM_VERSION_PATH '1.1.1' Mock Invoke-RestMethod { '1.1.1' } -parameterFilter { $Uri -eq 'blub' } $result = Is-New-Posh-GVM-Version-Available It 'returns $false' { $result | Should Be $false } } Context 'Version service error' { $Script:PGVM_VERSION_SERVICE = 'blub' $Script:PGVM_VERSION_PATH = 'TestDrive:VERSION.txt' Set-Content $Script:PGVM_VERSION_PATH '1.1.1' Mock Invoke-RestMethod { throw 'error' } -parameterFilter { $Uri -eq 'blub' } $result = Is-New-Posh-GVM-Version-Available It 'returns $false' { $result | Should Be $false } } } Describe 'Get-GVM-API-Version' { Context 'No cached version' { $Script:GVM_API_VERSION_PATH = 'TestDrive:version.txt' It 'returns `$null' { Get-GVM-API-Version | Should Be $null } } Context 'No cached version' { $Script:GVM_API_VERSION_PATH = 'TestDrive:version.txt' Set-Content $Script:GVM_API_VERSION_PATH '1.1.1' It 'returns $null' { Get-GVM-API-Version | Should Be 1.1.1 } } } Describe 'Check-Available-Broadcast' { Context 'Last execution was online, still online' { $Script:GVM_ONLINE = $true $Script:GVM_AVAILABLE = $true Mock Get-GVM-API-Version { '1.2.3' } Mock Invoke-Broadcast-API-Call { 'Broadcast message' } Mock Handle-Broadcast -verifiable -parameterFilter { $Command -eq $null -and $Broadcast -eq 'Broadcast message' } Mock Write-Offline-Broadcast Mock Write-Online-Broadcast Check-Available-Broadcast It 'does not announce any mode changes' { Assert-MockCalled Write-Offline-Broadcast 0 Assert-MockCalled Write-Online-Broadcast 0 } It 'calls Handle-Broadcast' { Assert-VerifiableMocks } } Context 'Last execution was online, now offline' { $Script:GVM_ONLINE = $true $Script:GVM_AVAILABLE = $false Mock Get-GVM-API-Version { '1.2.4' } Mock Invoke-Broadcast-API-Call { $null } Mock Handle-Broadcast Mock Write-Offline-Broadcast Mock Write-Online-Broadcast Check-Available-Broadcast It 'does announce offline mode' { Assert-MockCalled Write-Offline-Broadcast 1 Assert-MockCalled Write-Online-Broadcast 0 } It 'does not call Handle-Broadcast' { Assert-MockCalled Handle-Broadcast 0 } } Context 'Last execution was offline, still offline' { $Script:GVM_ONLINE = $false $Script:GVM_AVAILABLE = $false Mock Get-GVM-API-Version { '1.2.4' } Mock Invoke-Broadcast-API-Call { $null } Mock Handle-Broadcast Mock Write-Offline-Broadcast Mock Write-Online-Broadcast Check-Available-Broadcast It 'does not announce any mode changes' { Assert-MockCalled Write-Offline-Broadcast 0 Assert-MockCalled Write-Online-Broadcast 0 } It 'does not call Handle-Broadcast' { Assert-MockCalled Handle-Broadcast 0 } } Context 'Last execution was offline, now online' { $Script:GVM_ONLINE = $false $Script:GVM_AVAILABLE = $true Mock Get-GVM-API-Version { '1.2.5' } Mock Invoke-Broadcast-API-Call { 'Broadcast message' } Mock Handle-Broadcast -verifiable -parameterFilter { $Command -eq $null -and $Broadcast -eq 'Broadcast message' } Mock Write-Offline-Broadcast Mock Write-Online-Broadcast Check-Available-Broadcast It 'does announce online mode' { Assert-MockCalled Write-Offline-Broadcast 0 Assert-MockCalled Write-Online-Broadcast 1 } It 'calls Handle-Broadcast' { Assert-VerifiableMocks } } } Describe 'Invoke-Self-Update' { Context 'Selfupdate will be triggered, no force, no new version' { Mock Update-Candidates-Cache -verifiable Mock Write-Output -verifiable Mock Is-New-Posh-GVM-Version-Available { $false } Mock Invoke-Posh-Gvm-Update Invoke-Self-Update It 'updates the candidate cache' { Assert-VerifiableMocks } It 'does not updates itself' { Assert-MockCalled Invoke-Posh-Gvm-Update -Times 0 } } Context 'Selfupdate will be triggered, no force, new version' { Mock Update-Candidates-Cache -verifiable Mock Write-Output -verifiable Mock Is-New-Posh-GVM-Version-Available { $true } Mock Invoke-Posh-Gvm-Update -verifiable Invoke-Self-Update It 'updates the candidate cache and version' { Assert-VerifiableMocks } } Context 'Selfupdate will be triggered, force, no new version' { Mock Update-Candidates-Cache -verifiable Mock Write-Output -verifiable Mock Is-New-Posh-GVM-Version-Available { $false } Mock Invoke-Posh-Gvm-Update -verifiable Invoke-Self-Update -Force $true It 'updates the candidate cache and version' { Assert-VerifiableMocks } } } Describe 'Check-Candidate-Present checks if candidate parameter is valid' { It 'throws an error if no candidate is provided' { { Check-Candidate-Present } | Should Throw } $Script:GVM_CANDIDATES = @('grails','groovy') It 'throws error if candidate unknown' { { Check-Candidate-Present java } | Should Throw } It 'throws no error if candidate known' { { Check-Candidate-Present groovy } | Should Not Throw } } Describe 'Check-Version-Present checks if version parameter is defined' { It 'throws an error if no candidate is provided' { { Check-Version-Present } | Should Throw } It 'throws no error if version provided' { { Check-Version-Present 2.1.3 } | Should Not Throw } } Describe 'Check-Candidate-Version-Available select or vadidates a version for a candidate' { Context 'When grails version 1.1.1 is locally available' { Mock-Check-Candidate-Grails Mock-Grails-1.1.1-Locally-Available $true $result = Check-Candidate-Version-Available grails 1.1.1 It 'check candidate parameter' { Assert-VerifiableMocks } It 'returns the 1.1.1' { $result | Should Be 1.1.1 } } Context 'When gvm is offline and the provided version is not locally available' { Mock-Check-Candidate-Grails Mock-Offline Mock-Grails-1.1.1-Locally-Available $false It 'throws an error' { { Check-Candidate-Version-Available grails 1.1.1 } | Should Throw } It 'check candidate parameter' { Assert-VerifiableMocks } } Context 'When gvm is offline and no version is provided but there is a current version' { Mock-Check-Candidate-Grails Mock-Offline Mock-Current-Grails-1.2 $result = Check-Candidate-Version-Available grails It 'check candidate parameter' { Assert-VerifiableMocks } It 'returns the current version' { $result | Should Be 1.2 } } Context 'When gvm is offline and no version is provided and no current version is defined' { Mock-Check-Candidate-Grails Mock-Offline Mock-No-Current-Grails It 'throws an error' { { Check-Candidate-Version-Available grails } | Should Throw } It 'check candidate parameter' { Assert-VerifiableMocks } } Context 'When gvm is online and no version is provided' { Mock-Check-Candidate-Grails Mock-Online Mock-Api-Call-Default-Grails-2.2 $result = Check-Candidate-Version-Available grails It 'the API default is returned' { $result | Should Be 2.2 } It 'check candidate parameter' { Assert-VerifiableMocks } } Context 'When gvm is online and the provided version is valid' { Mock-Check-Candidate-Grails Mock-Online Mock-Api-Call-Grails-1.1.1-Available $true $result = Check-Candidate-Version-Available grails 1.1.1 It 'returns the version' { $result | Should Be 1.1.1 } It 'check candidate parameter' { Assert-VerifiableMocks } } Context 'When gvm is online and the provided version is invalid' { Mock-Check-Candidate-Grails Mock-Online Mock-Api-Call-Grails-1.1.1-Available $false It 'throws an error' { { Check-Candidate-Version-Available grails 1.1.1 } | Should Throw } It 'check candidate parameter' { Assert-VerifiableMocks } } } Describe 'Get-Current-Candidate-Version reads the currently linked version' { Context 'When current is not defined' { Mock-PGVM-Dir It 'returns $null if current not defined' { Get-Current-Candidate-Version grails | Should Be $null } Reset-PGVM-DIR } Context 'When current is defined' { Mock-PGVM-Dir New-Item -ItemType Directory "$Global:PGVM_DIR\grails\2.2.2" | Out-Null Set-Junction-Via-Mklink "$Global:PGVM_DIR\grails\current" "$Global:PGVM_DIR\grails\2.2.2" It 'returns the liked version' { Get-Current-Candidate-Version grails | Should Be 2.2.2 } Reset-PGVM-Dir } } Describe 'Get-Env-Candidate-Version reads the version set in $Candidate-Home' { Context 'When GRAILS_HOME is set to a specific version' { Mock-PGVM-Dir New-Item -ItemType Directory "$Global:PGVM_DIR\grails\2.2.1" | Out-Null Mock-Grails-Home 2.2.1 It 'returns the set version' { Get-Env-Candidate-Version grails | Should Be 2.2.1 } Reset-Grails-Home Reset-PGVM-Dir } Context 'When GRAILS_HOME is set to current' { Mock-PGVM-Dir New-Item -ItemType Directory "$Global:PGVM_DIR\grails\2.2.1" | Out-Null Set-Junction-Via-Mklink "$Global:PGVM_DIR\grails\current" "$Global:PGVM_DIR\grails\2.2.1" Mock-Grails-Home current It 'returns the version linked to current' { Get-Env-Candidate-Version grails | Should Be 2.2.1 } Reset-Grails-Home Reset-PGVM-Dir } } Describe 'Check-Candidate-Version-Locally-Available throws error message if not available' { Context 'Version not available' { Mock-Grails-1.1.1-Locally-Available $false It 'throws an error' { { Check-Candidate-Version-Locally-Available grails 1.1.1 } | Should Throw } } Context 'Version is available' { Mock-Grails-1.1.1-Locally-Available $true It 'not throws any error' { { Check-Candidate-Version-Locally-Available grails 1.1.1 } | Should Not Throw } } } Describe 'Is-Candidate-Version-Locally-Available check the path exists' { Context 'No version provided' { it 'returns $false' { Is-Candidate-Version-Locally-Available grails | Should Be $false } } Context 'COC path for grails 1.1.1 is missing' { Mock-PGVM-Dir it 'returns $false' { Is-Candidate-Version-Locally-Available grails 1.1.1 | Should Be $false } Reset-PGVM-Dir } Context 'COC path for grails 1.1.1 exists' { Mock-PGVM-Dir New-Item -ItemType Directory "$Global:PGVM_DIR\grails\1.1.1" | Out-Null it 'returns $true' { Is-Candidate-Version-Locally-Available grails 1.1.1 | Should Be $true } Reset-PGVM-Dir } } Describe 'Get-Installed-Candidate-Version-List' { Context 'Version 1.1, 1.3.7 and 2.2.1 of grails installed' { Mock-PGVM-Dir New-Item -ItemType Directory "$Global:PGVM_DIR\grails\1.1" | Out-Null New-Item -ItemType Directory "$Global:PGVM_DIR\grails\1.3.7" | Out-Null New-Item -ItemType Directory "$Global:PGVM_DIR\grails\2.2.1" | Out-Null Set-Junction-Via-Mklink "$Global:PGVM_DIR\grails\current" "$Global:PGVM_DIR\grails\2.2.1" It 'returns list of installed versions' { Get-Installed-Candidate-Version-List grails | Should Be 1.1,1.3.7,2.2.1 } Reset-PGVM-Dir } } Describe 'Set-Env-Candidate-Version' { Context 'Env-Version of grails is current' { Mock-PGVM-Dir New-Item -ItemType Directory "$Global:PGVM_DIR\grails\1.3.7" | Out-Null New-Item -ItemType Directory "$Global:PGVM_DIR\grails\2.2.1" | Out-Null Set-Junction-Via-Mklink "$Global:PGVM_DIR\grails\current" "$Global:PGVM_DIR\grails\2.2.1" Mock-Grails-Home current $backupPATH = $env:Path Set-Env-Candidate-Version grails 1.3.7 It 'sets GRAILS_HOME' { $env:GRAILS_HOME -eq "$Global:PGVM_DIR\grails\1.3.7" } It 'extends the Path' { $env:Path -eq "$Global:PGVM_DIR\grails\1.3.7\bin" } $env:Path = $backupPATH Reset-Grails-Home Reset-PGVM-Dir } } Describe 'Set-Linked-Candidate-Version' { Context 'In a initialized PGVM-Dir' { Mock-PGVM-Dir Mock Set-Junction-Via-Mklink -verifiable -parameterFilter { $Candidate -eq 'grails' -and $Version -eq '2.2.1' } Set-Linked-Candidate-Version grails 2.2.1 It 'calls Set-Junction-Via-Mklink with the correct paths' { Assert-VerifiableMocks } Reset-PGVM-Dir } } Describe 'Set-Junction-Via-Mklink' { Context 'No junction for the link-path exists' { Mock-PGVM-Dir New-Item -ItemType Directory "$Global:PGVM_DIR\grails\1.3.7" | Out-Null Set-Junction-Via-Mklink "$Global:PGVM_DIR\grails\bla" "$Global:PGVM_DIR\grails\1.3.7" It 'creates a junction to the target location' { (Get-Junction-Target "$Global:PGVM_DIR\grails\bla").FullName -eq "$Global:PGVM_DIR\grails\1.3.7" } (Get-Item "$Global:PGVM_DIR\grails\bla").Delete() Reset-PGVM-Dir } Context 'A Junction for the link-path exists' { Mock-PGVM-Dir New-Item -ItemType Directory "$Global:PGVM_DIR\grails\1.3.7" | Out-Null New-Item -ItemType Directory "$Global:PGVM_DIR\grails\1.3.8" | Out-Null Set-Junction-Via-Mklink "$Global:PGVM_DIR\grails\bla" "$Global:PGVM_DIR\grails\1.3.8" Set-Junction-Via-Mklink "$Global:PGVM_DIR\grails\bla" "$Global:PGVM_DIR\grails\1.3.7" It 'creates a junction to the target location without errors' { (Get-Junction-Target "$Global:PGVM_DIR\grails\bla").FullName -eq "$Global:PGVM_DIR\grails\1.3.7" } (Get-Item "$Global:PGVM_DIR\grails\bla").Delete() Reset-PGVM-Dir } } Describe 'Get-Junction-Target' { Context 'Provided path is a junction' { Mock-PGVM-Dir New-Item -ItemType Directory "$Global:PGVM_DIR\grails\1.3.7" | Out-Null Set-Junction-Via-Mklink "$Global:PGVM_DIR\grails\bla" "$Global:PGVM_DIR\grails\1.3.7" It 'returns the item of the junction correctly' { (Get-Junction-Target "$Global:PGVM_DIR\grails\bla").FullName -eq "$Global:PGVM_DIR\grails\1.3.7" } (Get-Item "$Global:PGVM_DIR\grails\bla").Delete() Reset-PGVM-Dir } Context 'Provided path is no junction' { Mock-PGVM-Dir New-Item -ItemType Directory "$Global:PGVM_DIR\grails\1.3.7" | Out-Null It 'returns correctly a null object without exception' { Get-Junction-Target "$Global:PGVM_DIR\grails\1.3.7" -eq $null } Reset-PGVM-Dir } } Describe 'Get-Online-Mode check the state variables for GVM-API availablitiy and for force offline mode' { Context 'GVM-Api unavailable but may be connected' { $Script:GVM_AVAILABLE = $false $Script:GVM_FORCE_OFFLINE = $false It 'returns $false' { Get-Online-Mode | Should Be $false } } Context 'GVM-Api unavailable and may not be connected' { $Script:GVM_AVAILABLE = $false $Script:GVM_FORCE_OFFLINE = $true It 'returns $false' { Get-Online-Mode | Should Be $false } } Context 'GVM-Api is available and may not be connected' { $Script:GVM_AVAILABLE = $true $Script:GVM_FORCE_OFFLINE = $true It 'returns $false' { Get-Online-Mode | Should Be $false } } Context 'GVM-Api is available and may be connected' { $Script:GVM_AVAILABLE = $true $Script:GVM_FORCE_OFFLINE = $false It 'returns $true' { Get-Online-Mode | Should Be $true } } } Describe 'Check-Online-Mode throws an error when offline' { Context 'Offline' { Mock-Offline It 'throws an error' { { Check-Online-Mode } | Should Throw } } Context 'Online' { Mock-Online It 'throws no error' { { Check-Online-Mode } | Should Not Throw } } } Describe 'Invoke-API-Call helps doing calls to the GVM-API' { Context 'Successful API call only with API path' { $Script:PGVM_SERVICE = 'blub' Mock Invoke-RestMethod { 'called' } -parameterFilter { $Uri -eq 'blub/na/rock' } It 'returns the result from Invoke-RestMethod' { Invoke-API-Call 'na/rock' | Should Be 'called' } } Context 'Failed API call only with API path' { $Script:PGVM_SERVICE = 'blub' $Script:GVM_AVAILABLE = $true Mock Invoke-RestMethod { throw 'error' } -parameterFilter { $Uri -eq 'blub/na/rock' } Mock Check-Online-Mode -verifiable Invoke-API-Call 'na/rock' It 'sets GVM_AVAILABLE to false' { $Script:GVM_AVAILABLE | Should Be $false } It 'calls Check-Online-Mode which throws an error' { Assert-VerifiableMocks } } Context 'Failed API call with API path and IgnoreFailure' { $Script:PGVM_SERVICE = 'blub' $Script:GVM_AVAILABLE = $true Mock Invoke-RestMethod { throw 'error' } -parameterFilter { $Uri -eq 'blub/na/rock' } Mock Check-Online-Mode Invoke-API-Call 'na/rock' -IgnoreFailure It 'sets GVM_AVAILABLE to false' { $Script:GVM_AVAILABLE | Should Be $false } It 'do not call Check-Online-Mode' { Assert-MockCalled Check-Online-Mode 0 } } Context 'Successful API call with API path and FilePath' { $Script:PGVM_SERVICE = 'blub' Mock Invoke-RestMethod -verifiable -parameterFilter { $Uri -eq 'blub/na/rock' -and $OutFile -eq 'TestDrive:a.txt' } Invoke-API-Call 'na/rock' TestDrive:a.txt It 'calls Invoke-RestMethod with file path' { Assert-VerifiableMocks } } } Describe 'Cleanup-Directory' { Context 'Directory with subdirectories and files' { New-Item -ItemType Directory TestDrive:bla | Out-Null New-Item -ItemType Directory TestDrive:bla\a | Out-Null New-Item -ItemType Directory TestDrive:bla\b | Out-Null New-Item -ItemType File TestDrive:bla\c | Out-Null New-Item -ItemType File TestDrive:bla\a\a | Out-Null Mock Write-Output -verifiable -parameterFilter { $InputObject -eq '2 archive(s) flushed, freeing 0 MB' } Cleanup-Directory TestDrive:bla It 'Cleans the Test-Path file' { Test-Path TestDrive:bla | Should Be $False } It 'Write info to host' { Assert-VerifiableMocks } } } Describe 'Handle-Broadcast' { Context 'Cache broadcast message different than new broadcast' { Mock-PGVM-Dir $Script:PGVM_BROADCAST_PATH = "$Global:PGVM_DIR\broadcast.txt" Set-Content $Script:PGVM_BROADCAST_PATH 'Old Broadcast message' Mock Write-Output -verifiable -parameterFilter { $InputObject -eq 'New Broadcast message' } Handle-Broadcast list 'New Broadcast message' It 'outputs the broadcast message' { Assert-VerifiableMocks } It 'sets the new broadcast message in file' { Get-Content $Script:PGVM_BROADCAST_PATH | Should Be 'New Broadcast message' } Reset-PGVM-Dir } Context 'No cached broadcast message' { Mock-PGVM-Dir $Script:PGVM_BROADCAST_PATH = "$Global:PGVM_DIR\broadcast.txt" Mock Write-Output -verifiable -parameterFilter { $InputObject -eq 'New Broadcast message' } Handle-Broadcast list 'New Broadcast message' It 'outputs the broadcast message' { Assert-VerifiableMocks } It 'sets the new broadcast message in file' { Get-Content $Script:PGVM_BROADCAST_PATH | Should Be 'New Broadcast message' } Reset-PGVM-Dir } Context 'b do not print the new broadcast message' { Mock-PGVM-Dir $Script:PGVM_BROADCAST_PATH = "$Global:PGVM_DIR\broadcast.txt" Mock Write-Output -verifiable Handle-Broadcast b 'New Broadcast message' It 'no Broadcast' { Assert-MockCalled Write-Output 0 } It 'sets the new broadcast message in file' { Test-Path $Script:PGVM_BROADCAST_PATH | Should Be $false } Reset-PGVM-Dir } Context 'Broadcast do nOt print the new broadcast message' { Mock-PGVM-Dir $Script:PGVM_BROADCAST_PATH = "$Global:PGVM_DIR\broadcast.txt" Mock Write-Output -verifiable Handle-Broadcast broadcast 'New Broadcast message' It 'no Broadcast' { Assert-MockCalled Write-Output 0 } It 'sets the new broadcast message in file' { Test-Path $Script:PGVM_BROADCAST_PATH | Should Be $false } Reset-PGVM-Dir } Context 'selfupdate do not print the new broadcast message' { Mock-PGVM-Dir $Script:PGVM_BROADCAST_PATH = "$Global:PGVM_DIR\broadcast.txt" Mock Write-Output -verifiable Handle-Broadcast selfupdate 'New Broadcast message' It 'no Broadcast' { Assert-MockCalled Write-Output 0 } It 'sets the new broadcast message in file' { Test-Path $Script:PGVM_BROADCAST_PATH | Should Be $false } Reset-PGVM-Dir } Context 'flush do not print the new broadcast message' { Mock-PGVM-Dir $Script:PGVM_BROADCAST_PATH = "$Global:PGVM_DIR\broadcast.txt" Mock Write-Output -verifiable Handle-Broadcast flush 'New Broadcast message' It 'no Broadcast' { Assert-MockCalled Write-Output 0 } It 'sets the new broadcast message in file' { Test-Path $Script:PGVM_BROADCAST_PATH | Should Be $false } Reset-PGVM-Dir } } Describe 'Init-Candidate-Cache' { Context 'Candidate cache file does not exists' { Mock-PGVM-Dir $Script:PGVM_CANDIDATES_PATH = "$Global:PGVM_DIR\candidates.txt" It 'throws an error' { { Init-Candidate-Cache } | Should Throw } Reset-PGVM-Dir } Context 'Candidate cache file does exists' { Mock-PGVM-Dir $Script:PGVM_CANDIDATES_PATH = "$Global:PGVM_DIR\candidates.txt" Set-Content $Script:PGVM_CANDIDATES_PATH 'grails,groovy,test' $Script:GVM_CANDIDATES = $null Init-Candidate-Cache It 'sets `$Script:GVM_CANDIDATES' { $Script:GVM_CANDIDATEs | Should Be grails,groovy,test } Reset-PGVM-Dir } } Describe 'Update-Candidate-Cache' { Context 'Checks online mode and than get version and candidates from api' { Mock-PGVM-Dir $Script:GVM_API_VERSION_PATH = "$Global:PGVM_DIR\version.txt" $Script:PGVM_CANDIDATES_PATH = "$Global:PGVM_DIR\candidates.txt" Mock Check-Online-Mode -verifiable Mock Invoke-API-Call -verifiable -parameterFilter { $Path -eq 'app/version' -and $FileTarget -eq "$Global:PGVM_DIR\version.txt" } Mock Invoke-API-Call -verifiable -parameterFilter { $Path -eq 'candidates' -and $FileTarget -eq "$Global:PGVM_DIR\candidates.txt" } Update-Candidates-Cache It 'calls the Check-Online-Mode and two API paths' { Assert-VerifiableMocks } Reset-PGVM-Dir } } Describe 'Write-Offline-Version-List' { Context 'no versions of grails installed' { Mock Write-Output Mock Get-Current-Candidate-Version { $null } -parameterFilter { $Candidate -eq 'grails' } Mock Get-Installed-Candidate-Version-List { $null } -parameterFilter { $Candidate -eq 'grails' } Write-Offline-Version-List grails It 'Outputs 11 lines' { Assert-MockCalled Write-Output 9 } } Context 'Three versions of grails installed' { Mock Write-Output Mock Get-Current-Candidate-Version { 1.1.1 } -parameterFilter { $Candidate -eq 'grails' } Mock Get-Installed-Candidate-Version-List { 1.1.1,2.2.2,2.3.0 } -parameterFilter { $Candidate -eq 'grails' } Write-Offline-Version-List grails It 'Outputs 11 lines' { Assert-MockCalled Write-Output 11 } } } Describe 'Write-Version-List' { Context 'Three versions of grails installed' { Mock Write-Output Mock Get-Current-Candidate-Version { '1.1.1' } -parameterFilter { $Candidate -eq 'grails' } Mock Get-Installed-Candidate-Version-List { return '1.1.1','2.2.2','2.3.0' } -parameterFilter { $Candidate -eq 'grails' } Mock Invoke-API-Call { 'bla' } -parameterFilter { $Path -eq 'candidates/grails/list?platform=posh¤t=1.1.1&installed=1.1.1,2.2.2,2.3.0' } Write-Version-List grails It 'writes to host' { Assert-MockCalled Write-Output 1 } } } Describe 'Install-Local-Version' { Context 'LocalPath is no directory' { New-Item -ItemType File TestDrive:a.txt | Out-Null It 'throws an error' { { Install-Local-Version grails snapshot TestDrive:a.txt } | Should Throw } } Context 'LocalPath is valid' { New-Item -ItemType Directory TestDrive:Snapshot | Out-Null Mock Write-Output Mock Set-Junction-Via-Mklink -verifiable -parameterFilter { $Link -eq "$Global:PGVM_DIR\grails\snapshot" -and $Target -eq 'TestDrive:Snapshot' } Install-Local-Version grails snapshot TestDrive:Snapshot It 'creates junction for candidate version' { Assert-VerifiableMocks } } } Describe 'Install-Remote-Version' { Context 'Install of a valid version without local archive' { Mock-PGVM-Dir Mock Write-Output Mock Check-Online-Mode -verifiable $Script:PGVM_SERVICE = 'foobar' $Script:PGVM_ARCHIVES_PATH = "$Global:PGVM_DIR\archives" $Script:PGVM_TEMP_PATH = "$Global:PGVM_DIR\temp" $testFilePath = "$PSScriptRoot\test\grails-1.3.9.zip" Mock Download-File -verifiable { Copy-Item $testFilePath "$Script:PGVM_ARCHIVES_PATH\grails-1.3.9.zip" } -parameterFilter { $Url -eq 'foobar/download/grails/1.3.9?platform=posh' -and $TargetFile -eq "$Script:PGVM_ARCHIVES_PATH\grails-1.3.9.zip" } Install-Remote-Version grails 1.3.9 It 'downloads the archive' { Assert-VerifiableMocks } It 'install it correctly' { Test-Path "$Global:PGVM_DIR\grails\1.3.9\bin\grails" | Should be $true } Reset-PGVM-DIR } Context 'Install of a valid version with local archive' { Mock-PGVM-Dir Mock Write-Output Mock Download-File $Script:PGVM_ARCHIVES_PATH = "$Global:PGVM_DIR\archives" $Script:PGVM_TEMP_PATH = "$Global:PGVM_DIR\temp" New-Item -ItemType Directory $Script:PGVM_ARCHIVES_PATH | Out-Null Copy-Item "$PSScriptRoot\test\grails-1.3.9.zip" "$Script:PGVM_ARCHIVES_PATH\grails-1.3.9.zip" Install-Remote-Version grails 1.3.9 It 'does not download the archive again' { Assert-MockCalled Download-File 0 } It 'install it correctly' { Test-Path "$Global:PGVM_DIR\grails\1.3.9\bin\grails" | Should be $true } Reset-PGVM-DIR } Context 'Install of a currupt archive' { Mock-PGVM-Dir Mock Write-Output Mock Download-File $Script:PGVM_ARCHIVES_PATH = "$Global:PGVM_DIR\archives" $Script:PGVM_TEMP_PATH = "$Global:PGVM_DIR\temp" New-Item -ItemType Directory $Script:PGVM_ARCHIVES_PATH | Out-Null Copy-Item "$PSScriptRoot\test\grails-2.2.2.zip" "$Script:PGVM_ARCHIVES_PATH\grails-2.2.2.zip" It 'fails because of no unziped files' { { Install-Remote-Version grails 2.2.2 } | Should Throw } It 'does not download the archive again' { Assert-MockCalled Download-File 0 } Reset-PGVM-DIR } } ================================================ FILE: Utils.ps1 ================================================ function Write-Offline-Broadcast() { Write-Output @" ==== BROADCAST ================================================================= OFFLINE MODE ENABLED! Some functionality is now disabled. ================================================================================ "@ } function Write-Online-Broadcast() { Write-Output @" ==== BROADCAST ================================================================= ONLINE MODE RE-ENABLED! All functionality now restored. ================================================================================ "@ } function Write-New-Version-Broadcast() { if ( $Script:GVM_API_NEW_VERSION -or $Script:PGVM_NEW_VERSION ) { Write-Output @" ==== UPDATE AVAILABLE ========================================================== A new version is available. Please consider to execute: gvm selfupdate ================================================================================ "@ } } function Check-GVM-API-Version() { Write-Verbose 'Checking GVM-API version' try { $apiVersion = Get-GVM-API-Version $gvmRemoteVersion = Invoke-API-Call "app/version" if ( $gvmRemoteVersion -gt $apiVersion) { if ( $Global:PGVM_AUTO_SELFUPDATE ) { Invoke-Self-Update } else { $Script:GVM_API_NEW_VERSION = $true } } } catch { $Script:GVM_AVAILABLE = $false } } function Check-Posh-Gvm-Version() { Write-Verbose 'Checking posh-gvm version' if ( Is-New-Posh-GVM-Version-Available ) { if ( $Global:PGVM_AUTO_SELFUPDATE ) { Invoke-Self-Update } else { $Script:PGVM_NEW_VERSION = $true } } } function Get-Posh-Gvm-Version() { return Get-Content $Script:PGVM_VERSION_PATH } function Is-New-Posh-GVM-Version-Available() { try { $localVersion = (Get-Posh-Gvm-Version).Trim() $currentVersion = (Invoke-RestMethod $Script:PGVM_VERSION_SERVICE).Trim() Write-Verbose "posh-gvm version check $currentVersion > $localVersion = $($currentVersion -gt $localVersion)" return ( $currentVersion -gt $localVersion ) } catch { return $false } } function Get-GVM-API-Version() { if ( !(Test-Path $Script:GVM_API_VERSION_PATH) ) { return $null } return Get-Content $Script:GVM_API_VERSION_PATH } function Check-Available-Broadcast($Command) { $version = Get-GVM-API-Version if ( !( $version ) ) { return } $liveBroadcast = Invoke-Broadcast-API-Call Write-Verbose "Online-Mode: $Script:GVM_AVAILABLE" if ( $Script:GVM_ONLINE -and !($Script:GVM_AVAILABLE) ) { Write-Offline-Broadcast } elseif ( !($Script:GVM_ONLINE) -and $Script:GVM_AVAILABLE ) { Write-Online-Broadcast } $Script:GVM_ONLINE = $Script:GVM_AVAILABLE if ( $liveBroadcast ) { Handle-Broadcast $Command $liveBroadcast } } function Invoke-Broadcast-API-Call { try { $target = "$Script:PGVM_BROADCAST_SERVICE/broadcast/latest" Write-Verbose "Broadcast API call to: $target" return Invoke-RestMethod $target } catch { Write-Verbose "Could not reached broadcast API" $Script:GVM_AVAILABLE = $false return $null } } function Invoke-Self-Update($Force) { Write-Verbose 'Perform Invoke-Self-Update' Write-Output 'Update list of available candidates...' Update-Candidates-Cache $Script:GVM_API_NEW_VERSION = $false if ( $Force ) { Invoke-Posh-Gvm-Update } else { if ( Is-New-Posh-GVM-Version-Available ) { Invoke-Posh-Gvm-Update } } $Script:PGVM_NEW_VERSION = $false } function Invoke-Posh-Gvm-Update { Write-Output 'Update posh-gvm...' . "$psScriptRoot\GetPoshGvm.ps1" } function Check-Candidate-Present($Candidate) { if ( !($Candidate) ) { throw 'No candidate provided.' } if ( !($Script:GVM_CANDIDATES -contains $Candidate) ) { throw "Stop! $Candidate is no valid candidate!" } } function Check-Version-Present($Version) { if ( !($Version)) { throw 'No version provided.' } } function Check-Candidate-Version-Available($Candidate, $Version) { Check-Candidate-Present $Candidate $UseDefault = $false if ( !($Version) ) { Write-Verbose 'No version provided. Fallback to default version!' $UseDefault = $true } # Check locally elseif ( Is-Candidate-Version-Locally-Available $Candidate $Version ) { return $Version } # Check if offline if ( ! (Get-Online-Mode) ) { if ( $UseDefault ) { $Version = Get-Current-Candidate-Version $Candidate if ( $Version ) { return $Version } else { throw "Stop! No local default version for $Candidate and in offline mode." } } throw "Stop! $Candidate $Version is not available in offline mode." } if ( $UseDefault ) { Write-Verbose 'Try to get default version from remote' return Invoke-API-Call "candidates/$Candidate/default" } $VersionAvailable = Invoke-API-Call "candidates/$Candidate/$Version" if ( $VersionAvailable -eq 'valid' ) { return $Version } else { throw "Stop! $Version is not a valid $Candidate version." } } function Get-Current-Candidate-Version($Candidate) { $currentLink = "$Global:PGVM_DIR\$Candidate\current" $targetItem = Get-Junction-Target $currentLink if ($targetItem) { return $targetItem.Name } return $null } function Get-Junction-Target($linkPath) { if ( Test-Path $linkPath ) { try { $linkItem = Get-Item $linkPath if (Get-Member -InputObject $linkItem -Name "ReparsePoint") { return (Get-Item $linkItem.ReparsePoint.Target) } if (Get-Member -InputObject $linkItem -Name "Target") { return (Get-Item $linkItem.Target) } } catch { return $null } } return $null } function Get-Env-Candidate-Version($Candidate) { $envLink = [System.Environment]::GetEnvironmentVariable(([string]$Candidate).ToUpper() + "_HOME") if ( $envLink -match '(.*)current$' ) { Get-Current-Candidate-Version $Candidate } else { return (Get-Item $envLink).Name } } function Check-Candidate-Version-Locally-Available($Candidate, $Version) { if ( !(Is-Candidate-Version-Locally-Available $Candidate $Version) ) { throw "Stop! $Candidate $Version is not installed." } } function Is-Candidate-Version-Locally-Available($Candidate, $Version) { if ( $Version ) { return Test-Path "$Global:PGVM_DIR\$Candidate\$Version" } else { return $false } } function Get-Installed-Candidate-Version-List($Candidate) { return Get-ChildItem "$Global:PGVM_DIR\$Candidate" | ?{ $_.PSIsContainer -and $_.Name -ne 'current' } | Foreach { $_.Name } } function Set-Env-Candidate-Version($Candidate, $Version) { $candidateEnv = ([string]$candidate).ToUpper() + "_HOME" $candidateDir = "$Global:PGVM_DIR\$candidate" $candidateHome = "$candidateDir\$Version" $candidateBin = "$candidateHome\bin" if ( !([Environment]::GetEnvironmentVariable($candidateEnv) -eq $candidateHome) ) { [Environment]::SetEnvironmentVariable($candidateEnv, $candidateHome) } $env:PATH = "$candidateBin;$env:PATH" } function Set-Linked-Candidate-Version($Candidate, $Version) { $Link = "$Global:PGVM_DIR\$Candidate\current" $Target = "$Global:PGVM_DIR\$Candidate\$Version" Set-Junction-Via-Mklink $Link $Target } function Set-Junction-Via-Mklink($Link, $Target) { if ( Test-Path $Link ) { (Get-Item $Link).Delete() } Invoke-Expression -Command "cmd.exe /c mklink /J '$Link' '$Target'" | Out-Null } function Get-Online-Mode() { return $Script:GVM_AVAILABLE -and ! ($Script:GVM_FORCE_OFFLINE) } function Check-Online-Mode() { if ( ! (Get-Online-Mode) ) { throw 'This command is not available in offline mode.' } } function Invoke-API-Call([string]$Path, [string]$FileTarget, [switch]$IgnoreFailure) { try { $target = "$Script:PGVM_SERVICE/$Path" if ( $FileTarget ) { return Invoke-RestMethod $target -OutFile $FileTarget } return Invoke-RestMethod $target } catch { $Script:GVM_AVAILABLE = $false if ( ! ($IgnoreFailure) ) { Check-Online-Mode } else { return $null } } } function Cleanup-Directory($Path) { $dirStats = Get-ChildItem $Path -Recurse | Measure-Object -property length -sum Remove-Item -Force -Recurse $Path $count = $dirStats.Count $size = $dirStats.Sum/(1024*1024) Write-Output "$count archive(s) flushed, freeing $size MB" } function Handle-Broadcast($Command, $Broadcast) { $oldBroadcast = $null if (Test-Path $Script:PGVM_BROADCAST_PATH) { $oldBroadcast = (Get-Content $Script:PGVM_BROADCAST_PATH) -join "`n" Write-Verbose 'Old broadcast message loaded' } if ($oldBroadcast -ne $Broadcast -and !($Command -match 'b(roadcast)?') -and $Command -ne 'selfupdate' -and $Command -ne 'flush' ) { Write-Verbose 'Showing the new broadcast message' Set-Content $Script:PGVM_BROADCAST_PATH $Broadcast Write-Output $Broadcast } } function Init-Candidate-Cache() { if ( !(Test-Path $Script:PGVM_CANDIDATES_PATH) ) { throw 'Can not retrieve list of candidates' } $Script:GVM_CANDIDATES = (Get-Content $Script:PGVM_CANDIDATES_PATH).Split(',') Write-Verbose "Available candidates: $Script:GVM_CANDIDATES" } function Update-Candidates-Cache() { Write-Verbose 'Update candidates-cache from GVM-API' Check-Online-Mode Invoke-Api-Call 'app/version' $Script:GVM_API_VERSION_PATH Invoke-API-Call 'candidates' $Script:PGVM_CANDIDATES_PATH } function Write-Offline-Version-List($Candidate) { Write-Verbose 'Get version list from directory' Write-Output '------------------------------------------------------------' Write-Output "Offline Mode: only showing installed ${Candidate} versions" Write-Output '------------------------------------------------------------' Write-Output '' $current = Get-Current-Candidate-Version $Candidate $versions = Get-Installed-Candidate-Version-List $Candidate if ($versions) { foreach ($version in $versions) { if ($version -eq $current) { Write-Output " > $version" } else { Write-Output " * $version" } } } else { Write-Output ' None installed!' } Write-Output '------------------------------------------------------------' Write-Output '* - installed ' Write-Output '> - currently in use ' Write-Output '------------------------------------------------------------' } function Write-Version-List($Candidate) { Write-Verbose 'Get version list from API' $current = Get-Current-Candidate-Version $Candidate $versions = (Get-Installed-Candidate-Version-List $Candidate) -join ',' Invoke-API-Call "candidates/$Candidate/list?platform=posh¤t=$current&installed=$versions" | Write-Output } function Install-Local-Version($Candidate, $Version, $LocalPath) { $dir = Get-Item $LocalPath if ( !(Test-Path $dir -PathType Container) ) { throw "Local installation path $LocalPath is no directory" } Write-Output "Linking $Candidate $Version to $LocalPath" $link = "$Global:PGVM_DIR\$Candidate\$Version" Set-Junction-Via-Mklink $link $LocalPath Write-Output "Done installing!" } function Install-Remote-Version($Candidate, $Version) { if ( !(Test-Path $Script:PGVM_ARCHIVES_PATH) ) { New-Item -ItemType Directory $Script:PGVM_ARCHIVES_PATH | Out-Null } $archive = "$Script:PGVM_ARCHIVES_PATH\$Candidate-$Version.zip" if ( Test-Path $archive ) { Write-Output "Found a previously downloaded $Candidate $Version archive. Not downloading it again..." } else { Check-Online-Mode Write-Output "`nDownloading: $Candidate $Version`n" Download-File "$Script:PGVM_SERVICE/download/$Candidate/$Version`?platform=posh" $archive } Write-Output "Installing: $Candidate $Version" # create temp dir if necessary if ( !(Test-Path $Script:PGVM_TEMP_PATH) ) { New-Item -ItemType Directory $Script:PGVM_TEMP_PATH | Out-Null } # unzip downloaded archive Unzip-Archive $archive $Script:PGVM_TEMP_PATH # check if unzip successfully if ( !(Test-Path "$Script:PGVM_TEMP_PATH\*-$Version") ) { throw "Could not unzip the archive of $Candidate $Version. Please delete archive from $Script:PGVM_ARCHIVES_PATH (or delete all with 'gvm flush archives'" } # move to target location # Move was replaced by copy and remove because of random access denied errors # when Unzip was done by via -com shell.application # Move-Item "$Script:PGVM_TEMP_PATH\*-$Version" "$Global:PGVM_DIR\$Candidate\$Version" Copy-Item "$Script:PGVM_TEMP_PATH\*-$Version" "$Global:PGVM_DIR\$Candidate\$Version" -Recurse Remove-Item "$Script:PGVM_TEMP_PATH\*-$Version" -Recurse -Force Write-Output "Done installing!" } function Unzip-Archive($Archive, $Target) { if ( $Script:SEVENZ_On_PATH ) { $zipProcess = Start-Process 7z.exe -ArgumentList "x -o`"$Target`" -y `"$Archive`"" -Wait -PassThru -NoNewWindow if ($zipProcess.ExitCode -ne 0) { Remove-Item $Target -Recurse -Force } } elseif ( $Script:UNZIP_ON_PATH ) { unzip.exe -oq $Archive -d $Target } else { # use the windows shell as general fallback (no working on Windows Server Core because there is no shell) $shell = New-Object -com shell.application $shell.namespace($Target).copyhere($shell.namespace($Archive).items(), 0x10) } } function Download-File($Url, $TargetFile) { <# Adepted from http://blogs.msdn.com/b/jasonn/archive/2008/06/13/downloading-files-from-the-internet-in-powershell-with-progress.aspx #> Write-Verbose "Try to download $Url with HttpWebRequest" $uri = New-Object "System.Uri" $Url $request = [System.Net.HttpWebRequest]::Create($uri) $request.set_Timeout(15000) $response = $request.GetResponse() $totalLength = [System.Math]::Floor($response.get_ContentLength()/1024) $responseStream = $response.GetResponseStream() $targetStream = New-Object -TypeName System.IO.FileStream -ArgumentList $targetFile, Create $buffer = new-object byte[] 10KB $count = $responseStream.Read($buffer,0,$buffer.length) $downloadedBytes = $count while ($count -gt 0) { if ($totalLength -lt 0) { $totalLength = [System.Math]::Floor($response.get_ContentLength()/1024) } [System.Console]::CursorLeft = 0 [System.Console]::Write("Downloaded {0}K of {1}K", [System.Math]::Floor($downloadedBytes/1024), $totalLength) $targetStream.Write($buffer, 0, $count) $count = $responseStream.Read($buffer,0,$buffer.length) $downloadedBytes = $downloadedBytes + $count } $targetStream.Flush() $targetStream.Close() $targetStream.Dispose() $responseStream.Dispose() Write-Output '' } ================================================ FILE: VERSION.txt ================================================ 1.3.1 ================================================ FILE: posh-gvm.psm1 ================================================ <# posh-gvm / POwerSHell Groovy enVironment Manager https://github.com/flofreud/posh-gvm Needed: - Powershell 3.0 (For Windows 7 install Windows Management Framework 3.0) #> #region Config if ( !(Test-Path Variable:Global:PGVM_DIR) ) { $Global:PGVM_DIR = "$env:USERPROFILE\.posh_gvm" } if ( !(Test-Path Variable:Global:PGVM_AUTO_ANSWER) ) { $Global:PGVM_AUTO_ANSWER = $false } if ( !(Test-Path Variable:Global:PGVM_AUTO_SELFUPDATE) ) { $Global:PGVM_AUTO_SELFUPDATE = $false } $Script:PGVM_INIT = $false $Script:PGVM_SERVICE = 'https://api.sdkman.io' $Script:PGVM_BROADCAST_SERVICE = 'https://api.sdkman.io/2' $Script:GVM_BASE_VERSION = '1.3.13' $Script:PGVM_CANDIDATES_PATH = "$Global:PGVM_DIR\.meta\candidates.txt" $Script:PGVM_BROADCAST_PATH = "$Global:PGVM_DIR\.meta\broadcast.txt" $Script:GVM_API_VERSION_PATH = "$Global:PGVM_DIR\.meta\version.txt" $Script:PGVM_ARCHIVES_PATH = "$Global:PGVM_DIR\.meta\archives" $Script:PGVM_TEMP_PATH = "$Global:PGVM_DIR\.meta\tmp" $Script:GVM_API_NEW_VERSION = $false $Script:PGVM_NEW_VERSION = $false $Script:PGVM_VERSION_PATH = "$psScriptRoot\VERSION.txt" $Script:PGVM_VERSION_SERVICE = "https://raw.githubusercontent.com/flofreud/posh-gvm/master/VERSION.txt" $Script:GVM_AVAILABLE = $true $Script:GVM_ONLINE = $true $Script:GVM_FORCE_OFFLINE = $false $Script:GVM_CANDIDATES = $null $Script:FIRST_RUN = $true $Script:UNZIP_ON_PATH = $false #endregion Push-Location $psScriptRoot . .\Utils.ps1 . .\Commands.ps1 . .\Init.ps1 . .\TabExpansion.ps1 Pop-Location Init-Posh-Gvm Export-ModuleMember 'gvm'