diff --git a/src/ConvertTo-NixMode.ps1 b/src/ConvertTo-NixMode.ps1 new file mode 100644 index 0000000..916b88c --- /dev/null +++ b/src/ConvertTo-NixMode.ps1 @@ -0,0 +1,58 @@ +#!/usr/bin/env pwsh +$ErrorActionPreference = "Stop" +Set-StrictMode -Version Latest + + +<# +.SYNOPSIS + Converts a value to a strongly-typed [System.IO.UnixFileMode] enum value. +.DESCRIPTION + Converts a value to a strongly-typed [System.IO.UnixFileMode] enum value. +.EXAMPLE + ConvertTo-NixMode -FromOctal 755 +#> +function ConvertTo-NixMode() { + [CmdletBinding()] + [OutputType([System.IO.UnixFileMode])] + param( + [Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'FromOctal')] + [ValidateNotNullOrEmpty()] + [string] $FromOctal, + + [Parameter(Mandatory = $true, Position = 0, ParameterSetName = 'FromDecimal')] + [ValidateNotNullOrEmpty()] + [int] $FromDecimal + ) + Begin { + function Factor-EnumValue() { + [OutputType([System.IO.UnixFileMode])] + param( + [Parameter(Mandatory = $true)] + [int] + $Value + ) + $value = [int]$Value + $result = [System.IO.UnixFileMode]::None + + foreach ($enumValue in [System.Enum]::GetValues([System.IO.UnixFileMode])) { + if (($value -band $enumValue) -eq $enumValue) { + $result = $result -bor $enumValue + $value = $value -bxor $enumValue + } + } + + if ($value -ne 0) { + throw [System.ArgumentException]::new("Unable to interpret value '$FromDecimal' as a value of [System.IO.UnixFileMode].") + } else { + return $result + } + } + + if ($FromOctal) { + $FromDecimal = [Convert]::ToInt32($FromOctal, 8) + } + } + Process { + return (Factor-EnumValue $FromDecimal) + } +} diff --git a/src/Set-ItemNixMode.ps1 b/src/Set-ItemNixMode.ps1 index bb930ef..83ff418 100644 --- a/src/Set-ItemNixMode.ps1 +++ b/src/Set-ItemNixMode.ps1 @@ -9,12 +9,12 @@ if ($IsLinux) { [Parameter(Mandatory = $true)] [string[]] $Path, + [Parameter(Mandatory = $true)] - [System.IO.UnixFileMode] - $Mode + [ValidateScript({ ConvertTo-NixMode -FromOctal $_ })] + [string] $ModeOctal ) - [string] $modeInOctal = [Convert]::ToString([int]$Mode, 8) - Get-Item $Path | ForEach-Object { chmod $modeInOctal $_.FullName } | Out-Null + Get-Item $Path | ForEach-Object { chmod $ModeOctal $_.FullName } | Out-Null } } else { function Set-ItemNixMode() { diff --git a/test/ConvertTo-NixMode.Tests.ps1 b/test/ConvertTo-NixMode.Tests.ps1 new file mode 100644 index 0000000..a3cc650 --- /dev/null +++ b/test/ConvertTo-NixMode.Tests.ps1 @@ -0,0 +1,81 @@ +#!/usr/bin/env pwsh +#Requires -Modules "Pester" +$ErrorActionPreference = "Stop" +Set-StrictMode -Version Latest + + +BeforeAll { + $SutFile = Get-Item "$PSScriptRoot/../src/ConvertTo-NixMode.ps1" + $SutName = $SutFile.BaseName +} + +Describe "SUT file" { + It "should exist" { + $SutFile | Should -Exist + } + + It "should be sourceable" { + { . $SutFile.FullName } | Should -Not -Throw + } + + Context "when sourced" { + BeforeEach { + . $SutFile + } + + Describe "function" { + It "should be defined" { + Get-Command -Name $SutName -CommandType Function | Should -Not -BeNullOrEmpty + } + + Context "when invoked" { + Context "with no arguments" { + It "should throw" { + { & $SutName } | Should -Throw + } + } + + Context "via parameter" { + # single integer matching a UnixFileMode value + Context "single input is integer-equivalent [System.IO.UnixFileMode] value" { + It "should return the value as-is" { + $parameterValue = [int][Convert]::ToString([int][System.IO.UnixFileMode]::GroupExecute, 8) + $expectedResult = [System.IO.UnixFileMode]::GroupExecute + + $actualResult = ConvertTo-NixMode -FromOctal $parameterValue + + $actualResult | Should -BeOfType [System.IO.UnixFileMode] + $actualResult | Should -Be $expectedResult + } + } + + # single integer that should have been parsed as base8 + Context "single input is integer wrongly parsed as base10 instead of base8" { + It "should return the value converted" { + $parameterValue = [int]700 + $expectedResult = [System.IO.UnixFileMode]([Convert]::ToInt32('700', 8)) + + $actualResult = ConvertTo-NixMode -FromOctal $parameterValue + + $actualResult | Should -BeOfType [System.IO.UnixFileMode] + $actualResult | Should -Be $expectedResult + } + } + + # single integer string matching a UnixFileMode value as-is + Context "single input is an integer string matching a [System.IO.UnixFileMode] value as-is" { + It "should return the value as-is" { + $parameterValue = [Convert]::ToString([int][System.IO.UnixFileMode]::GroupExecute, 8) + $expectedResult = [System.IO.UnixFileMode]::GroupExecute + + $actualResult = ConvertTo-NixMode -FromOctal $parameterValue + + $actualResult | Should -BeOfType [System.IO.UnixFileMode] + $actualResult | Should -Be $expectedResult + } + } + } + } + } + } +}