Utils.ps1

function Compress-Cache {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true)]
        [string[]] $Sources,
        [Parameter(Mandatory=$true)]
        [string] $ArchiveFile
    )

    $files = @()

    foreach ($filePath in $Sources) {
        $fullPath = Join-Path $pwd $filePath
        $path = $fullPath
        $searchMode = [System.IO.SearchOption]::AllDirectories
        $searchPattern = "*"
        $leaf = Split-Path -Path $fullPath -Leaf

        if ($leaf.Contains("*")) {
            $searchMode = [System.IO.SearchOption]::TopDirectoryOnly
            $searchPattern = $leaf
            $path = Split-Path -Path $fullPath -Parent
        }

        $files += [System.IO.Directory]::GetFiles($path, $searchPattern, $searchMode)
    }

    $finalPath = $ArchiveFile

    if (-not([System.IO.Path]::IsPathRooted($finalPath))) {
        $finalPath = (Join-Path -Path $(Resolve-Path -Path ".") -ChildPath $finalPath)
    }

    if (Test-Path $finalPath) {
        Write-Warning "File already exists: $finalPath"
        return
    }

    Write-Host "Create new archive: $finalPath"
    $zip = [System.IO.Compression.ZipFile]::Open($finalPath, [System.IO.Compression.ZipArchiveMode]::Create)

    Write-Host "Appending $($files.Count) files..."

    foreach ($fname in $files) {
        $rname = $(Resolve-Path -Path $fname -Relative) -replace '\.\\',''
        $archiveEntry = $zip.CreateEntry($rname)
        $archiveEntryWriter = New-Object -TypeName System.IO.BinaryWriter $archiveEntry.Open()
        $archiveEntryWriter.Write([System.IO.File]::ReadAllBytes($fname))
        $archiveEntryWriter.Flush()
        $archiveEntryWriter.Close()
    }

    $zip.Dispose()
}

function Expand-Cache {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true)]
        [string] $ArchiveFile,
        [string] $DestinationFolder = "."   
    )

    $currentDir = $(Resolve-Path -Path ".")

    if (-not([System.IO.Path]::IsPathRooted($ArchiveFile))) {
        $ArchiveFile = (Join-Path -Path $currentDir -ChildPath $ArchiveFile)
    }
    if (-not([System.IO.Path]::IsPathRooted($DestinationFolder))) {
        $DestinationFolder = (Join-Path -Path $currentDir -ChildPath $DestinationFolder)
    }
    [System.IO.Compression.ZipFile]::ExtractToDirectory($ArchiveFile, $DestinationFolder, $true)
}

function Redo-IfFailed {
    [CmdletBinding()]
    param (
        [int] $RepeatCount,
        [ScriptBlock] $CodeBlock,
        $Parameters = @()
    )
    
    for ($currentCount = 1; $currentCount -le $RepeatCount; $currentCount++) {
        
        Write-Host "Sending request (attempt: #$currentCount)"

        try 
        {
            Invoke-Command $CodeBlock -ArgumentList $Parameters
            return $true
        } 
        catch 
        {
            $code = "$($_.Exception.Response.StatusCode.value__)"
            $message = $_.Exception.Message

            if (($code -eq "404") -or
                ($code -eq "401") -or
                ($code -eq "403") -or
                $message.StartsWith("CI_CACHE_NOT_FOUND")) {
                return $false
            }

            Write-Error $message
            Write-Host "Request result code:" $code
            Write-Host "Request result status:" $_.Exception.Response.StatusDescription

            Start-Sleep -Seconds ($currentCount * 5)
        }
    }

    return $false
}