99 lines
4.4 KiB
Bash
Executable File
99 lines
4.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -Eeuo pipefail
|
|
|
|
REPO_URL=${PLUGIN_REPO_URL:-https://git.awaioi.com/awaioi/sub2api-add.git}
|
|
SOURCE_DIR=${PLUGIN_SOURCE_DIR:-/opt/sub2api-add}
|
|
REF=${PLUGIN_REF:-v1.1.1}
|
|
EXPECTED_SHA=${PLUGIN_COMMIT_SHA:-}
|
|
ALLOW_MUTABLE_REF=${PLUGIN_ALLOW_MUTABLE_REF:-false}
|
|
DEPLOY_ENV=${PLUGIN_ENV:-production}
|
|
ALLOW_UNPINNED_TAG=${PLUGIN_ALLOW_UNPINNED_TAG:-false}
|
|
|
|
die() { printf '错误:%s\n' "$*" >&2; exit 1; }
|
|
|
|
validate_path_components() {
|
|
local value=$1 label=$2 component current=""
|
|
[[ -n "$value" && "$value" = /* && "$value" != "/" ]] || die "$label 必须是非根绝对路径"
|
|
[[ "$value" != *$'\n'* && "$value" != *$'\r'* ]] || die "$label 包含非法换行"
|
|
local parts=()
|
|
IFS='/' read -r -a parts <<< "${value#/}"
|
|
for component in "${parts[@]}"; do
|
|
[[ -z "$component" ]] && continue
|
|
[[ "$component" != "." && "$component" != ".." ]] || die "$label 不能包含 . 或 .. 路径组件"
|
|
current="$current/$component"
|
|
[[ ! -L "$current" ]] || die "$label 的路径组件不能是符号链接:$current"
|
|
[[ ! -e "$current" || -d "$current" ]] || die "$label 的路径组件不是目录:$current"
|
|
done
|
|
}
|
|
|
|
ensure_real_parent() {
|
|
local path=$1 label=$2 parent
|
|
parent=$(dirname -- "$path")
|
|
[[ -d "$parent" && ! -L "$parent" ]] || die "$label 的父目录必须是已存在的真实目录:$parent"
|
|
}
|
|
|
|
validate_path_components "$SOURCE_DIR" PLUGIN_SOURCE_DIR
|
|
ensure_real_parent "$SOURCE_DIR" PLUGIN_SOURCE_DIR
|
|
if [[ "$SOURCE_DIR" != */sub2api-add && "${PLUGIN_ALLOW_CUSTOM_PATHS:-false}" != "true" ]]; then
|
|
die "PLUGIN_SOURCE_DIR 必须以 sub2api-add 结尾;如确需自定义路径请显式设置 PLUGIN_ALLOW_CUSTOM_PATHS=true"
|
|
fi
|
|
[[ $EUID -eq 0 ]] || die "请使用 root 或 sudo 运行"
|
|
command -v git >/dev/null 2>&1 || die "缺少 git"
|
|
|
|
is_sha() { [[ "$1" =~ ^[0-9a-fA-F]{40}$ ]]; }
|
|
is_release_tag() { [[ "$1" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z.-]+)?$ ]]; }
|
|
[[ "$DEPLOY_ENV" == "development" || "$DEPLOY_ENV" == "production" ]] || die "PLUGIN_ENV 必须是 development 或 production"
|
|
if [[ -n "$EXPECTED_SHA" ]] && ! is_sha "$EXPECTED_SHA"; then
|
|
die "PLUGIN_COMMIT_SHA 必须是 40 位 commit SHA"
|
|
fi
|
|
if [[ "$ALLOW_MUTABLE_REF" == "true" && "$DEPLOY_ENV" != "development" ]]; then
|
|
die "PLUGIN_ALLOW_MUTABLE_REF=true 仅允许在 PLUGIN_ENV=development 使用"
|
|
fi
|
|
if ! is_sha "$REF" && ! is_release_tag "$REF" && [[ "$ALLOW_MUTABLE_REF" != "true" ]]; then
|
|
die "默认只接受不可变 commit SHA 或版本 tag;开发环境显式设置 PLUGIN_ALLOW_MUTABLE_REF=true 才能使用分支"
|
|
fi
|
|
if [[ -z "$EXPECTED_SHA" ]] && is_release_tag "$REF"; then
|
|
if [[ "$DEPLOY_ENV" != "development" || "$ALLOW_UNPINNED_TAG" != "true" ]]; then
|
|
die "使用版本 tag 时必须设置 PLUGIN_COMMIT_SHA;仅开发环境显式设置 PLUGIN_ALLOW_UNPINNED_TAG=true 才能跳过 pin"
|
|
fi
|
|
fi
|
|
if [[ "$ALLOW_UNPINNED_TAG" == "true" && "$DEPLOY_ENV" != "development" ]]; then
|
|
die "PLUGIN_ALLOW_UNPINNED_TAG=true 仅允许在 PLUGIN_ENV=development 使用"
|
|
fi
|
|
|
|
if [[ -e "$SOURCE_DIR" && ! -d "$SOURCE_DIR/.git" ]]; then
|
|
die "$SOURCE_DIR 已存在但不是本插件仓库;请设置 PLUGIN_SOURCE_DIR"
|
|
fi
|
|
|
|
if [[ ! -e "$SOURCE_DIR" ]]; then
|
|
ensure_real_parent "$SOURCE_DIR" PLUGIN_SOURCE_DIR
|
|
fi
|
|
|
|
if [[ -d "$SOURCE_DIR/.git" ]]; then
|
|
if [[ -n "$(git -C "$SOURCE_DIR" status --porcelain)" ]]; then
|
|
die "$SOURCE_DIR 有未提交修改,先清理后再升级"
|
|
fi
|
|
git -C "$SOURCE_DIR" fetch --depth 1 --no-tags origin "$REF"
|
|
git -C "$SOURCE_DIR" checkout --force FETCH_HEAD
|
|
else
|
|
if is_sha "$REF"; then
|
|
git clone --depth 1 --no-tags "$REPO_URL" "$SOURCE_DIR"
|
|
git -C "$SOURCE_DIR" fetch --depth 1 --no-tags origin "$REF"
|
|
git -C "$SOURCE_DIR" checkout --force FETCH_HEAD
|
|
else
|
|
git clone --depth 1 --no-tags --branch "$REF" "$REPO_URL" "$SOURCE_DIR"
|
|
fi
|
|
fi
|
|
|
|
RESOLVED_SHA=$(git -C "$SOURCE_DIR" rev-parse HEAD)
|
|
NORMALIZED_RESOLVED_SHA=$(printf '%s' "$RESOLVED_SHA" | tr '[:upper:]' '[:lower:]')
|
|
NORMALIZED_EXPECTED_SHA=$(printf '%s' "$EXPECTED_SHA" | tr '[:upper:]' '[:lower:]')
|
|
if [[ -n "$EXPECTED_SHA" && "$NORMALIZED_RESOLVED_SHA" != "$NORMALIZED_EXPECTED_SHA" ]]; then
|
|
die "检出的 commit 与 PLUGIN_COMMIT_SHA 不一致:$RESOLVED_SHA"
|
|
fi
|
|
if ! is_sha "$REF" && ! is_release_tag "$REF" && [[ "$ALLOW_MUTABLE_REF" == "true" ]]; then
|
|
printf '%s\n' '警告:当前使用可变 Git ref,仅限开发环境。' >&2
|
|
fi
|
|
|
|
exec "$SOURCE_DIR/scripts/install-local.sh" "$@"
|