forked from Gitlink/gitlink-cli
442 lines
12 KiB
PowerShell
442 lines
12 KiB
PowerShell
# GitLink CLI Windows 安装脚本
|
||
# 用法: powershell -NoProfile -ExecutionPolicy Bypass -File install.ps1
|
||
# 支持: .\install.ps1 -Version 0.1.0 -InstallDir "C:\GitLink"
|
||
|
||
param(
|
||
[string]$Version = "latest",
|
||
[string]$InstallDir = "$HOME\.gitlink-cli\bin",
|
||
[switch]$Help = $false,
|
||
[switch]$Uninstall = $false,
|
||
[switch]$ListVersions = $false,
|
||
[switch]$Debug = $false
|
||
)
|
||
|
||
$ErrorActionPreference = "Stop"
|
||
$REPO_OWNER = "Gitlink"
|
||
$REPO_NAME = "gitlink-cli"
|
||
$BINARY_NAME = "gitlink-cli"
|
||
$API_BASE = "https://www.gitlink.org.cn"
|
||
$SKILLS_DIR = "$HOME\.gitlink\skills"
|
||
|
||
# 颜色输出
|
||
function Info {
|
||
param([string]$msg)
|
||
Write-Host "[INFO] $msg" -ForegroundColor Green
|
||
}
|
||
|
||
function Warn {
|
||
param([string]$msg)
|
||
Write-Host "[WARN] $msg" -ForegroundColor Yellow
|
||
}
|
||
|
||
function ErrorMsg {
|
||
param([string]$msg)
|
||
Write-Host "[ERROR] $msg" -ForegroundColor Red
|
||
}
|
||
|
||
function Step {
|
||
param([string]$msg)
|
||
Write-Host "[STEP] $msg" -ForegroundColor Cyan
|
||
}
|
||
|
||
function DebugMsg {
|
||
param([string]$msg)
|
||
if ($Debug) {
|
||
Write-Host "[DEBUG] $msg" -ForegroundColor Blue
|
||
}
|
||
}
|
||
|
||
# 显示帮助
|
||
function Show-Help {
|
||
Write-Host @"
|
||
GitLink CLI Windows 安装脚本
|
||
|
||
用法:
|
||
.\install.ps1 [选项]
|
||
|
||
选项:
|
||
-Version <version> 指定版本 (默认: latest)
|
||
-InstallDir <path> 安装目录 (默认: $HOME\.gitlink-cli\bin)
|
||
-Uninstall 卸载
|
||
-ListVersions 列出可用版本
|
||
-Debug 显示调试信息
|
||
-Help 显示此帮助
|
||
|
||
示例:
|
||
# 安装最新版本
|
||
.\install.ps1
|
||
|
||
# 安装指定版本
|
||
.\install.ps1 -Version "0.1.0"
|
||
|
||
# 安装到指定目录
|
||
.\install.ps1 -InstallDir "C:\Tools\gitlink-cli"
|
||
|
||
# 列出可用版本
|
||
.\install.ps1 -ListVersions
|
||
|
||
# 卸载
|
||
.\install.ps1 -Uninstall
|
||
|
||
# 在线安装
|
||
powershell -NoProfile -ExecutionPolicy Bypass -Command "iex (irm https://www.gitlink.org.cn/Gitlink/gitlink-cli/raw/master/install.ps1)"
|
||
"@
|
||
}
|
||
|
||
# 检测架构
|
||
function Get-PlatformInfo {
|
||
$arch = switch ([System.Runtime.InteropServices::RuntimeInformation]::OSArchitecture) {
|
||
"X64" { "amd64" }
|
||
"Arm64" { "arm64" }
|
||
"X86" { "386"; Warn "32位系统支持有限" }
|
||
default { throw "不支持的架构: $arch" }
|
||
}
|
||
return @{ Platform = "windows"; Arch = $arch }
|
||
}
|
||
|
||
# 检查环境
|
||
function Test-Environment {
|
||
Step "检查安装环境..."
|
||
|
||
# 检查磁盘空间(至少50MB)
|
||
$drive = (Get-Item $InstallDir).PSDrive.Name
|
||
$driveInfo = Get-PSDrive $drive
|
||
$freeSpaceMB = [math]::Round($driveInfo.Free / 1MB, 2)
|
||
|
||
if ($freeSpaceMB -lt 50) {
|
||
ErrorMsg "磁盘空间不足(需要至少50MB,可用: ${freeSpaceMB}MB)"
|
||
exit 1
|
||
}
|
||
DebugMsg "磁盘空间检查通过: ${freeSpaceMB}MB"
|
||
|
||
# 检查网络连接
|
||
try {
|
||
$response = Invoke-WebRequest -Uri $API_BASE -UseBasicParsing -TimeoutSec 5 -Method Head
|
||
DebugMsg "网络连接检查通过"
|
||
}
|
||
catch {
|
||
ErrorMsg "无法连接到 GitLink 服务器: $API_BASE"
|
||
ErrorMsg "请检查网络连接"
|
||
exit 1
|
||
}
|
||
|
||
Info "环境检查通过"
|
||
}
|
||
|
||
# 下载文件(带重试)
|
||
function Download-File {
|
||
param(
|
||
[string]$Url,
|
||
[string]$Output,
|
||
[int]$MaxAttempts = 3
|
||
)
|
||
|
||
$attempt = 1
|
||
while ($attempt -le $MaxAttempts) {
|
||
try {
|
||
Step "下载 (尝试 $attempt/$MaxAttempts): $(Split-Path $Url -Leaf)"
|
||
DebugMsg "URL: $Url"
|
||
|
||
# 使用WebClient,支持进度显示
|
||
$webClient = New-Object System.Net.WebClient
|
||
|
||
# 注册下载进度事件
|
||
Register-ObjectEvent -InputObject $webClient -EventName DownloadProgressChanged -SourceIdentifier WebClient.DownloadProgressChanged -Action {
|
||
global:Progress = $EventArgs.ProgressPercentage
|
||
Write-Progress -Activity "下载中" -Status "$($EventArgs.ProgressPercentage)% 完成" -PercentComplete $EventArgs.ProgressPercentage
|
||
} | Out-Null
|
||
|
||
# 注册下载完成事件
|
||
Register-ObjectEvent -InputObject $webClient -EventName DownloadFileCompleted -SourceIdentifier WebClient.DownloadFileCompleted -Action {
|
||
global:DownloadComplete = $true
|
||
} | Out-Null
|
||
|
||
# 开始下载
|
||
$webClient.DownloadFileAsync($Url, $Output)
|
||
|
||
# 等待下载完成
|
||
while (-not $global:DownloadComplete) {
|
||
Start-Sleep -Milliseconds 100
|
||
}
|
||
|
||
Write-Progress -Activity "下载中" -Completed
|
||
|
||
# 清理事件
|
||
Unregister-Event -SourceIdentifier WebClient.DownloadProgressChanged -ErrorAction SilentlyContinue
|
||
Unregister-Event -SourceIdentifier WebClient.DownloadFileCompleted -ErrorAction SilentlyContinue
|
||
$webClient.Dispose()
|
||
|
||
if (Test-Path $Output) {
|
||
$size = [math]::Round((Get-Item $Output).Length / 1MB, 2)
|
||
Info "下载成功: $(Split-Path $Output -Leaf) (${size}MB)"
|
||
return $true
|
||
}
|
||
else {
|
||
Warn "下载文件为空"
|
||
}
|
||
}
|
||
catch {
|
||
Warn "下载失败: $_"
|
||
}
|
||
|
||
if ($attempt -lt $MaxAttempts) {
|
||
$waitTime = $attempt * 2
|
||
Warn "等待 ${waitTime}s 后重试..."
|
||
Start-Sleep -Seconds $waitTime
|
||
}
|
||
|
||
$attempt++
|
||
}
|
||
|
||
ErrorMsg "下载失败,已尝试 $MaxAttempts 次"
|
||
ErrorMsg "URL: $Url"
|
||
return $false
|
||
}
|
||
|
||
# 获取最新版本
|
||
function Get-LatestVersion {
|
||
Step "获取最新版本..."
|
||
|
||
try {
|
||
$releasesUrl = "$API_BASE/api/$REPO_OWNER/$REPO_NAME/releases.json"
|
||
$releases = Invoke-RestMethod -Uri $releasesUrl -TimeoutSec 30 -UseBasicParsing
|
||
|
||
if ($releases -and $releases.Count -gt 0) {
|
||
return $releases[0].tag_name
|
||
}
|
||
else {
|
||
Warn "无法获取版本信息,使用默认版本"
|
||
return "v0.1.0"
|
||
}
|
||
}
|
||
catch {
|
||
Warn "获取版本失败: $_"
|
||
return "v0.1.0"
|
||
}
|
||
}
|
||
|
||
# 列出可用版本
|
||
function Show-AvailableVersions {
|
||
Step "查询可用版本..."
|
||
|
||
try {
|
||
$releasesUrl = "$API_BASE/api/$REPO_OWNER/$REPO_NAME/releases.json"
|
||
$releases = Invoke-RestMethod -Uri $releasesUrl -TimeoutSec 30 -UseBasicParsing
|
||
|
||
if ($releases -and $releases.Count -gt 0) {
|
||
Info "可用版本:"
|
||
foreach ($release in $releases | Select-Object -First 10) {
|
||
Write-Host " - $($release.tag_name)" -ForegroundColor Cyan
|
||
}
|
||
}
|
||
else {
|
||
Warn "无法获取版本列表"
|
||
}
|
||
}
|
||
catch {
|
||
ErrorMsg "获取版本列表失败: $_"
|
||
}
|
||
}
|
||
|
||
# 解压zip文件
|
||
function Expand-ZipFile {
|
||
param(
|
||
[string]$ZipPath,
|
||
[string]$DestDir
|
||
)
|
||
|
||
Step "解压..."
|
||
DebugMsg "解压 $ZipPath 到 $DestDir"
|
||
|
||
try {
|
||
Expand-Archive -Force -Path $ZipPath -DestinationPath $DestDir
|
||
Info "解压完成"
|
||
}
|
||
catch {
|
||
ErrorMsg "解压失败: $_"
|
||
throw
|
||
}
|
||
}
|
||
|
||
# 添加到PATH
|
||
function Add-ToPath {
|
||
param([string]$Dir)
|
||
|
||
$path = [Environment]::GetEnvironmentVariable("Path", "User")
|
||
if ($path -notlike "*$Dir*") {
|
||
Step "添加到PATH: $Dir"
|
||
[Environment]::SetEnvironmentVariable("Path", "$path;$Dir", "User")
|
||
Warn "请重启终端使PATH生效"
|
||
}
|
||
else {
|
||
DebugMsg "已在PATH中: $Dir"
|
||
}
|
||
}
|
||
|
||
# 验证安装
|
||
function Test-Installation {
|
||
Step "验证安装..."
|
||
|
||
$binaryPath = Join-Path $InstallDir "$BINARY_NAME.exe"
|
||
|
||
if (Test-Path $binaryPath) {
|
||
try {
|
||
$versionOutput = & $binaryPath version 2>$null
|
||
Info "安装成功! $versionOutput"
|
||
|
||
# 添加到PATH
|
||
Add-ToPath $InstallDir
|
||
|
||
Write-Host ""
|
||
Info "快速开始:"
|
||
Info " gitlink-cli auth login # 登录账号"
|
||
Info " gitlink-cli --help # 查看所有命令"
|
||
Info " gitlink-cli version # 查看版本信息"
|
||
Write-Host ""
|
||
|
||
return $true
|
||
}
|
||
catch {
|
||
ErrorMsg "执行二进制文件失败: $_"
|
||
return $false
|
||
}
|
||
}
|
||
else {
|
||
ErrorMsg "安装验证失败: $binaryPath 不存在"
|
||
return $false
|
||
}
|
||
}
|
||
|
||
# 主安装流程
|
||
function Install-CLI {
|
||
Write-Host ""
|
||
Write-Host " ╔══════════════════════════════════════╗"
|
||
Write-Host " ║ GitLink CLI 一键安装 (Windows) ║"
|
||
Write-Host " ╚══════════════════════════════════════╝"
|
||
Write-Host ""
|
||
|
||
# 检测平台
|
||
$platform = Get-PlatformInfo
|
||
Info "检测到平台: $($platform.Platform)-$($platform.Arch)"
|
||
|
||
# 创建安装目录
|
||
if (!(Test-Path $InstallDir)) {
|
||
New-Item -ItemType Directory -Path $InstallDir -Force | Out-Null
|
||
Info "创建安装目录: $InstallDir"
|
||
}
|
||
|
||
# 检查环境
|
||
Test-Environment
|
||
|
||
# 获取版本
|
||
if ($Version -eq "latest") {
|
||
$Version = Get-LatestVersion
|
||
Info "最新版本: $Version"
|
||
}
|
||
else {
|
||
Info "指定版本: $Version"
|
||
}
|
||
|
||
# 下载
|
||
$zipName = "$BINARY_NAME_${Version}_windows_$($platform.Arch).zip"
|
||
$zipUrl = "$API_BASE/api/$REPO_OWNER/$REPO_NAME/releases/$Version/assets/$zipName"
|
||
$zipPath = Join-Path $env:TEMP $zipName
|
||
|
||
if (-not (Download-File -Url $zipUrl -Output $zipPath)) {
|
||
ErrorMsg "请确认以下版本已发布: $Version"
|
||
ErrorMsg "发布页: $API_BASE/$REPO_OWNER/$REPO_NAME/releases"
|
||
exit 1
|
||
}
|
||
|
||
# 解压
|
||
Expand-ZipFile -ZipPath $zipPath -DestDir $InstallDir
|
||
Remove-Item $zipPath
|
||
|
||
# 安装skills
|
||
Step "安装 skills..."
|
||
if (!(Test-Path $SKILLS_DIR)) {
|
||
New-Item -ItemType Directory -Path $SKILLS_DIR -Force | Out-Null
|
||
}
|
||
|
||
$skillsZipName = "$BINARY_NAME_${Version}_skills.zip"
|
||
$skillsUrl = "$API_BASE/api/$REPO_OWNER/$REPO_NAME/releases/$Version/assets/$skillsZipName"
|
||
$skillsZipPath = Join-Path $env:TEMP $skillsZipName
|
||
|
||
if (Download-File -Url $skillsUrl -Output $skillsZipPath) {
|
||
try {
|
||
Expand-Archive -Force -Path $skillsZipPath -DestinationPath $SKILLS_DIR
|
||
Info "Skills 安装到: $SKILLS_DIR"
|
||
}
|
||
catch {
|
||
Warn "Skills 解压失败(可稍后手动安装)"
|
||
}
|
||
Remove-Item $skillsZipPath -ErrorAction SilentlyContinue
|
||
}
|
||
else {
|
||
Warn "Skills 包不可用(可稍后手动安装)"
|
||
}
|
||
|
||
# 验证
|
||
if (-not (Test-Installation)) {
|
||
exit 1
|
||
}
|
||
}
|
||
|
||
# 卸载
|
||
function Uninstall-CLI {
|
||
Step "卸载 $BINARY_NAME..."
|
||
|
||
# 删除二进制
|
||
$binaryPath = Join-Path $InstallDir "$BINARY_NAME.exe"
|
||
if (Test-Path $binaryPath) {
|
||
Remove-Item $binaryPath -Force
|
||
Info "已删除: $binaryPath"
|
||
}
|
||
|
||
# 删除skills
|
||
if (Test-Path $SKILLS_DIR) {
|
||
Remove-Item $SKILLS_DIR -Recurse -Force
|
||
Info "已删除: $SKILLS_DIR"
|
||
}
|
||
|
||
# 删除配置(可选)
|
||
$response = Read-Host "是否删除配置文件? [y/N]"
|
||
if ($response -eq 'y' -or $response -eq 'Y') {
|
||
$configDir = Join-Path $env:APPDATA "gitlink-cli"
|
||
if (Test-Path $configDir) {
|
||
Remove-Item $configDir -Recurse -Force
|
||
Info "已删除配置文件"
|
||
}
|
||
}
|
||
|
||
Info "卸载完成"
|
||
}
|
||
|
||
# 主函数
|
||
function Main {
|
||
if ($Help) {
|
||
Show-Help
|
||
exit 0
|
||
}
|
||
|
||
if ($ListVersions) {
|
||
Show-AvailableVersions
|
||
exit 0
|
||
}
|
||
|
||
if ($Uninstall) {
|
||
Uninstall-CLI
|
||
exit 0
|
||
}
|
||
|
||
try {
|
||
Install-CLI
|
||
}
|
||
catch {
|
||
ErrorMsg "安装失败: $_"
|
||
exit 1
|
||
}
|
||
}
|
||
|
||
Main
|