ani-cli-rs 0.10.3

Cross-platform Rust port of ani-cli with Anikoto providers and a reusable provider/playback library
Documentation
param(
    [string]$InstallDirectory = $(if ($env:ANI_CLI_RS_INSTALL_DIR) { $env:ANI_CLI_RS_INSTALL_DIR } else { Join-Path ([Environment]::GetFolderPath("UserProfile")) ".local\bin" }),
    [switch]$NoPathUpdate,
    [switch]$UseSetup
)

$ErrorActionPreference = "Stop"

function Get-Sha256Hash {
    param([Parameter(Mandatory = $true)][string]$Path)

    $stream = [System.IO.File]::OpenRead($Path)
    try {
        $sha256 = [System.Security.Cryptography.SHA256]::Create()
        try {
            return ([System.BitConverter]::ToString($sha256.ComputeHash($stream))).Replace("-", "")
        }
        finally {
            $sha256.Dispose()
        }
    }
    finally {
        $stream.Dispose()
    }
}

if ($env:ANI_CLI_RS_WAIT_FOR_PID) {
    Wait-Process -Id ([int]$env:ANI_CLI_RS_WAIT_FOR_PID) -ErrorAction SilentlyContinue
}
$repository = "vorlie/ani-cli-rs"
# ani-cli-rs currently publishes one Windows archive. Windows 11 on ARM64 can
# run this x64 build through its compatibility layer.
$target = "x86_64-pc-windows-msvc"

$headers = @{ Accept = "application/vnd.github+json"; "User-Agent" = "ani-cli-rs-installer" }
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/$repository/releases/latest" -Headers $headers
$version = $release.tag_name.TrimStart("v")
$assetName = if ($UseSetup) { "ani-cli-rs-$version-windows-x64-setup.exe" } else { "ani-cli-rs-$version-$target.zip" }
$asset = $release.assets | Where-Object name -eq $assetName | Select-Object -First 1
$checksumAsset = $release.assets | Where-Object name -eq "$assetName.sha256" | Select-Object -First 1
if (-not $asset -or -not $checksumAsset) {
    throw "The latest release does not contain $assetName and its checksum."
}

$temporaryDirectory = Join-Path ([System.IO.Path]::GetTempPath()) ("ani-cli-rs-" + [guid]::NewGuid())
New-Item -ItemType Directory -Force $temporaryDirectory | Out-Null
try {
    $downloadPath = Join-Path $temporaryDirectory $assetName
    $checksumPath = "$downloadPath.sha256"
    Invoke-WebRequest -Uri $asset.browser_download_url -Headers $headers -OutFile $downloadPath
    Invoke-WebRequest -Uri $checksumAsset.browser_download_url -Headers $headers -OutFile $checksumPath

    $expectedHash = ((Get-Content -LiteralPath $checksumPath -Raw).Trim() -split "\s+")[0]
    $actualHash = Get-Sha256Hash -Path $downloadPath
    if ($expectedHash -ne $actualHash) { throw "Checksum verification failed for $assetName." }

    if ($UseSetup) {
        $setupProcess = Start-Process -FilePath $downloadPath -Wait -PassThru
        if ($setupProcess.ExitCode -ne 0) {
            throw "The Windows setup program exited with code $($setupProcess.ExitCode)."
        }
    }
    else {
        $expandedDirectory = Join-Path $temporaryDirectory "expanded"
        Add-Type -AssemblyName System.IO.Compression.FileSystem
        [System.IO.Compression.ZipFile]::ExtractToDirectory($downloadPath, $expandedDirectory)
        $binary = Get-ChildItem -LiteralPath $expandedDirectory -Filter "ani-cli-rs.exe" -File -Recurse | Select-Object -First 1
        if (-not $binary) { throw "The release archive did not contain ani-cli-rs.exe." }

        New-Item -ItemType Directory -Force $InstallDirectory | Out-Null
        Copy-Item -LiteralPath $binary.FullName -Destination (Join-Path $InstallDirectory "ani-cli-rs.exe") -Force
    }
} finally {
    if (Test-Path -LiteralPath $temporaryDirectory) { Remove-Item -LiteralPath $temporaryDirectory -Recurse -Force }
}

if (-not $UseSetup -and -not $NoPathUpdate) {
    $userPath = [Environment]::GetEnvironmentVariable("Path", "User")
    $pathEntries = @($userPath -split ";" | Where-Object { $_ })
    if (-not ($pathEntries | Where-Object { $_.TrimEnd("\") -ieq $InstallDirectory.TrimEnd("\") })) {
        $newPath = (@($pathEntries) + $InstallDirectory) -join ";"
        [Environment]::SetEnvironmentVariable("Path", $newPath, "User")
        $env:Path = "$InstallDirectory;$env:Path"
        Write-Host "Added $InstallDirectory to the user PATH. Open a new terminal to use it there."
    }
}

if ($UseSetup) {
    Write-Host "ani-cli-rs $($release.tag_name) was installed through Windows Setup."
}
else {
    Write-Host "Installed ani-cli-rs $($release.tag_name) to $InstallDirectory\ani-cli-rs.exe"
}

if ($env:ANI_CLI_RS_DELETE_INSTALLER -eq "1" -and $PSCommandPath) {
    Remove-Item -LiteralPath $PSCommandPath -Force -ErrorAction SilentlyContinue
}