<# .SYNOPSIS Downloads and installs the Gitea Tea CLI tool for Windows. .DESCRIPTION This script automatically downloads, verifies, and installs the Tea CLI (Gitea command-line tool). It supports automatic detection of the latest version, SHA256 checksum verification, and intelligent installation location based on administrator privileges. .PARAMETER TeaVersion Specifies the version of Tea to install. If not provided, the script will automatically fetch the latest version from the Gitea releases page. .PARAMETER Force Bypasses the overwrite confirmation prompt if Tea is already installed. .EXAMPLE .\download-tea.ps1 Automatically detects and installs the latest version of Tea. .EXAMPLE .\download-tea.ps1 -TeaVersion "0.11.1" Installs a specific version of Tea (v0.11.1). .EXAMPLE .\download-tea.ps1 -Force Installs the latest version and overwrites any existing installation without prompting. .EXAMPLE .\download-tea.ps1 -TeaVersion "0.11.1" -Force Installs version 0.11.1 and overwrites existing installation without prompting. .NOTES - Requires internet connection to download from https://gitea.com - Automatically detects system architecture (AMD64 or 386) - Installation location: * With Admin rights: C:\Program Files\tea * Without Admin rights: %LOCALAPPDATA%\Programs\tea - Automatically updates PATH environment variable - After installation, restart your terminal or reload PATH with: $env:Path = [System.Environment]::GetEnvironmentVariable("Path","User") + ";" + [System.Environment]::GetEnvironmentVariable("Path","Machine") .LINK https://gitea.com/gitea/tea #> # Parameters param( [string]$TeaVersion, [switch]$Force ) # 1. Determine version to install if (-not $TeaVersion) { Write-Host "No version specified. Fetching latest release..." try { # Fetch the releases page and parse HTML to find the latest version $releasePage = Invoke-WebRequest -Uri "https://gitea.com/gitea/tea/releases" -UseBasicParsing -ErrorAction Stop # Parse the HTML to find the latest version tag (format: /gitea/tea/releases/tag/v0.x.x) if ($releasePage.Content -match '/gitea/tea/releases/tag/v([\d.]+)') { $TeaVersion = $matches[1] Write-Host "Latest version found: v$TeaVersion" -ForegroundColor Green } else { Write-Error "Could not determine the latest version from the releases page." Write-Host "Please specify a version manually using -TeaVersion parameter." exit 1 } } catch { Write-Error "Failed to fetch latest version: $($_.Exception.Message)" Write-Host "Please specify a version manually using -TeaVersion parameter." exit 1 } } else { Write-Host "Using specified version: v$TeaVersion" } # 2. Define variables for the download # Detect system architecture (AMD64 = 64-bit, 386 = 32-bit) $Architecture = if ($env:PROCESSOR_ARCHITECTURE -eq "AMD64") { "amd64" } else { "386" } # Construct download URLs $DownloadUrl = "https://gitea.com/gitea/tea/releases/download/v$TeaVersion/tea-$TeaVersion-windows-$Architecture.exe" $ChecksumUrl = "https://gitea.com/gitea/tea/releases/download/v$TeaVersion/checksums.txt" # Determine installation directory based on admin privileges # Admin: Install to Program Files (system-wide) # Non-Admin: Install to user's AppData (user-specific) $IsAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) $InstallDir = if ($IsAdmin) { "C:\Program Files\tea" } else { "$env:LOCALAPPDATA\Programs\tea" } # Define file names and temp locations $FileName = "tea.exe" $TempFile = "$env:TEMP\tea-$TeaVersion.exe" $TempChecksum = "$env:TEMP\tea-checksums.txt" # 3. Check if file already exists if ((Test-Path -Path "$InstallDir\$FileName") -and -not $Force) { # Prompt user before overwriting existing installation $response = Read-Host "tea.exe already exists in $InstallDir. Overwrite? (Y/N)" if ($response -ne 'Y' -and $response -ne 'y') { Write-Host "Installation cancelled." exit 0 } } # 4. Create the installation directory if it doesn't exist Write-Host "Creating installation directory: $InstallDir" if (-not (Test-Path -Path $InstallDir)) { New-Item -Path $InstallDir -ItemType Directory -Force | Out-Null } # 5. Download the binary and checksum Write-Host "Downloading tea CLI v$TeaVersion for $Architecture..." try { # Download to temp location first for safety Invoke-WebRequest -Uri $DownloadUrl -OutFile $TempFile -UseBasicParsing -ErrorAction Stop Write-Host "Binary downloaded successfully." } catch { Write-Error "Failed to download the file. Please check the URL and version number. Error: $($_.Exception.Message)" # Cleanup temp files on failure Remove-Item -Path $TempFile -ErrorAction SilentlyContinue exit 1 } # Try to download checksum file for verification (optional but recommended) $checksumAvailable = $false try { Write-Host "Attempting to download checksum file..." Invoke-WebRequest -Uri $ChecksumUrl -OutFile $TempChecksum -UseBasicParsing -ErrorAction Stop $checksumAvailable = $true Write-Host "Checksum file downloaded." } catch { Write-Warning "Checksum file not available for this version. Skipping verification." } # 6. Verify checksum (if available) if ($checksumAvailable) { Write-Host "Verifying file integrity..." try { # Calculate SHA256 hash of downloaded file $downloadedHash = (Get-FileHash -Path $TempFile -Algorithm SHA256).Hash.ToLower() # Parse checksums.txt to find the hash for our specific file $expectedFileName = "tea-$TeaVersion-windows-$Architecture.exe" $checksumContent = Get-Content -Path $TempChecksum -Raw $expectedHash = $null # checksums.txt format is: "hash filename" foreach ($line in ($checksumContent -split "`n")) { if ($line -match "^([a-fA-F0-9]+)\s+$expectedFileName") { $expectedHash = $matches[1].ToLower() break } } if (-not $expectedHash) { Write-Warning "Could not find checksum for $expectedFileName in checksums.txt" $response = Read-Host "Continue without checksum verification? (Y/N)" if ($response -ne 'Y' -and $response -ne 'y') { Remove-Item -Path $TempFile -ErrorAction SilentlyContinue Remove-Item -Path $TempChecksum -ErrorAction SilentlyContinue exit 1 } } elseif ($downloadedHash -eq $expectedHash) { Write-Host "Checksum verification passed." -ForegroundColor Green } else { Write-Error "Checksum verification failed! Downloaded file may be corrupted or tampered with." Write-Error "Expected: $expectedHash" Write-Error "Got: $downloadedHash" Remove-Item -Path $TempFile -ErrorAction SilentlyContinue Remove-Item -Path $TempChecksum -ErrorAction SilentlyContinue exit 1 } } catch { Write-Warning "Could not verify checksum: $($_.Exception.Message)" $response = Read-Host "Continue without checksum verification? (Y/N)" if ($response -ne 'Y' -and $response -ne 'y') { Remove-Item -Path $TempFile -ErrorAction SilentlyContinue Remove-Item -Path $TempChecksum -ErrorAction SilentlyContinue exit 1 } } } # 7. Move file to installation directory try { Move-Item -Path $TempFile -Destination "$InstallDir\$FileName" -Force -ErrorAction Stop Write-Host "Installed to $InstallDir\$FileName" # Cleanup checksum file after successful installation Remove-Item -Path $TempChecksum -ErrorAction SilentlyContinue } catch { Write-Error "Failed to move file to installation directory: $($_.Exception.Message)" Remove-Item -Path $TempFile -ErrorAction SilentlyContinue Remove-Item -Path $TempChecksum -ErrorAction SilentlyContinue exit 1 } # 8. Add the directory to PATH Write-Host "" Write-Host "Updating PATH environment variable..." try { # Try Machine (system-wide) PATH first - requires Administrator privileges $machinePath = [Environment]::GetEnvironmentVariable("Path", "Machine") if ($machinePath -notlike "*$InstallDir*") { [Environment]::SetEnvironmentVariable("Path", "$machinePath;$InstallDir", "Machine") Write-Host "Added to system PATH (Machine level)." -ForegroundColor Green Write-Host "You may need to restart your terminal for changes to take effect." } else { Write-Host "Directory is already in system PATH." } } catch { Write-Warning "Could not modify System PATH (requires Administrator rights)." Write-Host "Attempting to add to User PATH instead..." # Fallback to User PATH - doesn't require Administrator privileges try { $userPath = [Environment]::GetEnvironmentVariable("Path", "User") if ($userPath -notlike "*$InstallDir*") { [Environment]::SetEnvironmentVariable("Path", "$userPath;$InstallDir", "User") Write-Host "Added to User PATH." -ForegroundColor Green Write-Host "You may need to restart your terminal for changes to take effect." } else { Write-Host "Directory is already in User PATH." } } catch { Write-Warning "Could not modify User PATH either. You may need to add '$InstallDir' to your PATH manually." } } # 9. Verification Write-Host "" Write-Host "Verification:" try { # Test the installation by running tea --version $version = & "$InstallDir\$FileName" --version 2>&1 Write-Host $version -ForegroundColor Green } catch { Write-Warning "Could not execute tea. PATH may not be updated in this session." } Write-Host "" Write-Host "Installation complete! Run 'tea login add' to start configuring your Gitea instance." -ForegroundColor Cyan Write-Host "Note: If 'tea' command is not found, restart your terminal or reload PATH with:" -ForegroundColor Yellow Write-Host ' $env:Path = [System.Environment]::GetEnvironmentVariable("Path","User") + ";" + [System.Environment]::GetEnvironmentVariable("Path","Machine")' -ForegroundColor Gray