#!/bin/bash # Zed Remote Server Auto-Downloader # 支持自动检测最新版本或指定版本下载 set -e ZED_SERVER_DIR="$HOME/.zed_server" GITHUB_REPO="zed-industries/zed" ARCH="x86_64" # 颜色输出 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # 显示帮助信息 show_help() { cat << EOF Zed Remote Server 下载工具 用法: $0 [选项] 选项: -v, --version VERSION 指定版本号下载 (例如: 0.230.0) -l, --list 列出已安装的版本 -h, --help 显示此帮助信息 示例: $0 # 自动下载最新版本 $0 -v 0.230.0 # 下载指定版本 0.230.0 EOF } # 列出已安装的版本 list_installed() { echo "📂 已安装的 Zed Server 版本:" if [ -d "$ZED_SERVER_DIR" ]; then ls -1 "$ZED_SERVER_DIR" 2>/dev/null | grep "^zed-remote-server" | while read -r file; do if [ -f "$ZED_SERVER_DIR/$file" ]; then size=$(du -h "$ZED_SERVER_DIR/$file" 2>/dev/null | cut -f1) echo " • $file (${size})" fi done echo "" LATEST_LINK="$ZED_SERVER_DIR/zed-remote-server-latest" if [ -L "$LATEST_LINK" ]; then echo "🔗 当前链接: $(readlink "$LATEST_LINK")" fi else echo " 无" fi } # 获取 tag 对应的 commit hash(通过 GitHub Git Refs API) get_tag_commit() { local version="$1" local tag_ref="refs/tags/v${version}" local api_url="https://api.github.com/repos/${GITHUB_REPO}/git/${tag_ref}" local tag_info tag_info=$(curl -s "$api_url") local object_type object_type=$(echo "$tag_info" | grep -o '"type": "[^"]*' | head -1 | cut -d'"' -f4) local commit_sha if [ "$object_type" = "tag" ]; then # annotated tag:object.sha 才是真正的 commit hash commit_sha=$(echo "$tag_info" | grep -o '"object": {[^}]*' | grep -o '"sha": "[^"]*' | head -1 | cut -d'"' -f4) else # lightweight tag:顶层 sha 直接就是 commit hash commit_sha=$(echo "$tag_info" | grep -o '"sha": "[^"]*' | head -1 | cut -d'"' -f4) fi echo "$commit_sha" } # 对应 GitHub Actions 页面 https://github.com/zed-industries/zed/actions/workflows/release.yml 中显示的 #xxx get_build_number() { local commit_sha="$1" if [ -z "$commit_sha" ]; then echo "0" return fi # 使用 /actions/workflows/release.yml/runs 端点,而非全局 /actions/runs # 这样拿到的 run_number 与页面显示的编号完全一致 local runs_api="https://api.github.com/repos/${GITHUB_REPO}/actions/workflows/release.yml/runs?head_sha=${commit_sha}&per_page=5&status=completed" local runs_info runs_info=$(curl -s "$runs_api") local build_num build_num=$(echo "$runs_info" | grep -o '"run_number": [0-9]*' | head -1 | grep -o '[0-9]*') if [ -z "$build_num" ]; then build_num="0" fi echo "$build_num" } # 解析命令行参数 SPECIFIED_VERSION="" while [[ $# -gt 0 ]]; do case $1 in -v|--version) SPECIFIED_VERSION="$2" shift 2 ;; -l|--list) list_installed exit 0 ;; -h|--help) show_help exit 0 ;; *) echo -e "${RED}❌ 未知参数: $1${NC}" show_help exit 1 ;; esac done # 获取 release 信息 if [ -n "$SPECIFIED_VERSION" ]; then echo "🔍 正在获取指定版本 v$SPECIFIED_VERSION..." SPECIFIED_VERSION=$(echo "$SPECIFIED_VERSION" | sed 's/^v//') GITHUB_API="https://api.github.com/repos/$GITHUB_REPO/releases/tags/v$SPECIFIED_VERSION" else echo "🔍 正在检查最新版本..." GITHUB_API="https://api.github.com/repos/$GITHUB_REPO/releases/latest" fi RELEASE_INFO=$(curl -s "$GITHUB_API") # 检查是否找到 release if echo "$RELEASE_INFO" | grep -q '"message": "Not Found"'; then echo -e "${RED}❌ 未找到版本: v${SPECIFIED_VERSION}${NC}" exit 1 fi # 解析版本号 VERSION=$(echo "$RELEASE_INFO" | grep -o '"tag_name": "[^"]*' | cut -d'"' -f4 | sed 's/^v//') if [ -z "$VERSION" ]; then echo -e "${RED}❌ 无法获取版本信息${NC}" exit 1 fi echo -e "${BLUE}📦 目标版本: v$VERSION${NC}" # 通过 Git Refs API 获取准确的 commit hash echo "🔍 正在获取准确的 commit hash..." COMMIT_SHA=$(get_tag_commit "$VERSION") if [ -z "$COMMIT_SHA" ]; then echo -e "${YELLOW}⚠️ 无法通过 Git API 获取 commit,尝试使用 release 中的信息...${NC}" COMMIT_SHA=$(echo "$RELEASE_INFO" | grep -o '"target_commitish": "[^"]*' | cut -d'"' -f4) if [ "$COMMIT_SHA" = "main" ] || [ "$COMMIT_SHA" = "master" ]; then echo -e "${RED}❌ 无法获取准确的 commit hash${NC}" exit 1 fi fi echo -e "${BLUE}🔖 Commit: ${COMMIT_SHA:0:12}...${NC}" echo "🔍 正在获取构建号..." BUILD_NUM=$(get_build_number "$COMMIT_SHA") if [ "$BUILD_NUM" = "0" ]; then echo -e "${YELLOW}⚠️ 无法获取构建号,使用默认值 0${NC}" else echo -e "${BLUE}🔢 构建号: $BUILD_NUM${NC}" fi # 构建目标文件名 TARGET_NAME="zed-remote-server-stable-${VERSION}+stable.${BUILD_NUM}.${COMMIT_SHA}" TARGET_PATH="$ZED_SERVER_DIR/$TARGET_NAME" # 检查目标版本是否已存在 if [ -f "$TARGET_PATH" ]; then echo "" echo -e "${GREEN}✅ 版本已存在,跳过下载${NC}" echo "📍 位置: $TARGET_PATH" exit 0 fi echo "" echo -e "${YELLOW}⬇️ 准备下载...${NC}" # 获取 assets 列表 ASSETS_URL=$(echo "$RELEASE_INFO" | grep -o '"assets_url": "[^"]*' | cut -d'"' -f4) ASSETS=$(curl -s "$ASSETS_URL") # 查找对应架构的远程服务器包 FILENAME_PATTERN="zed-remote-server-linux-${ARCH}" DOWNLOAD_URL=$(echo "$ASSETS" | grep -o '"browser_download_url": "[^"]*' | grep "$FILENAME_PATTERN" | head -1 | cut -d'"' -f4) if [ -z "$DOWNLOAD_URL" ]; then echo -e "${RED}❌ 未找到适合 ${ARCH} 架构的远程服务器包${NC}" exit 1 fi FILENAME=$(basename "$DOWNLOAD_URL") echo "📥 下载文件: $FILENAME" # 创建目录 mkdir -p "$ZED_SERVER_DIR" # 下载文件 TEMP_DIR=$(mktemp -d) TEMP_FILE="$TEMP_DIR/$FILENAME" echo "⬇️ 正在下载..." curl -L --progress-bar -o "$TEMP_FILE" "$DOWNLOAD_URL" if [ ! -f "$TEMP_FILE" ]; then echo -e "${RED}❌ 下载失败${NC}" rm -rf "$TEMP_DIR" exit 1 fi # 解压 echo "📂 正在解压..." gunzip -f "$TEMP_FILE" EXTRACTED_FILE="${TEMP_FILE%.gz}" # 移动到目标路径 if [ -f "$TARGET_PATH" ]; then echo -e "${YELLOW}⚠️ 检测到目标文件已存在,跳过移动${NC}" rm -f "$EXTRACTED_FILE" else mv "$EXTRACTED_FILE" "$TARGET_PATH" chmod +x "$TARGET_PATH" echo -e "${GREEN}✅ 安装完成!${NC}" fi # 清理临时文件 rm -rf "$TEMP_DIR" echo "📍 位置: $TARGET_PATH" # 验证安装 echo "🔍 验证..." if "$TARGET_PATH" version 2>/dev/null; then : else echo "(该版本可能不支持 --version 参数,但文件已就绪)" fi echo "" echo -e "${GREEN}💡 使用提示:${NC}" echo " 完整路径: $TARGET_PATH"