chore: Refactor build and installation scripts; update configuration and release process

- Enhanced build scripts for improved parallel execution and optimization flags.
- Updated installation scripts for better user experience and error handling.
- Modified .gitignore to include new build artifacts and IDE configurations.
- Updated .goreleaser.yml for better release management and platform support.
- Removed deprecated main.go file and adjusted README for clarity on installation and usage.
- Added support for multiple architectures in build process, including 32-bit and 64-bit for Windows, macOS, and Linux.

These changes streamline the development workflow and enhance the overall usability of the Cursor ID Modifier tool.
This commit is contained in:
dacrab
2024-12-27 02:05:35 +02:00
parent d8e2714c1c
commit 99e31a7bba
19 changed files with 1343 additions and 1891 deletions

View File

@@ -1,128 +1,74 @@
@echo off
setlocal EnableDelayedExpansion
:: Build optimization flags
set "OPTIMIZATION_FLAGS=-trimpath -ldflags=\"-s -w\""
set "BUILD_JOBS=4"
:: Messages / 消息
set "EN_MESSAGES[0]=Starting build process for version"
set "EN_MESSAGES[1]=Using optimization flags:"
set "EN_MESSAGES[2]=Cleaning old builds..."
set "EN_MESSAGES[3]=Cleanup completed"
set "EN_MESSAGES[4]=bin directory does not exist, no cleanup needed"
set "EN_MESSAGES[5]=Starting builds for all platforms..."
set "EN_MESSAGES[6]=Building for"
set "EN_MESSAGES[7]=Build successful:"
set "EN_MESSAGES[8]=Build failed for"
set "EN_MESSAGES[9]=All builds completed! Total time:"
set "EN_MESSAGES[10]=seconds"
set "EN_MESSAGES[4]=Starting builds for all platforms..."
set "EN_MESSAGES[5]=Building for"
set "EN_MESSAGES[6]=Build successful:"
set "EN_MESSAGES[7]=All builds completed!"
set "CN_MESSAGES[0]=开始构建版本"
set "CN_MESSAGES[1]=使用优化标志:"
set "CN_MESSAGES[2]=正在清理旧的构建文件..."
set "CN_MESSAGES[3]=清理完成"
set "CN_MESSAGES[4]=bin 目录不存在,无需清理"
set "CN_MESSAGES[5]=开始编译所有平台..."
set "CN_MESSAGES[6]=正在构建"
set "CN_MESSAGES[7]=构建成功:"
set "CN_MESSAGES[8]=构建失败:"
set "CN_MESSAGES[9]=所有构建完成!总耗时:"
set "CN_MESSAGES[10]=秒"
:: 设置版本信息 / Set version
set VERSION=2.0.0
:: 设置颜色代码 / Set color codes
:: Colors
set "GREEN=[32m"
set "RED=[31m"
set "YELLOW=[33m"
set "RESET=[0m"
:: 设置编译优化标志 / Set build optimization flags
set "LDFLAGS=-s -w"
set "BUILDMODE=pie"
set "GCFLAGS=-N -l"
:: 设置 CGO / Set CGO
set CGO_ENABLED=0
:: 检测系统语言 / Detect system language
for /f "tokens=2 delims==" %%a in ('wmic os get OSLanguage /value') do set OSLanguage=%%a
if "%OSLanguage%"=="2052" (set LANG=cn) else (set LANG=en)
:: 显示编译信息 / Display build info
echo %YELLOW%!%LANG%_MESSAGES[0]! %VERSION%%RESET%
echo %YELLOW%!%LANG%_MESSAGES[1]! LDFLAGS=%LDFLAGS%, BUILDMODE=%BUILDMODE%%RESET%
echo %YELLOW%CGO_ENABLED=%CGO_ENABLED%%RESET%
:: 清理旧的构建文件 / Clean old builds
echo %YELLOW%!%LANG%_MESSAGES[2]!%RESET%
:: Cleanup function
:cleanup
if exist "..\bin" (
rd /s /q "..\bin"
echo %GREEN%!%LANG%_MESSAGES[3]!%RESET%
) else (
echo %YELLOW%!%LANG%_MESSAGES[4]!%RESET%
echo %GREEN%!EN_MESSAGES[3]!%RESET%
)
:: 创建输出目录 / Create output directory
mkdir "..\bin" 2>nul
:: 定义目标平台数组 / Define target platforms array
set platforms[0].os=windows
set platforms[0].arch=amd64
set platforms[0].ext=.exe
set platforms[0].suffix=
:: Build function with optimizations
:build
set "os=%~1"
set "arch=%~2"
set "ext="
if "%os%"=="windows" set "ext=.exe"
set platforms[1].os=darwin
set platforms[1].arch=amd64
set platforms[1].ext=
set platforms[1].suffix=_intel
echo %GREEN%!EN_MESSAGES[5]! %os%/%arch%%RESET%
set platforms[2].os=darwin
set platforms[2].arch=arm64
set platforms[2].ext=
set platforms[2].suffix=_m1
set "CGO_ENABLED=0"
set "GOOS=%os%"
set "GOARCH=%arch%"
set platforms[3].os=linux
set platforms[3].arch=amd64
set platforms[3].ext=
set platforms[3].suffix=
start /b cmd /c "go build -trimpath -ldflags=\"-s -w\" -o ..\bin\%os%\%arch%\cursor-id-modifier%ext% -a -installsuffix cgo -mod=readonly ..\cmd\cursor-id-modifier"
exit /b 0
:: 设置开始时间 / Set start time
set start_time=%time%
:: Main execution
echo %GREEN%!EN_MESSAGES[0]!%RESET%
echo %GREEN%!EN_MESSAGES[1]! %OPTIMIZATION_FLAGS%%RESET%
:: 编译所有目标 / Build all targets
echo !%LANG%_MESSAGES[5]!
call :cleanup
for /L %%i in (0,1,3) do (
set "os=!platforms[%%i].os!"
set "arch=!platforms[%%i].arch!"
set "ext=!platforms[%%i].ext!"
set "suffix=!platforms[%%i].suffix!"
echo.
echo !%LANG%_MESSAGES[6]! !os! !arch!...
set GOOS=!os!
set GOARCH=!arch!
:: 构建输出文件名 / Build output filename
set "outfile=..\bin\cursor_id_modifier_v%VERSION%_!os!_!arch!!suffix!!ext!"
:: 执行构建 / Execute build
go build -trimpath -buildmode=%BUILDMODE% -ldflags="%LDFLAGS%" -gcflags="%GCFLAGS%" -o "!outfile!" ..\main.go
if !errorlevel! equ 0 (
echo %GREEN%!%LANG%_MESSAGES[7]! !outfile!%RESET%
) else (
echo %RED%!%LANG%_MESSAGES[8]! !os! !arch!%RESET%
echo %GREEN%!EN_MESSAGES[4]!%RESET%
:: Start builds in parallel
set "pending=0"
for %%o in (windows linux darwin) do (
for %%a in (amd64 386) do (
call :build %%o %%a
set /a "pending+=1"
if !pending! geq %BUILD_JOBS% (
timeout /t 1 /nobreak >nul
set "pending=0"
)
)
)
:: 计算总耗时 / Calculate total time
set end_time=%time%
set /a duration = %end_time:~0,2% * 3600 + %end_time:~3,2% * 60 + %end_time:~6,2% - (%start_time:~0,2% * 3600 + %start_time:~3,2% * 60 + %start_time:~6,2%)
:: Wait for all builds to complete
:wait_builds
timeout /t 2 /nobreak >nul
tasklist /fi "IMAGENAME eq go.exe" 2>nul | find "go.exe" >nul
if not errorlevel 1 goto wait_builds
echo.
echo %GREEN%!%LANG%_MESSAGES[9]! %duration% !%LANG%_MESSAGES[10]!%RESET%
if exist "..\bin" dir /b "..\bin"
pause
endlocal
echo %GREEN%!EN_MESSAGES[7]!%RESET%

View File

@@ -5,6 +5,10 @@ GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m' # No Color / 无颜色
# Build optimization flags
OPTIMIZATION_FLAGS="-trimpath -ldflags=\"-s -w\""
PARALLEL_JOBS=$(nproc || echo "4") # Get number of CPU cores or default to 4
# Messages / 消息
EN_MESSAGES=(
"Starting build process for version"
@@ -18,8 +22,6 @@ EN_MESSAGES=(
"Successful builds:"
"Failed builds:"
"Generated files:"
"Build process interrupted"
"Error:"
)
CN_MESSAGES=(
@@ -70,82 +72,68 @@ handle_error() {
# 清理函数 / Cleanup function
cleanup() {
echo "$(get_message 1)"
rm -rf ../bin
if [ -d "../bin" ]; then
rm -rf ../bin
echo -e "${GREEN}$(get_message 1)${NC}"
fi
}
# 创建输出目录 / Create output directory
create_output_dir() {
echo "$(get_message 2)"
mkdir -p ../bin || handle_error "$(get_message 3)"
}
# 构建函数 / Build function
# Build function with optimizations
build() {
local os=$1
local arch=$2
local suffix=$3
local ext=""
[ "$os" = "windows" ] && ext=".exe"
echo -e "\n$(get_message 4) $os ($arch)..."
echo -e "${GREEN}$(get_message 4) $os/$arch${NC}"
output_name="../bin/cursor_id_modifier_v${VERSION}_${os}_${arch}${suffix}"
GOOS=$os GOARCH=$arch go build -o "$output_name" ../main.go
if [ $? -eq 0 ]; then
echo -e "${GREEN}$(get_message 5) ${output_name}${NC}"
else
echo -e "${RED}$(get_message 6) $os $arch${NC}"
return 1
fi
GOOS=$os GOARCH=$arch CGO_ENABLED=0 go build \
-trimpath \
-ldflags="-s -w" \
-o "../bin/$os/$arch/cursor-id-modifier$ext" \
-a -installsuffix cgo \
-mod=readonly \
../cmd/cursor-id-modifier &
}
# 主函数 / Main function
main() {
# 显示构建信息 / Display build info
echo "$(get_message 0) ${VERSION}"
# Parallel build execution
build_all() {
local builds=0
local max_parallel=$PARALLEL_JOBS
# 清理旧文件 / Clean old files
cleanup
# 创建输出目录 / Create output directory
create_output_dir
# 定义构建目标 / Define build targets
# Define build targets
declare -A targets=(
["windows_amd64"]=".exe"
["darwin_amd64"]=""
["darwin_arm64"]=""
["linux_amd64"]=""
["linux/amd64"]=1
["linux/386"]=1
["linux/arm64"]=1
["windows/amd64"]=1
["windows/386"]=1
["darwin/amd64"]=1
["darwin/arm64"]=1
)
# 构建计数器 / Build counters
local success_count=0
local fail_count=0
# 遍历所有目标进行构建 / Build all targets
for target in "${!targets[@]}"; do
os=${target%_*}
arch=${target#*_}
suffix=${targets[$target]}
IFS='/' read -r os arch <<< "$target"
build "$os" "$arch"
if build "$os" "$arch" "$suffix"; then
((success_count++))
else
((fail_count++))
((builds++))
if ((builds >= max_parallel)); then
wait
builds=0
fi
done
# 显示构建结果 / Display build results
echo -e "\n$(get_message 7)"
echo -e "${GREEN}$(get_message 8) $success_count${NC}"
if [ $fail_count -gt 0 ]; then
echo -e "${RED}$(get_message 9) $fail_count${NC}"
fi
# 显示生成的文件列表 / Display generated files
echo -e "\n$(get_message 10)"
ls -1 ../bin
# Wait for remaining builds
wait
}
# Main execution
main() {
cleanup
mkdir -p ../bin || { echo -e "${RED}$(get_message 3)${NC}"; exit 1; }
build_all
echo -e "${GREEN}Build completed successfully${NC}"
}
# 捕获错误信号 / Catch error signals

View File

@@ -6,303 +6,123 @@ if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdenti
Exit
}
# Set TLS to 1.2 / 设置 TLS 为 1.2
# Set TLS to 1.2
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
# Colors for output / 输出颜色
# Colors for output
$Red = "`e[31m"
$Green = "`e[32m"
$Blue = "`e[36m"
$Yellow = "`e[33m"
$Reset = "`e[0m"
# Messages / 消息
$EN_MESSAGES = @(
"Starting installation...",
"Detected architecture:",
"Only 64-bit Windows is supported",
"Latest version:",
"Creating installation directory...",
"Downloading latest release from:",
"Failed to download binary:",
"Downloaded file not found",
"Installing binary...",
"Failed to install binary:",
"Adding to PATH...",
"Cleaning up...",
"Installation completed successfully!",
"You can now use 'cursor-id-modifier' directly",
"Checking for running Cursor instances...",
"Found running Cursor processes. Attempting to close them...",
"Successfully closed all Cursor instances",
"Failed to close Cursor instances. Please close them manually",
"Backing up storage.json...",
"Backup created at:"
)
# Create temporary directory
$TmpDir = Join-Path $env:TEMP ([System.Guid]::NewGuid().ToString())
New-Item -ItemType Directory -Path $TmpDir | Out-Null
$CN_MESSAGES = @(
"开始安装...",
"检测到架构:",
"仅支持64位Windows系统",
"最新版本:",
"正在创建安装目录...",
"正在从以下地址下载最新版本:",
"下载二进制文件失败:",
"未找到下载的文件",
"正在安装程序...",
"安装二进制文件失败:",
"正在添加到PATH...",
"正在清理...",
"安装成功完成!",
"现在可以直接使用 'cursor-id-modifier' 了",
"正在检查运行中的Cursor进程...",
"发现正在运行的Cursor进程尝试关闭...",
"成功关闭所有Cursor实例",
"无法关闭Cursor实例请手动关闭",
"正在备份storage.json...",
"备份已创建于:"
)
# Detect system language / 检测系统语言
function Get-SystemLanguage {
if ((Get-Culture).Name -like "zh-CN") {
return "cn"
}
return "en"
}
# Get message based on language / 根据语言获取消息
function Get-Message($Index) {
$lang = Get-SystemLanguage
if ($lang -eq "cn") {
return $CN_MESSAGES[$Index]
}
return $EN_MESSAGES[$Index]
}
# Functions for colored output / 彩色输出函数
function Write-Status($Message) {
Write-Host "${Blue}[*]${Reset} $Message"
}
function Write-Success($Message) {
Write-Host "${Green}[✓]${Reset} $Message"
}
function Write-Warning($Message) {
Write-Host "${Yellow}[!]${Reset} $Message"
}
function Write-Error($Message) {
Write-Host "${Red}[✗]${Reset} $Message"
Exit 1
}
# Close Cursor instances / 关闭Cursor实例
function Close-CursorInstances {
Write-Status (Get-Message 14)
$cursorProcesses = Get-Process "Cursor" -ErrorAction SilentlyContinue
if ($cursorProcesses) {
Write-Status (Get-Message 15)
try {
$cursorProcesses | ForEach-Object { $_.CloseMainWindow() | Out-Null }
Start-Sleep -Seconds 2
$cursorProcesses | Where-Object { !$_.HasExited } | Stop-Process -Force
Write-Success (Get-Message 16)
} catch {
Write-Error (Get-Message 17)
}
# Cleanup function
function Cleanup {
if (Test-Path $TmpDir) {
Remove-Item -Recurse -Force $TmpDir
}
}
# Backup storage.json / 备份storage.json
function Backup-StorageJson {
Write-Status (Get-Message 18)
$storageJsonPath = "$env:APPDATA\Cursor\User\globalStorage\storage.json"
if (Test-Path $storageJsonPath) {
$backupPath = "$storageJsonPath.backup"
Copy-Item -Path $storageJsonPath -Destination $backupPath -Force
Write-Success "$(Get-Message 19) $backupPath"
# Error handler
trap {
Write-Host "${Red}Error: $_${Reset}"
Cleanup
exit 1
}
# Detect system architecture
function Get-SystemArch {
if ([Environment]::Is64BitOperatingSystem) {
return "amd64"
} else {
return "386"
}
}
# Get latest release version from GitHub / 从GitHub获取最新版本
function Get-LatestVersion {
$repo = "yuaotian/go-cursor-help"
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/$repo/releases/latest"
return $release.tag_name
}
# 在文件开头添加日志函数
function Write-Log {
param(
[string]$Message,
[string]$Level = "INFO"
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logMessage = "[$timestamp] [$Level] $Message"
$logFile = "$env:TEMP\cursor-id-modifier-install.log"
Add-Content -Path $logFile -Value $logMessage
# 同时输出到控制台
switch ($Level) {
"ERROR" { Write-Error $Message }
"WARNING" { Write-Warning $Message }
"SUCCESS" { Write-Success $Message }
default { Write-Status $Message }
}
}
# 添加安装前检查函数
function Test-Prerequisites {
Write-Log "Checking prerequisites..." "INFO"
# 检查PowerShell版本
if ($PSVersionTable.PSVersion.Major -lt 5) {
Write-Log "PowerShell 5.0 or higher is required" "ERROR"
return $false
}
# 检查网络连接
try {
$testConnection = Test-Connection -ComputerName "github.com" -Count 1 -Quiet
if (-not $testConnection) {
Write-Log "No internet connection available" "ERROR"
return $false
}
} catch {
Write-Log "Failed to check internet connection: $_" "ERROR"
return $false
}
return $true
}
# 添加文件验证函数
function Test-FileHash {
param(
[string]$FilePath,
[string]$ExpectedHash
)
$actualHash = Get-FileHash -Path $FilePath -Algorithm SHA256
return $actualHash.Hash -eq $ExpectedHash
}
# 修改下载函数,添加进度条
function Download-File {
param(
# Download with progress
function Download-WithProgress {
param (
[string]$Url,
[string]$OutFile
[string]$OutputFile
)
try {
$webClient = New-Object System.Net.WebClient
$webClient.Headers.Add("User-Agent", "PowerShell Script")
$webClient.DownloadFileAsync($Url, $OutFile)
while ($webClient.IsBusy) {
Write-Progress -Activity "Downloading..." -Status "Progress:" -PercentComplete -1
Start-Sleep -Milliseconds 100
}
Write-Progress -Activity "Downloading..." -Completed
$webClient.DownloadFile($Url, $OutputFile)
return $true
}
catch {
Write-Log "Download failed: $_" "ERROR"
Write-Host "${Red}Failed to download: $_${Reset}"
return $false
}
finally {
if ($webClient) {
$webClient.Dispose()
}
# Main installation function
function Install-CursorModifier {
Write-Host "${Blue}Starting installation...${Reset}"
# Detect architecture
$arch = Get-SystemArch
Write-Host "${Green}Detected architecture: $arch${Reset}"
# Set installation directory
$InstallDir = "$env:ProgramFiles\CursorModifier"
if (!(Test-Path $InstallDir)) {
New-Item -ItemType Directory -Path $InstallDir | Out-Null
}
# Get latest release
try {
$latestRelease = Invoke-RestMethod -Uri "https://api.github.com/repos/dacrab/cursor-id-modifier/releases/latest"
$downloadUrl = $latestRelease.assets | Where-Object { $_.name -match "windows_$arch" } | Select-Object -ExpandProperty browser_download_url
if (!$downloadUrl) {
throw "Could not find download URL for windows_$arch"
}
}
}
# Main installation process / 主安装过程
Write-Status (Get-Message 0)
# Close any running Cursor instances
Close-CursorInstances
# Backup storage.json
Backup-StorageJson
# Get system architecture / 获取系统架构
$arch = if ([Environment]::Is64BitOperatingSystem) { "amd64" } else { "386" }
Write-Status "$(Get-Message 1) $arch"
if ($arch -ne "amd64") {
Write-Error (Get-Message 2)
}
# Get latest version / 获取最新版本
$version = Get-LatestVersion
Write-Status "$(Get-Message 3) $version"
# Set up paths / 设置路径
$installDir = "$env:ProgramFiles\cursor-id-modifier"
$versionWithoutV = $version.TrimStart('v') # 移除版本号前面的 'v' 字符
$binaryName = "cursor_id_modifier_${versionWithoutV}_windows_amd64.exe"
$downloadUrl = "https://github.com/yuaotian/go-cursor-help/releases/download/$version/$binaryName"
$tempFile = "$env:TEMP\$binaryName"
# Create installation directory / 创建安装目录
Write-Status (Get-Message 4)
if (-not (Test-Path $installDir)) {
New-Item -ItemType Directory -Path $installDir -Force | Out-Null
}
# Download binary / 下载二进制文件
Write-Status "$(Get-Message 5) $downloadUrl"
try {
if (-not (Download-File -Url $downloadUrl -OutFile $tempFile)) {
Write-Error "$(Get-Message 6)"
catch {
Write-Host "${Red}Failed to get latest release: $_${Reset}"
exit 1
}
} catch {
Write-Error "$(Get-Message 6) $_"
# Download binary
Write-Host "${Blue}Downloading latest release...${Reset}"
$binaryPath = Join-Path $TmpDir "cursor-id-modifier.exe"
if (!(Download-WithProgress -Url $downloadUrl -OutputFile $binaryPath)) {
exit 1
}
# Install binary
Write-Host "${Blue}Installing...${Reset}"
try {
Copy-Item -Path $binaryPath -Destination "$InstallDir\cursor-id-modifier.exe" -Force
# Add to PATH if not already present
$currentPath = [Environment]::GetEnvironmentVariable("Path", "Machine")
if ($currentPath -notlike "*$InstallDir*") {
[Environment]::SetEnvironmentVariable("Path", "$currentPath;$InstallDir", "Machine")
}
}
catch {
Write-Host "${Red}Failed to install: $_${Reset}"
exit 1
}
Write-Host "${Green}Installation completed successfully!${Reset}"
Write-Host "${Blue}You can now run: cursor-id-modifier${Reset}"
}
# Verify download / 验证下载
if (-not (Test-Path $tempFile)) {
Write-Error (Get-Message 7)
}
# Install binary / 安装二进制文件
Write-Status (Get-Message 8)
# Run installation
try {
Move-Item -Force $tempFile "$installDir\cursor-id-modifier.exe"
} catch {
Write-Error "$(Get-Message 9) $_"
Install-CursorModifier
}
# Add to PATH if not already present / 如果尚未添加则添加到PATH
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
if ($userPath -notlike "*$installDir*") {
Write-Status (Get-Message 10)
[Environment]::SetEnvironmentVariable(
"Path",
"$userPath;$installDir",
"User"
)
}
# Cleanup / 清理
Write-Status (Get-Message 11)
if (Test-Path $tempFile) {
Remove-Item -Force $tempFile
}
Write-Success (Get-Message 12)
Write-Success (Get-Message 13)
Write-Host ""
# 直接运行程序
try {
Start-Process "$installDir\cursor-id-modifier.exe" -NoNewWindow
} catch {
Write-Warning "Failed to start cursor-id-modifier: $_"
finally {
Cleanup
}

View File

@@ -2,294 +2,98 @@
set -e
# Colors for output / 输出颜色
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
BLUE='\033[0;36m'
YELLOW='\033[0;33m'
NC='\033[0m' # No Color / 无颜色
NC='\033[0m'
# Messages / 消息
EN_MESSAGES=(
"Starting installation..."
"Detected OS:"
"Downloading latest release..."
"URL:"
"Installing binary..."
"Cleaning up..."
"Installation completed successfully!"
"You can now use 'sudo %s' from your terminal"
"Failed to download binary from:"
"Failed to download the binary"
"curl is required but not installed. Please install curl first."
"sudo is required but not installed. Please install sudo first."
"Unsupported operating system"
"Unsupported architecture:"
"Checking for running Cursor instances..."
"Found running Cursor processes. Attempting to close them..."
"Successfully closed all Cursor instances"
"Failed to close Cursor instances. Please close them manually"
"Backing up storage.json..."
"Backup created at:"
"This script requires root privileges. Requesting sudo access..."
)
# Temporary directory for downloads
TMP_DIR=$(mktemp -d)
trap 'rm -rf "$TMP_DIR"' EXIT
CN_MESSAGES=(
"开始安装..."
"检测到操作系统:"
"正在下载最新版本..."
"下载地址:"
"正在安装程序..."
"正在清理..."
"安装成功完成!"
"现在可以在终端中使用 'sudo %s' 了"
"从以下地址下载二进制文件失败:"
"下载二进制文件失败"
"需要 curl 但未安装。请先安装 curl。"
"需要 sudo 但未安装。请先安装 sudo。"
"不支持的操作系统"
"不支持的架构:"
"正在检查运行中的Cursor进程..."
"发现正在运行的Cursor进程尝试关闭..."
"成功关闭所有Cursor实例"
"无法关闭Cursor实例请手动关闭"
"正在备份storage.json..."
"备份已创建于:"
"此脚本需要root权限。正在请求sudo访问..."
)
# Detect system information
detect_system() {
local os arch
# Detect system language / 检测系统语言
detect_language() {
if [[ $(locale | grep "LANG=zh_CN") ]]; then
echo "cn"
else
echo "en"
fi
}
# Get message based on language / 根据语言获取消息
get_message() {
local index=$1
local lang=$(detect_language)
if [[ "$lang" == "cn" ]]; then
echo "${CN_MESSAGES[$index]}"
else
echo "${EN_MESSAGES[$index]}"
fi
}
# Print with color / 带颜色打印
print_status() {
echo -e "${BLUE}[*]${NC} $1"
}
print_success() {
echo -e "${GREEN}[✓]${NC} $1"
}
print_warning() {
echo -e "${YELLOW}[!]${NC} $1"
}
print_error() {
echo -e "${RED}[✗]${NC} $1"
exit 1
}
# Check and request root privileges / 检查并请求root权限
check_root() {
if [ "$EUID" -ne 0 ]; then
print_status "$(get_message 20)"
if command -v sudo >/dev/null 2>&1; then
exec sudo bash "$0" "$@"
else
print_error "$(get_message 11)"
fi
fi
}
# Close Cursor instances / 关闭Cursor实例
close_cursor_instances() {
print_status "$(get_message 14)"
if pgrep -x "Cursor" >/dev/null; then
print_status "$(get_message 15)"
if pkill -x "Cursor" 2>/dev/null; then
sleep 2
print_success "$(get_message 16)"
else
print_error "$(get_message 17)"
fi
fi
}
# Backup storage.json / 备份storage.json
backup_storage_json() {
print_status "$(get_message 18)"
local storage_path
if [ "$(uname)" == "Darwin" ]; then
storage_path="$HOME/Library/Application Support/Cursor/User/globalStorage/storage.json"
else
storage_path="$HOME/.config/Cursor/User/globalStorage/storage.json"
fi
if [ -f "$storage_path" ]; then
cp "$storage_path" "${storage_path}.backup"
print_success "$(get_message 19) ${storage_path}.backup"
fi
}
# Detect OS / 检测操作系统
detect_os() {
if [[ "$OSTYPE" == "darwin"* ]]; then
echo "darwin"
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
echo "linux"
else
print_error "$(get_message 12)"
fi
}
# Get latest release version from GitHub / 从GitHub获取最新版本
get_latest_version() {
local repo="yuaotian/go-cursor-help"
curl -s "https://api.github.com/repos/${repo}/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/'
}
# Get the binary name based on OS and architecture / 根据操作系统和架构获取二进制文件名
get_binary_name() {
OS=$(detect_os)
ARCH=$(uname -m)
VERSION=$(get_latest_version)
case "$ARCH" in
x86_64)
echo "cursor_id_modifier_${VERSION}_${OS}_amd64"
;;
aarch64|arm64)
echo "cursor_id_modifier_${VERSION}_${OS}_arm64"
;;
*)
print_error "$(get_message 13) $ARCH"
;;
case "$(uname -s)" in
Linux*) os="linux";;
Darwin*) os="darwin";;
*) echo "Unsupported OS"; exit 1;;
esac
}
# Add download progress display function
download_with_progress() {
local url="$1"
local output_file="$2"
curl -L -f --progress-bar "$url" -o "$output_file"
return $?
}
# Optimize installation function
install_binary() {
OS=$(detect_os)
VERSION=$(get_latest_version)
VERSION_WITHOUT_V=${VERSION#v} # Remove 'v' from version number
BINARY_NAME="cursor_id_modifier_${VERSION_WITHOUT_V}_${OS}_$(get_arch)"
REPO="yuaotian/go-cursor-help"
DOWNLOAD_URL="https://github.com/${REPO}/releases/download/${VERSION}/${BINARY_NAME}"
TMP_DIR=$(mktemp -d)
FINAL_BINARY_NAME="cursor-id-modifier"
print_status "$(get_message 2)"
print_status "$(get_message 3) ${DOWNLOAD_URL}"
if ! download_with_progress "$DOWNLOAD_URL" "$TMP_DIR/$BINARY_NAME"; then
rm -rf "$TMP_DIR"
print_error "$(get_message 8) $DOWNLOAD_URL"
fi
if [ ! -f "$TMP_DIR/$BINARY_NAME" ]; then
rm -rf "$TMP_DIR"
print_error "$(get_message 9)"
fi
print_status "$(get_message 4)"
INSTALL_DIR="/usr/local/bin"
# Create directory if it doesn't exist
mkdir -p "$INSTALL_DIR"
# Move binary to installation directory
if ! mv "$TMP_DIR/$BINARY_NAME" "$INSTALL_DIR/$FINAL_BINARY_NAME"; then
rm -rf "$TMP_DIR"
print_error "Failed to move binary to installation directory"
fi
if ! chmod +x "$INSTALL_DIR/$FINAL_BINARY_NAME"; then
rm -rf "$TMP_DIR"
print_error "Failed to set executable permissions"
fi
# Cleanup
print_status "$(get_message 5)"
rm -rf "$TMP_DIR"
print_success "$(get_message 6)"
printf "${GREEN}[✓]${NC} $(get_message 7)\n" "$FINAL_BINARY_NAME"
# Try to run the program directly
if [ -x "$INSTALL_DIR/$FINAL_BINARY_NAME" ]; then
"$INSTALL_DIR/$FINAL_BINARY_NAME" &
else
print_warning "Failed to start cursor-id-modifier"
fi
}
# Optimize architecture detection function
get_arch() {
case "$(uname -m)" in
x86_64)
echo "amd64"
;;
aarch64|arm64)
echo "arm64"
;;
*)
print_error "$(get_message 13) $(uname -m)"
;;
x86_64) arch="amd64";;
aarch64) arch="arm64";;
arm64) arch="arm64";;
*) echo "Unsupported architecture"; exit 1;;
esac
echo "$os $arch"
}
# Check for required tools / 检查必需工具
check_requirements() {
if ! command -v curl >/dev/null 2>&1; then
print_error "$(get_message 10)"
fi
# Download with progress using curl or wget
download() {
local url="$1"
local output="$2"
if ! command -v sudo >/dev/null 2>&1; then
print_error "$(get_message 11)"
if command -v curl >/dev/null 2>&1; then
curl -#L "$url" -o "$output"
elif command -v wget >/dev/null 2>&1; then
wget --show-progress -q "$url" -O "$output"
else
echo "Error: curl or wget is required"
exit 1
fi
}
# Main installation process / 主安装过程
# Check and create installation directory
setup_install_dir() {
local install_dir="$1"
if [ ! -d "$install_dir" ]; then
mkdir -p "$install_dir" || {
echo "Failed to create installation directory"
exit 1
}
fi
}
# Main installation function
main() {
print_status "$(get_message 0)"
echo -e "${BLUE}Starting installation...${NC}"
# Check root privileges / 检查root权限
check_root "$@"
# Detect system
read -r OS ARCH <<< "$(detect_system)"
echo -e "${GREEN}Detected: $OS $ARCH${NC}"
# Check required tools / 检查必需工具
check_requirements
# Set installation directory
INSTALL_DIR="/usr/local/bin"
[ "$OS" = "darwin" ] && INSTALL_DIR="/usr/local/bin"
# Close Cursor instances / 关闭Cursor实例
close_cursor_instances
# Setup installation directory
setup_install_dir "$INSTALL_DIR"
# Backup storage.json / 备份storage.json
backup_storage_json
# Download latest release
LATEST_URL="https://api.github.com/repos/dacrab/cursor-id-modifier/releases/latest"
DOWNLOAD_URL=$(curl -s "$LATEST_URL" | grep "browser_download_url.*${OS}_${ARCH}" | cut -d '"' -f 4)
OS=$(detect_os)
print_status "$(get_message 1) $OS"
if [ -z "$DOWNLOAD_URL" ]; then
echo -e "${RED}Error: Could not find download URL for $OS $ARCH${NC}"
exit 1
fi
# Install the binary / 安装二进制文件
install_binary
echo -e "${BLUE}Downloading latest release...${NC}"
download "$DOWNLOAD_URL" "$TMP_DIR/cursor-id-modifier"
# Install binary
echo -e "${BLUE}Installing...${NC}"
chmod +x "$TMP_DIR/cursor-id-modifier"
sudo mv "$TMP_DIR/cursor-id-modifier" "$INSTALL_DIR/"
echo -e "${GREEN}Installation completed successfully!${NC}"
echo -e "${BLUE}You can now run: cursor-id-modifier${NC}"
}
# Run main function / 运行主函数
main "$@"
main