Skip to content

Commit ce300f3

Browse files
committed
🐛 Adds Platform Guards Around UnixFileMode Enum
The UnixFileMode enum type is not defined before PowerShell 7.3 and/or .NET 7, (which our GitHub runners don't have yet.)
1 parent fb76541 commit ce300f3

File tree

4 files changed

+192
-45
lines changed

4 files changed

+192
-45
lines changed

src/ConvertTo-NixMode.ps1

Lines changed: 73 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,56 +3,87 @@ $ErrorActionPreference = "Stop"
33
Set-StrictMode -Version Latest
44

55

6-
<#
7-
.SYNOPSIS
8-
Converts a value to a strongly-typed [System.IO.UnixFileMode] enum value.
9-
.DESCRIPTION
10-
Converts a value to a strongly-typed [System.IO.UnixFileMode] enum value.
11-
.EXAMPLE
12-
ConvertTo-NixMode -FromOctal 755
13-
#>
14-
function ConvertTo-NixMode() {
15-
[CmdletBinding()]
16-
[OutputType([System.IO.UnixFileMode])]
17-
param(
18-
[Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'FromOctal')]
19-
[ValidateNotNullOrEmpty()]
20-
[string] $FromOctal,
6+
if ([Type]::GetType("System.IO.UnixFileMode")) {
7+
<#
8+
.SYNOPSIS
9+
Converts a value to a strongly-typed [System.IO.UnixFileMode] enum value.
10+
.DESCRIPTION
11+
Converts a value to a strongly-typed [System.IO.UnixFileMode] enum value.
12+
.EXAMPLE
13+
ConvertTo-NixMode -FromOctal 755
14+
#>
15+
function ConvertTo-NixMode() {
16+
[System.Runtime.Versioning.SupportedOSPlatform("net7.0")]
17+
[CmdletBinding()]
18+
[OutputType([System.IO.UnixFileMode])]
19+
param(
20+
[Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'FromOctal')]
21+
[ValidateNotNullOrEmpty()]
22+
[string] $FromOctal,
2123

22-
[Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'FromDecimal')]
23-
[ValidateNotNullOrEmpty()]
24-
[int] $FromDecimal
25-
)
26-
Begin {
27-
function Factor-EnumValue() {
28-
[OutputType([System.IO.UnixFileMode])]
29-
param(
30-
[Parameter(Mandatory = $true)]
31-
[int]
32-
$Value
33-
)
34-
$value = [int]$Value
35-
$result = [System.IO.UnixFileMode]::None
24+
[Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'FromDecimal')]
25+
[ValidateNotNullOrEmpty()]
26+
[int] $FromDecimal
27+
)
28+
Begin {
29+
function Factor-EnumValue() {
30+
[OutputType([System.IO.UnixFileMode])]
31+
param(
32+
[Parameter(Mandatory = $true)]
33+
[int]
34+
$Value
35+
)
36+
$value = [int]$Value
37+
$result = [System.IO.UnixFileMode]::None
3638

37-
foreach ($enumValue in [System.Enum]::GetValues([System.IO.UnixFileMode])) {
38-
if (($value -band $enumValue) -eq $enumValue) {
39-
$result = $result -bor $enumValue
40-
$value = $value -bxor $enumValue
39+
foreach ($enumValue in [System.Enum]::GetValues([System.IO.UnixFileMode])) {
40+
if (($value -band $enumValue) -eq $enumValue) {
41+
$result = $result -bor $enumValue
42+
$value = $value -bxor $enumValue
43+
}
44+
}
45+
46+
if ($value -ne 0) {
47+
throw [System.ArgumentException]::new("Unable to interpret value '$FromDecimal' as a value of [System.IO.UnixFileMode].")
48+
} else {
49+
return $result
4150
}
4251
}
4352

44-
if ($value -ne 0) {
45-
throw [System.ArgumentException]::new("Unable to interpret value '$FromDecimal' as a value of [System.IO.UnixFileMode].")
46-
} else {
47-
return $result
53+
if ($FromOctal) {
54+
$FromDecimal = [Convert]::ToInt32($FromOctal, 8)
4855
}
4956
}
50-
51-
if ($FromOctal) {
52-
$FromDecimal = [Convert]::ToInt32($FromOctal, 8)
57+
Process {
58+
return (Factor-EnumValue $FromDecimal)
5359
}
5460
}
55-
Process {
56-
return (Factor-EnumValue $FromDecimal)
61+
} else {
62+
<#
63+
.SYNOPSIS
64+
Converts a value to a strongly-typed [System.IO.UnixFileMode] enum value.
65+
.DESCRIPTION
66+
Converts a value to a strongly-typed [System.IO.UnixFileMode] enum value.
67+
.EXAMPLE
68+
ConvertTo-NixMode -FromOctal 755
69+
#>
70+
function ConvertTo-NixMode() {
71+
[System.Runtime.Versioning.SupportedOSPlatform("net7.0")]
72+
[CmdletBinding()]
73+
# [OutputType([System.IO.UnixFileMode])]
74+
param(
75+
[Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'FromOctal')]
76+
[ValidateNotNullOrEmpty()]
77+
[string] $FromOctal,
78+
79+
[Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'FromDecimal')]
80+
[ValidateNotNullOrEmpty()]
81+
[int] $FromDecimal
82+
)
83+
Begin {
84+
throw [System.PlatformNotSupportedException]::new()
85+
}
86+
Process {
87+
}
5788
}
5889
}

src/Set-ItemNixMode.ps1

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,38 @@ Set-StrictMode -Version Latest
55

66
if ($IsLinux) {
77
function Set-ItemNixMode() {
8+
[System.Runtime.Versioning.UnsupportedOSPlatform("windows")]
89
param(
910
[Parameter(Mandatory = $true)]
1011
[string[]]
1112
$Path,
1213

1314
[Parameter(Mandatory = $true)]
14-
[ValidateScript({ ConvertTo-NixMode -FromOctal $_ })]
15+
# [ValidateScript({ ConvertTo-NixMode -FromOctal $_ })]
1516
[string] $ModeOctal
1617
)
17-
Get-Item $Path | ForEach-Object { chmod $ModeOctal $_.FullName } | Out-Null
18+
DynamicParam {
19+
# Add the ValidateScript attribute to the ModeOctal parameter, but
20+
# only if the UnixFileMode type is available.
21+
if ([Type]::GetType("System.IO.UnixFileMode")) {
22+
$Attribute = [System.Management.Automation.ValidateScriptAttribute]::new(
23+
[ScriptBlock]::Create("ConvertTo-NixMode -FromOctal $_")
24+
)
25+
$RuntimeParameterDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
26+
$RuntimeParameterDictionary.Add(
27+
"ModeOctal",
28+
[System.Management.Automation.RuntimeDefinedParameter]::new(
29+
"ModeOctal",
30+
[string],
31+
[System.Collections.ObjectModel.Collection[System.Attribute]]::new($Attribute)
32+
)
33+
)
34+
return $RuntimeParameterDictionary
35+
}
36+
}
37+
Process {
38+
Get-Item $Path | ForEach-Object { chmod $ModeOctal $_.FullName } | Out-Null
39+
}
1840
}
1941
} else {
2042
function Set-ItemNixMode() {

test/ConvertTo-NixMode.Tests.ps1

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,15 @@ Describe "SUT file" {
2424
}
2525

2626
Describe "function" {
27+
BeforeDiscovery {
28+
$FileModeSettingNotSupported = $IsWindows -or ($null -eq [Type]::GetType("System.IO.UnixFileMode"))
29+
}
30+
2731
It "should be defined" {
2832
Get-Command -Name $SutName -CommandType Function | Should -Not -BeNullOrEmpty
2933
}
3034

31-
Context "when invoked" {
35+
Context "when invoked" -Skip:$FileModeSettingNotSupported {
3236
Context "with no arguments" {
3337
It "should throw" {
3438
{ & $SutName } | Should -Throw

test/Set-ItemNixMode.Tests.ps1

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
#!/usr/bin/env pwsh
2+
#Requires -Modules "Pester"
3+
$ErrorActionPreference = "Stop"
4+
Set-StrictMode -Version Latest
5+
6+
7+
BeforeAll {
8+
$SutFile = Get-Item "$PSScriptRoot/../src/Set-ItemNixMode.ps1"
9+
$SutName = $SutFile.BaseName
10+
}
11+
12+
Describe "SUT file" {
13+
It "should exist" {
14+
$SutFile | Should -Exist
15+
}
16+
17+
It "should be sourceable" {
18+
{ . $SutFile.FullName } | Should -Not -Throw
19+
}
20+
21+
Context "when sourced" {
22+
BeforeEach {
23+
. $SutFile
24+
}
25+
26+
Describe "function" {
27+
BeforeDiscovery {
28+
$FileModeSettingNotSupported = $IsWindows -or ($null -eq [Type]::GetType("System.IO.UnixFileMode"))
29+
}
30+
31+
It "should be defined" {
32+
Get-Command -Name $SutName -CommandType Function | Should -Not -BeNullOrEmpty
33+
}
34+
35+
Context "when invoked" -Skip:$FileModeSettingNotSupported {
36+
Context "with no arguments" {
37+
It "should throw" {
38+
{ & $SutName } | Should -Throw
39+
}
40+
}
41+
42+
Context "for an existing file" {
43+
BeforeEach {
44+
$targetFile = New-TemporaryFile
45+
}
46+
47+
AfterEach {
48+
Remove-Item $targetFile.FullName -Force
49+
}
50+
51+
Context "ModeOctal is 700" {
52+
It "should set the mode" {
53+
$modeOctalParameter = '700'
54+
[System.IO.UnixFileMode] $expectedMode = [System.IO.UnixFileMode]::OwnerRead -bor [System.IO.UnixFileMode]::OwnerWrite -bor [System.IO.UnixFileMode]::OwnerExecute
55+
56+
Set-ItemNixMode -Path $targetFile -ModeOctal $modeOctalParameter
57+
58+
$targetFile.Refresh()
59+
$targetFile.Mode | Should -Be $expectedMode
60+
}
61+
}
62+
63+
Context "ModeOctal is 555" {
64+
It "should set the mode" {
65+
$modeOctalParameter = '555'
66+
[System.IO.UnixFileMode] $expectedMode = [System.IO.UnixFileMode]::OwnerRead -bor [System.IO.UnixFileMode]::OwnerExecute -bor [System.IO.UnixFileMode]::GroupRead -bor [System.IO.UnixFileMode]::GroupExecute -bor [System.IO.UnixFileMode]::OthersRead -bor [System.IO.UnixFileMode]::OthersExecute
67+
68+
Set-ItemNixMode -Path $targetFile -ModeOctal $modeOctalParameter
69+
70+
$targetFile.Refresh()
71+
$targetFile.Mode | Should -Be $expectedMode
72+
}
73+
}
74+
75+
Context "ModeOctal is 644" {
76+
It "should set the mode" {
77+
$modeOctalParameter = '644'
78+
[System.IO.UnixFileMode] $expectedMode = [System.IO.UnixFileMode]::OwnerRead -bor [System.IO.UnixFileMode]::OwnerWrite -bor [System.IO.UnixFileMode]::GroupRead -bor [System.IO.UnixFileMode]::OthersRead
79+
80+
Set-ItemNixMode -Path $targetFile -ModeOctal $modeOctalParameter
81+
82+
$targetFile.Refresh()
83+
$targetFile.Mode | Should -Be $expectedMode
84+
}
85+
}
86+
}
87+
}
88+
}
89+
}
90+
}

0 commit comments

Comments
 (0)