first commit

This commit is contained in:
Your Name
2026-09-08 11:40:15 +08:00
commit a5353f7eb5
9568 changed files with 1646214 additions and 0 deletions
+152
View File
@@ -0,0 +1,152 @@
#!/usr/bin/env bash
set -euo pipefail
script_dir="$(cd "$(dirname "$0")" && pwd -P)"
project_root="$(cd "$script_dir/.." && pwd -P)"
# shellcheck source=macos_helpers.sh
source "$script_dir/macos_helpers.sh"
macos_install_exit_trap 1
macos_require_darwin
/bin/bash "$script_dir/check_macos_entrypoints.sh"
NODE_BIN=""
NPM_BIN=""
use_node_pair() {
local node_candidate="$1"
local npm_candidate="$2"
local major version
[[ -x "$node_candidate" && -x "$npm_candidate" ]] || return 1
version="$("$node_candidate" --version 2>/dev/null || true)"
major="${version#v}"
major="${major%%.*}"
case "$major" in
''|*[!0-9]*) return 1 ;;
esac
[[ "$major" -ge 20 ]] || return 1
NODE_BIN="$node_candidate"
NPM_BIN="$npm_candidate"
export PATH="$(dirname "$NODE_BIN"):$PATH"
}
locate_node() {
local bin_dir node_candidate npm_candidate
node_candidate="$(command -v node 2>/dev/null || true)"
npm_candidate="$(command -v npm 2>/dev/null || true)"
if use_node_pair "$node_candidate" "$npm_candidate"; then
return 0
fi
for bin_dir in /opt/homebrew/bin /usr/local/bin; do
if use_node_pair "$bin_dir/node" "$bin_dir/npm"; then
return 0
fi
done
if [[ -n "${HOME:-}" ]]; then
for node_candidate in "$HOME"/.nvm/versions/node/*/bin/node; do
[[ -x "$node_candidate" ]] || continue
npm_candidate="$(dirname "$node_candidate")/npm"
if use_node_pair "$node_candidate" "$npm_candidate"; then
return 0
fi
done
fi
return 1
}
install_local_node() {
local architecture archive archive_path cache_root curl_bin download_dir
local expected extracted install_dir node_version shasums_path actual
node_version="${DOCTOR_NODE_VERSION:-22.14.0}"
case "$(uname -m)" in
arm64) architecture="arm64" ;;
x86_64) architecture="x64" ;;
*) macos_die "不支持的 Mac CPU 架构:$(uname -m)" ;;
esac
if [[ -n "${XDG_CACHE_HOME:-}" ]]; then
cache_root="$XDG_CACHE_HOME/DoctorWorkstation/tools"
elif [[ -n "${HOME:-}" ]]; then
cache_root="$HOME/Library/Caches/DoctorWorkstation/tools"
else
macos_die "无法确定 Node 工具缓存目录:HOME 与 XDG_CACHE_HOME 均未设置。"
fi
install_dir="$cache_root/node-v$node_version-darwin-$architecture"
if use_node_pair "$install_dir/bin/node" "$install_dir/bin/npm"; then
return 0
fi
if [[ -e "$install_dir" ]]; then
macos_die "Node 缓存不完整,请删除后重试:$install_dir"
fi
curl_bin="$(command -v curl 2>/dev/null || true)"
[[ -n "$curl_bin" ]] || macos_die "未找到用于下载 Node.js 的 curl。"
mkdir -p "$cache_root"
download_dir="$(mktemp -d "$cache_root/doctor-node.XXXXXX")"
macos_register_temp_dir "$download_dir"
archive="node-v$node_version-darwin-$architecture.tar.gz"
archive_path="$download_dir/$archive"
shasums_path="$download_dir/SHASUMS256.txt"
printf '未检测到 Node.js 20+ 与 npm,正在下载 Node.js %s%s)…\n' \
"$node_version" "$architecture"
if ! "$curl_bin" --proto '=https' --tlsv1.2 -fsSL \
"https://nodejs.org/dist/v$node_version/$archive" -o "$archive_path"; then
macos_die "Node.js 下载失败,请检查网络后重试。"
fi
if ! "$curl_bin" --proto '=https' --tlsv1.2 -fsSL \
"https://nodejs.org/dist/v$node_version/SHASUMS256.txt" -o "$shasums_path"; then
macos_die "Node.js 校验文件下载失败。"
fi
expected="$(/usr/bin/awk -v file="$archive" '$2 == file { print $1; exit }' "$shasums_path")"
actual="$(/usr/bin/shasum -a 256 "$archive_path" | /usr/bin/awk '{print $1}')"
[[ -n "$expected" && "$actual" == "$expected" ]] || macos_die "Node.js 下载包 SHA-256 校验失败。"
/usr/bin/tar -xzf "$archive_path" -C "$download_dir"
extracted="$download_dir/node-v$node_version-darwin-$architecture"
[[ -d "$extracted" ]] || macos_die "Node.js 下载包结构无效。"
if [[ ! -e "$install_dir" ]]; then
/bin/mv "$extracted" "$install_dir"
fi
use_node_pair "$install_dir/bin/node" "$install_dir/bin/npm" || \
macos_die "Node.js 安装完成,但 node/npm 无法执行。"
}
macos_ensure_uv
cd "$project_root"
printf '正在同步 Python 与 PyInstaller 构建依赖…\n'
"$MACOS_UV_BIN" sync --locked --extra build
python_bin="$project_root/.venv/bin/python"
[[ -x "$python_bin" ]] || macos_die "uv 未生成可用的构建 Python$python_bin"
locate_node || install_local_node
printf 'Node.js: %snpm: %s\n' \
"$("$NODE_BIN" --version)" "$("$NPM_BIN" --version)"
printf '正在安装锁定的 companion 依赖…\n'
"$NPM_BIN" ci --prefix "$project_root/video_companion" --no-audit --no-fund
printf '正在构建 DoctorWorkstation.app…\n'
PYINSTALLER_PYTHON="$python_bin" SKIP_FRONTEND_INSTALL=1 \
/bin/bash "$script_dir/build_macos.sh"
artifact="$project_root/dist/DoctorWorkstation.app"
project_version="$(/usr/bin/awk -F '"' '/^version = "/ { print $2; exit }' \
"$project_root/pyproject.toml")"
[[ -n "$project_version" ]] || macos_die "无法从 pyproject.toml 读取版本号。"
case "$(uname -m)" in
arm64) release_arch="arm64" ;;
x86_64) release_arch="x64" ;;
*) macos_die "不支持的 Mac CPU 架构:$(uname -m)" ;;
esac
release_zip="$project_root/dist/DoctorWorkstation-macOS-$release_arch-$project_version.zip"
checksum_file="$release_zip.sha256"
rm -f -- "$release_zip" "$checksum_file"
printf '正在生成可分发 ZIP…\n'
/usr/bin/ditto -c -k --sequesterRsrc --keepParent "$artifact" "$release_zip"
release_hash="$(/usr/bin/shasum -a 256 "$release_zip" | /usr/bin/awk '{print $1}')"
printf '%s %s\n' "$release_hash" "$(basename "$release_zip")" >"$checksum_file"
printf '\n打包成功:%s\n' "$artifact"
printf '分发包:%s\n' "$release_zip"
printf 'SHA-256%s\n' "$release_hash"