Skip to content

Commit

Permalink
Shift dynamic positional parameters, fix #217
Browse files Browse the repository at this point in the history
  • Loading branch information
nightroman committed Mar 3, 2024
1 parent f8502cc commit b359090
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 46 deletions.
5 changes: 5 additions & 0 deletions Invoke-Build.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ if ($_.get_Count()) {
foreach($p in $_.get_Values()) {
if ($c -notcontains ($_ = $p.Name)) {
if ($r -contains $_) {throw "Script uses reserved parameter '$_'."}
foreach ($a in $p.Attributes) {
if ($a -is [System.Management.Automation.ParameterAttribute] -and $a.Position -ne 0x80000000) {
$a.Position += 2
}
}
${*}.DP.Add($_, (New-Object System.Management.Automation.RuntimeDefinedParameter $_, $p.ParameterType, $p.Attributes))
}
}
Expand Down
2 changes: 2 additions & 0 deletions Release-Notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## v5.10.6

Fix cryptic errors on unknown parameters, #217

Minor tweaks, new demo Tasks/Repeat2, etc.

`Show-BuildGraph.ps1`
Expand Down
46 changes: 0 additions & 46 deletions Tests/Fixed.test.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -490,52 +490,6 @@ task PreserveCheckpoint {
Remove-Item z.build.ps1
}

# Issue #152 (1). Also test the bootstrapping scenario.
# This used to fail on the second call of z.ps1.
task DoNotMakeScriptParametersNamed {
# self-invoking build script
Set-Content z.ps1 {
param(
[Parameter()]$Tasks
)
if (!$MyInvocation.ScriptName.EndsWith('Invoke-Build.ps1')) {
return Invoke-Build $Tasks $MyInvocation.MyCommand.Path @PSBoundParameters
}
task Test {}
}

# invoke the script twice with the task name
./z.ps1 Test
./z.ps1 Test

remove z.ps1
}

<#
Issue #152 (2). Test positional parameters.
Potential problem:
- `Task` and `P1` both have position 0.
- `File` and `P2` both have position 1.
Fortunate current behaviour:
PowerShell somehow does what we expect, shift positions of P1, P2, P3.
This may change in the future, so let at least cover this by test.
Workarounds for the future:
- Use `[CmdletBinding(PositionalBinding=$false)]` (PowerShell v3+) to enforce named parameters.
- Set parameter positions explicitly starting with 2 (0, 1 are consumed by Task, File).
#>
task PositionalParameters {
Set-Content z.build.ps1 {
param($P1, $P2, $P3)
task Parameters {"$P1|$P2|$P3"}
}

# invoke the script with 5 positional parameters
($r = Invoke-Build Parameters z.build.ps1 v1 v2 v3)
assert ($r -contains 'v1|v2|v3')

remove z.build.ps1
}

# Issue #183, introduce $OriginalLocation, where the build starts.
task OriginalLocation {
Set-Location $HOME
Expand Down
48 changes: 48 additions & 0 deletions Tests/Issues/152-positional-script-parameters/152.test.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@

# Issue #152 (1). Also test the bootstrapping scenario.
# This used to fail on the second call of z.ps1.
task DoNotMakeScriptParametersNamed {
# self-invoking build script
Set-Content z.ps1 {
param(
[Parameter()]$Tasks
)
if (!$MyInvocation.ScriptName.EndsWith('Invoke-Build.ps1')) {
return Invoke-Build $Tasks $MyInvocation.MyCommand.Path @PSBoundParameters
}
task Test {}
}

# invoke the script twice with the task name
./z.ps1 Test
./z.ps1 Test

remove z.ps1
}

<#
Issue #152 (2). Test positional parameters.
Potential problem:
- `Task` and `P1` both have position 0.
- `File` and `P2` both have position 1.
UPDATE: yes, it is a problem, see #217
Fortunate current behaviour:
PowerShell somehow does what we expect, shift positions of P1, P2, P3.
This may change in the future, so let at least cover this by test.
Workarounds for the future:
- Use `[CmdletBinding(PositionalBinding=$false)]` (PowerShell v3+) to enforce named parameters.
- Set parameter positions explicitly starting with 2 (0, 1 are consumed by Task, File).
UPDATE: This is used by #217 (shift +2)
#>
task PositionalParameters {
Set-Content z.build.ps1 {
param($P1, $P2, $P3)
task Parameters {"$P1|$P2|$P3"}
}

# invoke the script with 5 positional parameters
($r = Invoke-Build Parameters z.build.ps1 v1 v2 v3)
assert ($r -contains 'v1|v2|v3')

remove z.build.ps1
}
10 changes: 10 additions & 0 deletions Tests/Issues/217-bad-error-on-unknown-parameter/217.build.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<# https://github.com/nightroman/Invoke-Build/issues/217
#152 fixed one issue but added another, cryptic errors.
#217 shifts script parameters positions (+2) avoiding conflicts with IB Task and File.
#>

param(
$MyParam1 #! this parameter position 0 conflicts with IB Task
)

task .
9 changes: 9 additions & 0 deletions Tests/Issues/217-bad-error-on-unknown-parameter/217.test.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

task UnknownParameter {
try {
throw Invoke-Build -bar
}
catch {
equals "$_" "A parameter cannot be found that matches parameter name 'bar'."
}
}

0 comments on commit b359090

Please sign in to comment.