Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 22 additions & 43 deletions src/private/cli/GetNovaCliInvocationContext.ps1
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
function Get-NovaCliBaseInvocationData {
function Get-NovaCliResolvedInvocationContext {
[CmdletBinding()]
param(
[Parameter(Mandatory)][string]$Command,
[AllowEmptyCollection()][string[]]$Arguments = @(),
[Parameter(Mandatory)][hashtable]$CommonParameters,
[Parameter(Mandatory)][hashtable]$MutatingCommonParameters,
[Parameter(Mandatory)][string]$ModuleName,
[Parameter(Mandatory)][bool]$WhatIfEnabled
[Parameter(Mandatory)][bool]$WhatIfEnabled,
[Parameter(Mandatory)][bool]$CliConfirmEnabled,
[AllowNull()][pscustomobject]$HelpRequest = $null
)

return [pscustomobject]@{
Command = $Command
Arguments = @($Arguments)
CommonParameters = $CommonParameters
MutatingCommonParameters = $MutatingCommonParameters
IsHelpRequest = $null -ne $HelpRequest
HelpRequest = $HelpRequest
ModuleName = $ModuleName
WhatIfEnabled = $WhatIfEnabled
CliConfirmEnabled = $CliConfirmEnabled
}
}

function Get-NovaCliHelpInvocationContext {
function Get-NovaCliInvocationWhatIfState {
[CmdletBinding()]
param(
[Parameter(Mandatory)][pscustomobject]$HelpRequest,
[Parameter(Mandatory)][pscustomobject]$BaseInvocationData
[switch]$WhatIfEnabled,
[Parameter(Mandatory)][hashtable]$MutatingCommonParameters,
[switch]$RoutingWhatIfEnabled
)

return [pscustomobject]@{
Command = $HelpRequest.Command
Arguments = @()
CommonParameters = $BaseInvocationData.CommonParameters
MutatingCommonParameters = $BaseInvocationData.MutatingCommonParameters
IsHelpRequest = $true
HelpRequest = $HelpRequest
ModuleName = $BaseInvocationData.ModuleName
WhatIfEnabled = $BaseInvocationData.WhatIfEnabled
CliConfirmEnabled = $false
}
return $WhatIfEnabled.IsPresent -or $RoutingWhatIfEnabled.IsPresent -or $MutatingCommonParameters.ContainsKey('WhatIf')
}

function Get-NovaCliConfirmState {
function Get-NovaCliInvocationConfirmState {
[CmdletBinding()]
param(
[Parameter(Mandatory)][hashtable]$MutatingCommonParameters
Expand All @@ -50,27 +50,6 @@ function Get-NovaCliConfirmState {
return $cliConfirmEnabled
}

function Get-NovaCliRoutedInvocationContext {
[CmdletBinding()]
param(
[Parameter(Mandatory)][pscustomobject]$RoutingState,
[Parameter(Mandatory)][pscustomobject]$BaseInvocationData,
[Parameter(Mandatory)][bool]$CliConfirmEnabled
)

return [pscustomobject]@{
Command = $RoutingState.Command
Arguments = $RoutingState.Arguments
CommonParameters = $BaseInvocationData.CommonParameters
MutatingCommonParameters = $BaseInvocationData.MutatingCommonParameters
IsHelpRequest = $false
HelpRequest = $null
ModuleName = $BaseInvocationData.ModuleName
WhatIfEnabled = $BaseInvocationData.WhatIfEnabled
CliConfirmEnabled = $CliConfirmEnabled
}
}

function Get-NovaCliInvocationContext {
[CmdletBinding()]
param(
Expand All @@ -85,22 +64,22 @@ function Get-NovaCliInvocationContext {
Assert-NovaCliArgumentSyntax -Arguments (@($InvocationRequest.Command) + $normalizedArguments)
$helpRequest = Get-NovaCliHelpRequest -Command $InvocationRequest.Command -Arguments $normalizedArguments
$moduleName = $ExecutionContext.SessionState.Module.Name
$helpBaseInvocationData = Get-NovaCliBaseInvocationData -CommonParameters $commonParameters -MutatingCommonParameters $mutatingCommonParameters -ModuleName $moduleName -WhatIfEnabled:($WhatIfEnabled.IsPresent -or $mutatingCommonParameters.ContainsKey('WhatIf'))
$whatIfState = Get-NovaCliInvocationWhatIfState -WhatIfEnabled:$WhatIfEnabled -MutatingCommonParameters $mutatingCommonParameters

if ($null -ne $helpRequest) {
return Get-NovaCliHelpInvocationContext -HelpRequest $helpRequest -BaseInvocationData $helpBaseInvocationData
return Get-NovaCliResolvedInvocationContext -Command $helpRequest.Command -Arguments @() -CommonParameters $commonParameters -MutatingCommonParameters $mutatingCommonParameters -ModuleName $moduleName -WhatIfEnabled:$whatIfState -CliConfirmEnabled:$false -HelpRequest $helpRequest
}

$routingState = Get-NovaCliArgumentRoutingState -Command $InvocationRequest.Command -Arguments $normalizedArguments
$cliConfirmEnabled = Get-NovaCliConfirmState -MutatingCommonParameters $mutatingCommonParameters
$cliConfirmEnabled = Get-NovaCliInvocationConfirmState -MutatingCommonParameters $mutatingCommonParameters

if ( $routingState.ForwardedParameters.ContainsKey('Verbose')) {
$commonParameters.Verbose = $true
}

$mutatingCommonParameters = Merge-NovaCliParameterSet -BaseParameters $mutatingCommonParameters -AdditionalParameters $routingState.ForwardedParameters
$cliConfirmEnabled = $cliConfirmEnabled -or $routingState.CliConfirmEnabled
$routedBaseInvocationData = Get-NovaCliBaseInvocationData -CommonParameters $commonParameters -MutatingCommonParameters $mutatingCommonParameters -ModuleName $moduleName -WhatIfEnabled:($WhatIfEnabled.IsPresent -or $routingState.WhatIfEnabled -or $mutatingCommonParameters.ContainsKey('WhatIf'))
$whatIfState = Get-NovaCliInvocationWhatIfState -WhatIfEnabled:$WhatIfEnabled -MutatingCommonParameters $mutatingCommonParameters -RoutingWhatIfEnabled:$routingState.WhatIfEnabled

return Get-NovaCliRoutedInvocationContext -RoutingState $routingState -BaseInvocationData $routedBaseInvocationData -CliConfirmEnabled:$cliConfirmEnabled
return Get-NovaCliResolvedInvocationContext -Command $routingState.Command -Arguments $routingState.Arguments -CommonParameters $commonParameters -MutatingCommonParameters $mutatingCommonParameters -ModuleName $moduleName -WhatIfEnabled:$whatIfState -CliConfirmEnabled:$cliConfirmEnabled
}
17 changes: 1 addition & 16 deletions src/private/cli/InvokeNovaCliCommandRoute.ps1
Original file line number Diff line number Diff line change
@@ -1,18 +1,3 @@
function Get-NovaCliCommandHandler {
[CmdletBinding()]
param(
[Parameter(Mandatory)][hashtable]$CommandHandlerMap,
[Parameter(Mandatory)][string]$Command
)

$commandHandler = $CommandHandlerMap[$Command]
if ($null -eq $commandHandler) {
Stop-NovaOperation -Message "Unknown command: <$Command> | Use 'nova --help' to see available commands." -ErrorId 'Nova.Validation.UnknownCliCommand' -Category InvalidArgument -TargetObject $Command
}

return $commandHandler
}

function Confirm-NovaCliRoutedCommand {
[CmdletBinding()]
param(
Expand Down Expand Up @@ -156,7 +141,7 @@ function Invoke-NovaCliCommandRoute {
return Get-NovaCliHelp
}
default {
return Get-NovaCliCommandHandler -CommandHandlerMap @{} -Command $command
Stop-NovaOperation -Message "Unknown command: <$command> | Use 'nova --help' to see available commands." -ErrorId 'Nova.Validation.UnknownCliCommand' -Category InvalidArgument -TargetObject $command
}
}
}
45 changes: 40 additions & 5 deletions tests/CoverageGaps.Cli.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ Describe 'Coverage gaps for CLI and installed-version internals' {
}
ModuleName = 'NovaModuleTools'
WhatIfEnabled = $false
CliConfirmEnabled = $false
}
Mock Get-NovaCliCommandHelp {'package-help'}

Expand Down Expand Up @@ -212,14 +213,33 @@ Describe 'Coverage gaps for CLI and installed-version internals' {
}
}

It 'Get-NovaCliCommandHandler returns the mapped handler for a known command' {
It 'Invoke-NovaCliCommandRoute throws the stable unknown-command error for unmapped commands' {
InModuleScope $script:moduleName {
$expectedHandler = [pscustomobject]@{Name = 'publish-handler'}
$handlerMap = @{publish = $expectedHandler}
$invocationContext = [pscustomobject]@{
Command = 'banana'
Arguments = @()
CommonParameters = @{}
MutatingCommonParameters = @{}
IsHelpRequest = $false
HelpRequest = $null
ModuleName = 'NovaModuleTools'
WhatIfEnabled = $false
CliConfirmEnabled = $false
}

$result = Get-NovaCliCommandHandler -CommandHandlerMap $handlerMap -Command 'publish'
$thrown = $null
try {
Invoke-NovaCliCommandRoute -InvocationContext $invocationContext
}
catch {
$thrown = $_
}

$result | Should -Be $expectedHandler
$thrown | Should -Not -BeNullOrEmpty
$thrown.Exception.Message | Should -Be "Unknown command: <banana> | Use 'nova --help' to see available commands."
$thrown.FullyQualifiedErrorId | Should -Be 'Nova.Validation.UnknownCliCommand'
$thrown.CategoryInfo.Category | Should -Be ([System.Management.Automation.ErrorCategory]::InvalidArgument)
$thrown.TargetObject | Should -Be 'banana'
}
}

Expand Down Expand Up @@ -293,6 +313,21 @@ Describe 'Coverage gaps for CLI and installed-version internals' {
}
}

It 'Get-NovaCliInvocationContext strips raw Confirm from mutating parameters while preserving CLI confirm intent' {
InModuleScope $script:moduleName {
$invocationRequest = [pscustomobject]@{
Command = 'publish'
BoundParameters = @{Command = 'publish'; Arguments = @('--confirm'); Confirm = $true}
Arguments = @('--confirm')
}
$result = Get-NovaCliInvocationContext -InvocationRequest $invocationRequest

$result.Command | Should -Be 'publish'
$result.CliConfirmEnabled | Should -BeTrue
$result.MutatingCommonParameters.ContainsKey('Confirm') | Should -BeFalse
}
}

It 'Get-NovaCliArgumentRoutingState enables CLI confirmation only for supported mutating commands' {
InModuleScope $script:moduleName {
$supportedCommandList = @('build', 'test', 'package', 'deploy', 'bump', 'update', 'notification', 'publish', 'release')
Expand Down
Loading