lib/CacheLocation.ps1

function Set-CacheLocation {
    <#
    .SYNOPSIS
        Points a User-scope environment variable at a new directory and migrates
        existing cache data into it when the new location is empty.
    #>

    [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')]
    param(
        [Parameter(Mandatory)]
        [string] $Name,

        [Parameter(Mandatory)]
        [string] $TargetRoot,

        [Parameter(Mandatory)]
        [string] $DefaultSource
    )

    $currentValue = [Environment]::GetEnvironmentVariable($Name, 'User')

    if ($currentValue -eq $TargetRoot) {
        Write-Status -Level Info -Message " [INFO] $Name is already set to $TargetRoot"
        return
    }

    $source = if ($currentValue) {
        $currentValue
    }
    else {
        [Environment]::ExpandEnvironmentVariables($DefaultSource)
    }

    if (Test-Path -Path $source -PathType Container) {
        if (-not (Test-Path -Path $TargetRoot -PathType Container)) {
            if ($PSCmdlet.ShouldProcess($TargetRoot, 'Create directory')) {
                New-Item -ItemType Directory -Path $TargetRoot -Force | Out-Null
            }
        }

        # Read target items only if it actually exists (under -WhatIf the
        # New-Item above is skipped, so the directory may not be there).
        # Use explicit assignment instead of an `if` expression because PS
        # unwraps the empty-array branch to $null, which then trips the
        # `.Count` access under StrictMode 3.
        $sourceItems = @(Get-ChildItem -Path $source -Force)
        $targetItems = @()
        if (Test-Path -Path $TargetRoot -PathType Container) {
            $targetItems = @(Get-ChildItem -Path $TargetRoot -Force)
        }

        if ($sourceItems.Count -gt 0 -and $targetItems.Count -eq 0) {
            if ($PSCmdlet.ShouldProcess("$source -> $TargetRoot", "Move $Name data")) {
                Write-Status -Level Info -Message " [INFO] Moving $Name data from $source to $TargetRoot..."
                $sourceItems | Move-Item -Destination $TargetRoot -Force
            }
        }
    }

    if ($PSCmdlet.ShouldProcess("$Name (User scope)", "Set to $TargetRoot")) {
        [Environment]::SetEnvironmentVariable($Name, $TargetRoot, 'User')
        Write-Status -Level Info -Message " [INFO] $Name -> $TargetRoot"
    }
}