Private/EnvTools.ps1

function Write-EnvModificationLog{
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [ValidateSet('User','Process','Machine')]
        [string]$Level,
        [Parameter(Mandatory)]
        [ValidateSet('Remove','Add','Maintain','Not Add','Not Remove')]
        [string]$Type,
        [string]$Path='' # $null will be converted to empty string
    )
    $message = "Try to $($Type.ToLower()) '$Path' in '$Level' level `$Env:PATH."
    Write-VerboseLog $message -Verbose
}
function Assert-ValidLevel4EnvTools{
    [CmdletBinding()]
    [OutputType([System.Boolean])]
    param(
        [string]$Level
    )
    if ($Level -notin @('User','Process','Machine')){
        throw "The arg `$Level should be one of 'User','Process','Machine', not $Level."
    }elseif (($Level -eq 'Machine') -and (Test-Platform 'Windows')){
        Assert-AdminPermission
    }else{
        if (((Test-Platform 'Wsl2') -or (Test-Platform 'Linux'))`
            -and ($Level -in @('User','Machine'))){
            Write-VerboseLog  "The 'User' or 'Machine' level `$Env:PATH in current platform, $($PSVersionTable.Platform), are not supported. They can be get or set but this means nothing."
        }
    }
}

function Test-EnvPathExist{
<#
.DESCRIPTION
    Test if the `Path` is `existing` or not `empty` or not `$null`.
    Show corresonding logs.

.OUTPUTS
    $true: if the `Path` is `existing` and not `empty` and not `$null`.
    $false: if the `Path` is not `existing` or is `empty` or `$null`.
#>

    [CmdletBinding()]
    [OutputType([System.Boolean])]
    param(
        [Parameter(Mandatory)]
        [string]$Level,
        [Parameter(Mandatory)]
        [AllowEmptyString()]
        [AllowNull()]
        [string]$Path,
        [switch]$SkipLevelCheck
    )
    if (-not $SkipLevelCheck){
        Assert-ValidLevel4EnvTools $Level
    }
    if ($Path -eq $null){
        Write-VerboseLog "The $Path in in '$Level' level `$Env:PATH is `$null."
        return $false
    }elseif ($Path -eq '') {
        Write-VerboseLog "The $Path in in '$Level' level `$Env:PATH is empty."
        return $false
    }elseif (-not (Test-Path -LiteralPath $Path)){
        Write-VerboseLog "The $Path in in '$Level' level `$Env:PATH is not exiting."
        return $false
    }else{
        return $true
    }
}
function Test-EnvPathNotDuplicated{
<#
.DESCRIPTION
    Test if the `Path` is `duplicated` in the `$Container`.
    Show corresonding logs.
.OUTPUTS
    $true: if the `Path` is not `duplicated` in the `$Container`.
    $false: if the `Path` is `duplicated` in the `$Container`.

#>

    [CmdletBinding()]
    [OutputType([System.Boolean])]
    param(
        [Parameter(Mandatory)]
        [string]$Level,
        [Parameter(Mandatory)]
        [string]$Path,
        [Parameter(Mandatory)]
        [AllowEmptyCollection()]
        [string[]]$Container,
        [switch]$SkipLevelCheck
    )
    if (-not $SkipLevelCheck){
        Assert-ValidLevel4EnvTools $Level
    }
    if ($Path -in $Container){
        Write-VerboseLog "The $Path in in '$Level' level `$Env:PATH is duplicated."
        return $false
    }else{
        return $true
    }
}

function Get-EnvPathAsSplit{
    [CmdletBinding()]
    [OutputType([System.Object[]])]
    param(
        [Parameter(Mandatory)]
        [string]$Level,
        [switch]$SkipLevelCheck
    )
    if (-not $SkipLevelCheck){
        Assert-ValidLevel4EnvTools $Level
    }
    if (Test-Platform 'Windows'){
        return @([Environment]::GetEnvironmentVariable('Path',$Level) -Split ';')

    }elseif (Test-Platform 'Wsl2'){

        return @([Environment]::GetEnvironmentVariable('PATH',$Level) -Split ':')

    }elseif (Test-Platform 'Linux'){
        return @([Environment]::GetEnvironmentVariable('PATH',$Level) -Split ':')

    }else{
        Write-VerboseLog  "The current platform, $($PSVersionTable.Platform), has not been supported yet."
        exit -1
    }
}

function Set-EnvPathBySplit{
<#
See https://learn.microsoft.com/zh-cn/powershell/scripting/learn/deep-dives/everything-about-shouldprocess?view=powershell-7.3 for ShouldProcess warnings given by PSScriptAnalyzer.
#>

    [CmdletBinding(SupportsShouldProcess)]
    param(
        [string[]]$Paths,
        [Parameter(Mandatory)]
        [string]$Level,
        [switch]$SkipLevelCheck
    )
    if (-not $SkipLevelCheck){
        Assert-ValidLevel4EnvTools $Level
    }

    if($PSCmdlet.ShouldProcess("$Level level `$Env:PATH","cover `{$Paths}` ")){
        if (Test-Platform 'Windows'){
            [Environment]::SetEnvironmentVariable('Path',$Paths -join ';',$Level)

        }elseif (Test-Platform 'Wsl2'){
            [Environment]::SetEnvironmentVariable('PATH',$Paths -join ':',$Level)

        }elseif (Test-Platform 'Linux'){
            [Environment]::SetEnvironmentVariable('PATH',$Paths -join ':',$Level)

        }else{
            Write-VerboseLog  "The current platform, $($PSVersionTable.Platform), has not been supported yet."
            exit -1
        }
    }
}
function Format-EnvPath{
<#
.DESCRIPTION
    Format all paths of `$Env:PATH in $Level Level:
        1. Remove the invalid (non-existent or empty or duplicated) items.
        2. Format the content of all items by `Format-FileSystemPath` function.
#>

    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$Level,
        [switch]$SkipLevelCheck
    )
    if (-not $SkipLevelCheck){
        Assert-ValidLevel4EnvTools $Level
    }
    $env_paths = Get-EnvPathAsSplit -Level $Level -SkipLevelCheck
    $out_buf = @()
    $counter = 0  # count the number of invalid path (`non-existent` or `empty` or `duplicated`)
    foreach ($item in $env_paths)
    {
        if (Test-EnvPathExist -Level $Level -Path $item -SkipLevelCheck){
            $item = Format-FileSystemPath -Path $item
            if (Test-EnvPathNotDuplicated -Level $Level -Path $item -Container $out_buf -SkipLevelCheck){
                $out_buf += $item
            }
            else{
                Write-EnvModificationLog -Level $Level -Type 'Remove' -Path $item
                $counter += 1
            }
        }else{
            Write-EnvModificationLog -Level $Level -Type 'Remove' -Path $item
            $counter += 1
        }

    }
    Set-EnvPathBySplit -Paths $out_buf -Level $Level -SkipLevelCheck
    Write-VerboseLog "Formating $Level level `$Env:PATH, $counter invalid(non-existent or empty or duplicated) items have been found and merged."
}