Internals.ps1

$script:PrecomputedVCSHashInEnvVar = $env:CI_CACH_PRECOMPUTED_HASH_ENV_VAR ?? "BUILD_VCS_NUMBER" # TC default
$script:DisableCheckCache = $env:CI_CACHE_DISABLE_CHECKS ?? $false
$script:DisableCaches = $env:CI_CACHE_DISABLE ?? $false
$script:CacheFilePattern = "ci_{0}.zip"

function ComputeLookupHash($Id, $FilePathsToHash) {
    $finalHash = $null

    if (($FilePathsToHash -ne @()) -and $FilePathsToHash) 
    {
        $hashKey = ""
        foreach ($path in $FilePathsToHash) {
            $files = Get-ChildItem -Path $path -Recurse -File
            foreach ($file in $files) {
                $hashKey += "$((Get-FileHash -Path $file -Algorithm SHA256).Hash)"
            }
        }

        $mystream = [IO.MemoryStream]::new([byte[]][char[]]$hashKey)
        $finalHash = (Get-FileHash -InputStream $mystream -Algorithm SHA256).Hash
    } 
    elseif (Test-Path "env:$($script:PrecomputedVCSHashInEnvVar)") {
        $finalHash = [System.Environment]::GetEnvironmentVariable($script:PrecomputedVCSHashInEnvVar, "User")
    }

    return $finalHash ? "$($Id)__$($finalHash)" : $Id
}

function SetContextVariableForKey($Id, $key) {
    $envVariableForKey = "$($Id)_HashKey"
    [System.Environment]::SetEnvironmentVariable($envVariableForKey, $key, "User")
}

function Save-CacheInternal {
    [CmdletBinding()]
    param (
        [ValidatePattern('[a-zA-Z_]+')]
        [Parameter(Mandatory=$true)]
        [string] $Id,
        [Parameter(Mandatory=$true)][string[]] $Paths,
        [string[]] $PathsToComputeHash = @(),
        [Parameter(Mandatory=$true)][scriptblock] $TestHandler,
        [Parameter(Mandatory=$true)][scriptblock] $SaveHandler,
        [int] $RepeatCount
    )

    $envVariableForKey = "$($Id)_HashKey"

    if ((-not ($PathsToComputeHash) -or ($null -eq $PathsToComputeHash) -or $PathsToComputeHash -eq @()) -and (Test-Path "env:$($envVariableForKey)")) {
        $key = [System.Environment]::GetEnvironmentVariable("$envVariableForKey", "User")
    } else {
        $key = ComputeLookupHash $Id $PathsToComputeHash
    }

    SetContextVariableForKey $Id $key

    $artifactKey = $script:CacheFilePattern -f $key

    $zipFile = Join-Path ([System.IO.Path]::GetTempPath()) $artifactKey

    Write-Host "Compressing all required folders..."
    Compress-Cache -Sources $Paths -ArchiveFile $zipFile

    if (-not(Test-Path $zipFile)) {
        Write-Error "$zipFile does not exist!"
        return $false
    }

    $result = $false
    $checkResult = (Redo-IfFailed -RepeatCount $RepeatCount -CodeBlock $TestHandler -Parameters $artifactKey)

    if ($checkResult) {
        Write-Host "Cache has been already available in storage"
        return $key
    } else {
        Write-Host "Uploading cache file: $zipFile..."
        $result = (Redo-IfFailed -RepeatCount $RepeatCount -CodeBlock $SaveHandler -Parameters $zipFile)
    }

    if ($result) {
        Write-Host "Cache has been successfuly uploaded"
        return $key
    } else {
        Write-Host "Cache upload failed. Check errors above"
        return $null
    }
}

function Restore-CacheInternal {
    [CmdletBinding()]
    param (
        [ValidatePattern('[a-zA-Z_]+')]
        [Parameter(Mandatory=$true)]
        [string] $Id,
        [string[]] $PathsToComputeHash = @(),
        [string] $RestoreHashKey,
        [string] $OutputPath,
        [Parameter(Mandatory=$true)][scriptblock] $RestoreHandler,
        [int] $RepeatCount
    )

    if ($script:DisableCaches -eq $true) {
        Write-Host "All caches have been disabled completely by configuration"
        return $null
    }

    if (-not($OutputPath)) {
        $OutputPath = "./"
    }

    if ($RestoreHashKey) {
        $key = $RestoreHashKey
    } else {
        $key = ComputeLookupHash $Id $PathsToComputeHash
    }

    SetContextVariableForKey $Id $key

    $artifactKey = $script:CacheFilePattern -f $key

    Write-Host "Downloading the cache file: $artifactKey"
    $result = (Redo-IfFailed -RepeatCount $RepeatCount -CodeBlock $RestoreHandler -Parameters $artifactKey)

    if ($result) {
        Write-Host "Cache has been downloaded"
        Write-Host "Expanding cache $artifactKey..."

        Expand-Cache -ArchiveFile $artifactKey -DestinationFolder $OutputPath
        return $key
    } else {
        Write-Host "Cache is not available (or request failed)"
        return $null
    }
}

function Test-CacheInternal {
    [CmdletBinding()]
    param (
        [ValidatePattern('[a-zA-Z_]+')]
        [Parameter(Mandatory=$true)]
        [string] $Id,
        [string[]] $PathsToComputeHash = @(),
        [Parameter(Mandatory=$true)][scriptblock] $TestHandler,
        [int] $RepeatCount
    )

    if ($script:DisableCheckCache -eq $true -or $script:DisableCaches -eq $true) {
        Write-Host "All caches have been disabled for check functionality in configuration"
        return $null
    }

    $key = ComputeLookupHash $Id $PathsToComputeHash

    SetContextVariableForKey $Id $key

    $artifactKey = $script:CacheFilePattern -f $key

    Write-Host "Testing existance of: $artifactKey..."
    $result = (Redo-IfFailed -RepeatCount $RepeatCount -CodeBlock $TestHandler -Parameters $artifactKey)

    if ($result) {
        Write-Host "Cache has been found"
        return $key
    } else {
        Write-Host "Cache is not available (or request failed)"
        return $null
    }
}