forked from hesabix/arc
546 lines
20 KiB
Shell
546 lines
20 KiB
Shell
#!/usr/bin/env bash
|
|
# Shared PyPI / Flutter mirror presets and prompts for deploy.sh, update.sh, build_web.sh.
|
|
# Non-interactive: PIP_MIRROR=hesabix|official|tuna|aliyun|custom
|
|
# FLUTTER_MIRROR=hesabix|pub_azs|flutter_io_cn|tuna|sjtu|official|custom
|
|
# Direct URL override (advanced): PIP_INDEX_URL, PUB_HOSTED_URL, FLUTTER_STORAGE_BASE_URL
|
|
# China fallback: Aliyun extra-index (sanctions-safe; reachable from Iran) unless PIP_DISABLE_CHINA_FALLBACK=1.
|
|
|
|
# shellcheck disable=SC2034
|
|
HESABIX_PIP_INDEX_URL="https://p.mirror.hesabix.ir/simple"
|
|
HESABIX_PIP_TRUSTED_HOST="p.mirror.hesabix.ir"
|
|
HESABIX_PIP_CHINA_INDEX_URL="https://mirrors.aliyun.com/pypi/simple"
|
|
HESABIX_PIP_CHINA_TRUSTED_HOST="mirrors.aliyun.com"
|
|
HESABIX_PIP_CHINA_SECONDARY_INDEX_URL="https://mirrors.cloud.tencent.com/pypi/simple"
|
|
HESABIX_PUB_HOSTED_URL="https://f.mirror.hesabix.ir/pub"
|
|
HESABIX_FLUTTER_STORAGE_BASE_URL="https://f.mirror.hesabix.ir/gcs"
|
|
|
|
hesabix_mirror_log_info() {
|
|
if declare -F log_info >/dev/null 2>&1; then
|
|
log_info "$@"
|
|
else
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
|
|
fi
|
|
}
|
|
|
|
hesabix_mirror_log_warning() {
|
|
if declare -F log_warning >/dev/null 2>&1; then
|
|
log_warning "$@"
|
|
elif declare -F log_warn >/dev/null 2>&1; then
|
|
log_warn "$@"
|
|
else
|
|
echo "WARNING: $*" >&2
|
|
fi
|
|
}
|
|
|
|
# Normalize pip index URL (ensure /simple suffix for custom input).
|
|
hesabix_normalize_pip_index_url() {
|
|
local url="${1%/}"
|
|
case "${url}" in
|
|
*/simple) printf '%s' "${url}" ;;
|
|
*) printf '%s/simple' "${url}" ;;
|
|
esac
|
|
}
|
|
|
|
hesabix_pip_trusted_host_from_url() {
|
|
local index_url="$1"
|
|
if [[ "${index_url}" == *"pypi.org"* ]]; then
|
|
return 0
|
|
fi
|
|
echo "${index_url}" | sed -n 's|https\?://\([^/]*\).*|\1|p'
|
|
}
|
|
|
|
hesabix_set_pip_mirror_for_url() {
|
|
local index_url
|
|
index_url="$(hesabix_normalize_pip_index_url "$1")"
|
|
export PIP_INDEX_URL="${index_url}"
|
|
if [[ "${index_url}" != *"pypi.org"* ]]; then
|
|
export PIP_TRUSTED_HOST="$(hesabix_pip_trusted_host_from_url "${index_url}")"
|
|
else
|
|
unset PIP_TRUSTED_HOST
|
|
fi
|
|
}
|
|
|
|
hesabix_pip_append_trusted_host() {
|
|
local host="$1"
|
|
[[ -n "${host}" ]] || return 0
|
|
case " ${PIP_TRUSTED_HOST:-} " in
|
|
*" ${host} "*) return 0 ;;
|
|
esac
|
|
if [[ -n "${PIP_TRUSTED_HOST:-}" ]]; then
|
|
export PIP_TRUSTED_HOST="${PIP_TRUSTED_HOST} ${host}"
|
|
else
|
|
export PIP_TRUSTED_HOST="${host}"
|
|
fi
|
|
}
|
|
|
|
# Attach a Chinese extra-index so incomplete/sanctioned primary mirrors still resolve setuptools etc.
|
|
hesabix_apply_pip_china_fallback() {
|
|
if [[ "${PIP_DISABLE_CHINA_FALLBACK:-0}" == "1" ]]; then
|
|
return 0
|
|
fi
|
|
local china="${HESABIX_PIP_CHINA_INDEX_URL}"
|
|
local primary="${PIP_INDEX_URL:-}"
|
|
if [[ -z "${PIP_EXTRA_INDEX_URL:-}" ]]; then
|
|
if [[ "${primary}" == "${china}" ]]; then
|
|
export PIP_EXTRA_INDEX_URL="${HESABIX_PIP_CHINA_SECONDARY_INDEX_URL}"
|
|
hesabix_pip_append_trusted_host "mirrors.cloud.tencent.com"
|
|
else
|
|
export PIP_EXTRA_INDEX_URL="${china}"
|
|
hesabix_pip_append_trusted_host "${HESABIX_PIP_CHINA_TRUSTED_HOST}"
|
|
fi
|
|
else
|
|
local extra_host
|
|
extra_host="$(hesabix_pip_trusted_host_from_url "${PIP_EXTRA_INDEX_URL%% *}")"
|
|
[[ -n "${extra_host}" ]] && hesabix_pip_append_trusted_host "${extra_host}"
|
|
fi
|
|
hesabix_mirror_log_info "PyPI extra index (China fallback): ${PIP_EXTRA_INDEX_URL}"
|
|
}
|
|
|
|
hesabix_pip_index_fallback_urls() {
|
|
local -a urls=()
|
|
local u
|
|
[[ -n "${PIP_INDEX_URL:-}" ]] && urls+=("${PIP_INDEX_URL}")
|
|
[[ -n "${PIP_EXTRA_INDEX_URL:-}" ]] && urls+=("${PIP_EXTRA_INDEX_URL%% *}")
|
|
urls+=("${HESABIX_PIP_CHINA_INDEX_URL}" "${HESABIX_PIP_CHINA_SECONDARY_INDEX_URL}" "${HESABIX_PIP_INDEX_URL}")
|
|
local -A seen=()
|
|
for u in "${urls[@]}"; do
|
|
u="${u%/}"
|
|
[[ -n "$u" && -z "${seen[$u]:-}" ]] || continue
|
|
seen[$u]=1
|
|
printf '%s\n' "$u"
|
|
done
|
|
}
|
|
|
|
# Usage: hesabix_pip_cmd_with_fallback <pip-binary> <pip args...>
|
|
hesabix_pip_cmd_with_fallback() {
|
|
local pip_bin="$1"
|
|
shift
|
|
if [[ "${PIP_DISABLE_CHINA_FALLBACK:-0}" == "1" ]]; then
|
|
"${pip_bin}" "$@"
|
|
return $?
|
|
fi
|
|
if "${pip_bin}" "$@"; then
|
|
return 0
|
|
fi
|
|
local url orig_index orig_extra orig_trust
|
|
orig_index="${PIP_INDEX_URL:-}"
|
|
orig_extra="${PIP_EXTRA_INDEX_URL:-}"
|
|
orig_trust="${PIP_TRUSTED_HOST:-}"
|
|
while IFS= read -r url; do
|
|
[[ -n "$url" ]] || continue
|
|
[[ "$url" == "${orig_index}" ]] && continue
|
|
hesabix_mirror_log_warning "pip failed on ${orig_index:-<unset>}; retrying ${url}"
|
|
hesabix_set_pip_mirror_for_url "$url"
|
|
if [[ "$url" == "${HESABIX_PIP_CHINA_INDEX_URL}" ]]; then
|
|
export PIP_EXTRA_INDEX_URL="${HESABIX_PIP_CHINA_SECONDARY_INDEX_URL}"
|
|
else
|
|
export PIP_EXTRA_INDEX_URL="${HESABIX_PIP_CHINA_INDEX_URL}"
|
|
fi
|
|
hesabix_pip_append_trusted_host "$(hesabix_pip_trusted_host_from_url "${PIP_EXTRA_INDEX_URL}")"
|
|
if "${pip_bin}" "$@"; then
|
|
hesabix_mirror_log_info "pip succeeded from ${url}"
|
|
return 0
|
|
fi
|
|
done < <(hesabix_pip_index_fallback_urls)
|
|
export PIP_INDEX_URL="${orig_index}"
|
|
export PIP_EXTRA_INDEX_URL="${orig_extra}"
|
|
export PIP_TRUSTED_HOST="${orig_trust}"
|
|
return 1
|
|
}
|
|
|
|
hesabix_resolve_pip_mirror_from_preset() {
|
|
local preset="${1:-hesabix}"
|
|
preset="${preset,,}"
|
|
case "${preset}" in
|
|
hesabix|default)
|
|
hesabix_set_pip_mirror_for_url "${HESABIX_PIP_INDEX_URL}"
|
|
;;
|
|
official|pypi)
|
|
hesabix_set_pip_mirror_for_url "https://pypi.org/simple"
|
|
;;
|
|
tuna|tsinghua)
|
|
hesabix_set_pip_mirror_for_url "https://pypi.tuna.tsinghua.edu.cn/simple"
|
|
;;
|
|
aliyun)
|
|
hesabix_set_pip_mirror_for_url "https://mirrors.aliyun.com/pypi/simple"
|
|
;;
|
|
custom)
|
|
if [[ -z "${PIP_INDEX_URL:-}" ]]; then
|
|
hesabix_mirror_log_warning "PIP_MIRROR=custom but PIP_INDEX_URL is empty; falling back to Hesabix."
|
|
PIP_MIRROR=hesabix
|
|
export PIP_MIRROR
|
|
hesabix_set_pip_mirror_for_url "${HESABIX_PIP_INDEX_URL}"
|
|
return 0
|
|
fi
|
|
hesabix_set_pip_mirror_for_url "${PIP_INDEX_URL}"
|
|
;;
|
|
*)
|
|
hesabix_mirror_log_warning "Unknown PIP_MIRROR='${preset}'; using Hesabix."
|
|
PIP_MIRROR=hesabix
|
|
export PIP_MIRROR
|
|
hesabix_set_pip_mirror_for_url "${HESABIX_PIP_INDEX_URL}"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
hesabix_resolve_flutter_mirror_from_preset() {
|
|
local preset="${1:-hesabix}"
|
|
preset="${preset,,}"
|
|
case "${preset}" in
|
|
hesabix|default)
|
|
export PUB_HOSTED_URL="${HESABIX_PUB_HOSTED_URL}"
|
|
export FLUTTER_STORAGE_BASE_URL="${HESABIX_FLUTTER_STORAGE_BASE_URL}"
|
|
;;
|
|
pub_azs|pub-azs|azs)
|
|
export PUB_HOSTED_URL="https://pub-azs.ir"
|
|
export FLUTTER_STORAGE_BASE_URL="https://pub-azs.ir"
|
|
;;
|
|
flutter_io_cn|china|flutter-io)
|
|
export PUB_HOSTED_URL="https://pub.flutter-io.cn"
|
|
export FLUTTER_STORAGE_BASE_URL="https://storage.flutter-io.cn"
|
|
;;
|
|
tuna|tsinghua)
|
|
export PUB_HOSTED_URL="https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
|
|
export FLUTTER_STORAGE_BASE_URL="https://mirrors.tuna.tsinghua.edu.cn/flutter"
|
|
;;
|
|
sjtu)
|
|
export PUB_HOSTED_URL="https://mirror.sjtu.edu.cn/dart-pub"
|
|
export FLUTTER_STORAGE_BASE_URL="https://mirror.sjtu.edu.cn"
|
|
;;
|
|
official|pubdev)
|
|
export PUB_HOSTED_URL="https://pub.dev"
|
|
export FLUTTER_STORAGE_BASE_URL="https://storage.googleapis.com"
|
|
;;
|
|
custom)
|
|
if [[ -z "${PUB_HOSTED_URL:-}" || -z "${FLUTTER_STORAGE_BASE_URL:-}" ]]; then
|
|
hesabix_mirror_log_warning "FLUTTER_MIRROR=custom but PUB_HOSTED_URL/FLUTTER_STORAGE_BASE_URL missing; falling back to Hesabix."
|
|
FLUTTER_MIRROR=hesabix
|
|
export FLUTTER_MIRROR
|
|
export PUB_HOSTED_URL="${HESABIX_PUB_HOSTED_URL}"
|
|
export FLUTTER_STORAGE_BASE_URL="${HESABIX_FLUTTER_STORAGE_BASE_URL}"
|
|
return 0
|
|
fi
|
|
export PUB_HOSTED_URL FLUTTER_STORAGE_BASE_URL
|
|
;;
|
|
*)
|
|
hesabix_mirror_log_warning "Unknown FLUTTER_MIRROR='${preset}'; using Hesabix."
|
|
FLUTTER_MIRROR=hesabix
|
|
export FLUTTER_MIRROR
|
|
export PUB_HOSTED_URL="${HESABIX_PUB_HOSTED_URL}"
|
|
export FLUTTER_STORAGE_BASE_URL="${HESABIX_FLUTTER_STORAGE_BASE_URL}"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Apply pip mirror: env PIP_INDEX_URL wins; else PIP_MIRROR preset; else Hesabix.
|
|
# Always attach a Chinese extra-index unless PIP_DISABLE_CHINA_FALLBACK=1.
|
|
hesabix_apply_pip_mirror_env() {
|
|
if [[ -n "${PIP_INDEX_URL:-}" ]]; then
|
|
hesabix_mirror_log_info "Using PyPI index from environment: PIP_INDEX_URL=${PIP_INDEX_URL}"
|
|
hesabix_set_pip_mirror_for_url "${PIP_INDEX_URL}"
|
|
hesabix_apply_pip_china_fallback
|
|
return 0
|
|
fi
|
|
PIP_MIRROR="${PIP_MIRROR:-hesabix}"
|
|
export PIP_MIRROR
|
|
hesabix_resolve_pip_mirror_from_preset "${PIP_MIRROR}"
|
|
hesabix_apply_pip_china_fallback
|
|
hesabix_mirror_log_info "Using PyPI mirror (${PIP_MIRROR}): ${PIP_INDEX_URL}"
|
|
}
|
|
|
|
# Apply Flutter mirror: explicit URLs win; else FLUTTER_MIRROR preset; else Hesabix.
|
|
# Note: callers that need a reachable mirror should also run
|
|
# hesabix_resolve_flutter_pub_hosted_url / hesabix_resolve_flutter_storage_base_url
|
|
# (saved "official"/pub.dev often returns HTTP 403 from filtered networks).
|
|
hesabix_apply_flutter_mirror_env() {
|
|
if [[ -n "${PUB_HOSTED_URL:-}" && -n "${FLUTTER_STORAGE_BASE_URL:-}" ]]; then
|
|
export PUB_HOSTED_URL FLUTTER_STORAGE_BASE_URL
|
|
hesabix_mirror_log_info "Using Flutter mirrors from environment: PUB_HOSTED_URL=${PUB_HOSTED_URL}"
|
|
return 0
|
|
fi
|
|
FLUTTER_MIRROR="${FLUTTER_MIRROR:-hesabix}"
|
|
export FLUTTER_MIRROR
|
|
hesabix_resolve_flutter_mirror_from_preset "${FLUTTER_MIRROR}"
|
|
hesabix_mirror_log_info "Flutter pub/storage (${FLUTTER_MIRROR}): PUB_HOSTED_URL=${PUB_HOSTED_URL}"
|
|
}
|
|
|
|
# Ordered Flutter engine/storage bases (preferred env URL first).
|
|
hesabix_flutter_storage_fallback_bases() {
|
|
local -a bases=()
|
|
local b
|
|
if [[ -n "${FLUTTER_STORAGE_BASE_URL:-}" ]]; then
|
|
bases+=("${FLUTTER_STORAGE_BASE_URL%/}")
|
|
fi
|
|
bases+=(
|
|
"${HESABIX_FLUTTER_STORAGE_BASE_URL}"
|
|
"https://storage.flutter-io.cn"
|
|
"https://mirrors.tuna.tsinghua.edu.cn/flutter"
|
|
"https://storage.googleapis.com"
|
|
)
|
|
local -A seen=()
|
|
for b in "${bases[@]}"; do
|
|
[[ -n "$b" && -z "${seen[$b]:-}" ]] || continue
|
|
seen[$b]=1
|
|
printf '%s\n' "$b"
|
|
done
|
|
}
|
|
|
|
# Probe sky_engine.zip for the installed Flutter engine; print first working storage base.
|
|
hesabix_probe_flutter_storage_base() {
|
|
local flutter_root="${FLUTTER_STORAGE_PROBE_FLUTTER_ROOT:-/opt/flutter}"
|
|
local engine realm rel_path base url code
|
|
[[ -f "${flutter_root}/bin/internal/engine.version" ]] || return 1
|
|
engine="$(tr -d '\n\r' < "${flutter_root}/bin/internal/engine.version")"
|
|
[[ -n "$engine" ]] || return 1
|
|
realm=""
|
|
if [[ -f "${flutter_root}/bin/cache/engine.realm" ]]; then
|
|
realm="$(tr -d '[:space:]' < "${flutter_root}/bin/cache/engine.realm")"
|
|
fi
|
|
rel_path="flutter_infra_release/flutter/${engine}/sky_engine.zip"
|
|
while IFS= read -r base; do
|
|
[[ -n "$base" ]] || continue
|
|
base="${base%/}"
|
|
if [[ -n "$realm" ]]; then
|
|
url="${base}/${realm}/${rel_path}"
|
|
else
|
|
url="${base}/${rel_path}"
|
|
fi
|
|
code="$(curl -fsSI -o /dev/null -w '%{http_code}' --connect-timeout 8 --max-time 25 "$url" 2>/dev/null || true)"
|
|
code="${code:-000}"
|
|
if [[ "$code" == "200" ]]; then
|
|
printf '%s' "$base"
|
|
return 0
|
|
fi
|
|
done < <(hesabix_flutter_storage_fallback_bases)
|
|
return 1
|
|
}
|
|
|
|
# If the preferred storage mirror lacks engine artifacts, switch to a working fallback.
|
|
hesabix_resolve_flutter_storage_base_url() {
|
|
local preferred resolved
|
|
preferred="${FLUTTER_STORAGE_BASE_URL:-}"
|
|
hesabix_apply_flutter_mirror_env >/dev/null 2>&1 || true
|
|
preferred="${FLUTTER_STORAGE_BASE_URL:-${preferred}}"
|
|
resolved="$(hesabix_probe_flutter_storage_base)" || {
|
|
hesabix_mirror_log_warning "No Flutter storage mirror has sky_engine for the installed engine."
|
|
return 1
|
|
}
|
|
export FLUTTER_STORAGE_BASE_URL="${resolved}"
|
|
if [[ -n "${preferred}" && "${resolved}" != "${preferred%/}" ]]; then
|
|
hesabix_mirror_log_warning "Flutter storage fallback: ${preferred} → ${resolved} (engine artifacts missing on preferred mirror)"
|
|
else
|
|
hesabix_mirror_log_info "Flutter storage: ${resolved}"
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# Ordered pub hosted bases (preferred env URL first). pub.dev often returns 403 from
|
|
# sanctioned/filtered networks; Dart reports that as "authorization failed".
|
|
hesabix_flutter_pub_fallback_bases() {
|
|
local -a bases=()
|
|
local b
|
|
if [[ -n "${PUB_HOSTED_URL:-}" ]]; then
|
|
bases+=("${PUB_HOSTED_URL%/}")
|
|
fi
|
|
bases+=(
|
|
"${HESABIX_PUB_HOSTED_URL}"
|
|
"https://pub.flutter-io.cn"
|
|
"https://pub-azs.ir"
|
|
"https://mirrors.tuna.tsinghua.edu.cn/dart-pub"
|
|
"https://mirror.sjtu.edu.cn/dart-pub"
|
|
"https://pub.dev"
|
|
)
|
|
local -A seen=()
|
|
for b in "${bases[@]}"; do
|
|
b="${b%/}"
|
|
[[ -n "$b" && -z "${seen[$b]:-}" ]] || continue
|
|
seen[$b]=1
|
|
printf '%s\n' "$b"
|
|
done
|
|
}
|
|
|
|
# Probe a known package API; print first working PUB_HOSTED_URL base.
|
|
hesabix_probe_flutter_pub_hosted() {
|
|
local base url code
|
|
while IFS= read -r base; do
|
|
[[ -n "$base" ]] || continue
|
|
base="${base%/}"
|
|
url="${base}/api/packages/intl"
|
|
code="$(curl -fsSI -o /dev/null -w '%{http_code}' --connect-timeout 8 --max-time 20 "$url" 2>/dev/null || true)"
|
|
code="${code:-000}"
|
|
if [[ "$code" == "200" ]]; then
|
|
printf '%s' "$base"
|
|
return 0
|
|
fi
|
|
done < <(hesabix_flutter_pub_fallback_bases)
|
|
return 1
|
|
}
|
|
|
|
# If the preferred pub mirror is blocked/unreachable, switch to a working fallback.
|
|
hesabix_resolve_flutter_pub_hosted_url() {
|
|
local preferred resolved
|
|
preferred="${PUB_HOSTED_URL:-}"
|
|
hesabix_apply_flutter_mirror_env >/dev/null 2>&1 || true
|
|
preferred="${PUB_HOSTED_URL:-${preferred}}"
|
|
resolved="$(hesabix_probe_flutter_pub_hosted)" || {
|
|
hesabix_mirror_log_warning "No Flutter pub mirror can serve package metadata (intl)."
|
|
return 1
|
|
}
|
|
export PUB_HOSTED_URL="${resolved}"
|
|
if [[ -n "${preferred}" && "${resolved}" != "${preferred%/}" ]]; then
|
|
hesabix_mirror_log_warning "Flutter pub fallback: ${preferred} → ${resolved} (preferred blocked or unreachable)"
|
|
else
|
|
hesabix_mirror_log_info "Flutter pub: ${resolved}"
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
hesabix_configure_pip_mirror() {
|
|
if ! command -v python3 >/dev/null 2>&1; then
|
|
return 0
|
|
fi
|
|
hesabix_apply_pip_mirror_env
|
|
python3 -m pip config --user set global.index "${PIP_INDEX_URL}" 2>/dev/null || true
|
|
python3 -m pip config --user set global.index-url "${PIP_INDEX_URL}" 2>/dev/null || true
|
|
local primary_host
|
|
primary_host="$(hesabix_pip_trusted_host_from_url "${PIP_INDEX_URL}")"
|
|
if [[ -n "${primary_host}" ]]; then
|
|
python3 -m pip config --user set global.trusted-host "${primary_host}" 2>/dev/null || true
|
|
fi
|
|
if [[ -n "${PIP_EXTRA_INDEX_URL:-}" ]]; then
|
|
python3 -m pip config --user set global.extra-index-url "${PIP_EXTRA_INDEX_URL%% *}" 2>/dev/null || true
|
|
fi
|
|
hesabix_mirror_log_info "pip user config: ${PIP_INDEX_URL}"
|
|
}
|
|
|
|
hesabix_prompt_pip_mirror() {
|
|
if [[ -n "${PIP_INDEX_URL:-}" ]]; then
|
|
return 0
|
|
fi
|
|
PIP_MIRROR="${PIP_MIRROR:-}"
|
|
PIP_MIRROR="${PIP_MIRROR,,}"
|
|
if [[ -n "${PIP_MIRROR}" ]]; then
|
|
return 0
|
|
fi
|
|
echo
|
|
echo "مخزن پایتون (pip / PyPI) — برای نصب وابستگیهای بکاند:"
|
|
echo " [1] Hesabix — p.mirror.hesabix.ir (پیشفرض؛ مناسب ایران)"
|
|
echo " [2] رسمی — pypi.org"
|
|
echo " [3] آینه تسینگهوا (چین) — pypi.tuna.tsinghua.edu.cn"
|
|
echo " [4] آینه علیبابا (چین) — mirrors.aliyun.com/pypi"
|
|
echo " [5] آدرس سفارشی (خودتان وارد کنید)"
|
|
read -rp "انتخاب [1-5] (پیشفرض 1): " _pip_choice
|
|
_pip_choice=${_pip_choice:-1}
|
|
case "${_pip_choice}" in
|
|
2) PIP_MIRROR=official ;;
|
|
3) PIP_MIRROR=tuna ;;
|
|
4) PIP_MIRROR=aliyun ;;
|
|
5)
|
|
PIP_MIRROR=custom
|
|
read -rp "آدرس index (مثال https://my.mirror/simple): " _pip_custom
|
|
if [[ -n "${_pip_custom}" ]]; then
|
|
PIP_INDEX_URL="$(hesabix_normalize_pip_index_url "${_pip_custom}")"
|
|
export PIP_INDEX_URL
|
|
fi
|
|
;;
|
|
*) PIP_MIRROR=hesabix ;;
|
|
esac
|
|
export PIP_MIRROR
|
|
}
|
|
|
|
hesabix_prompt_flutter_mirror() {
|
|
if [[ -n "${PUB_HOSTED_URL:-}" && -n "${FLUTTER_STORAGE_BASE_URL:-}" ]]; then
|
|
return 0
|
|
fi
|
|
FLUTTER_MIRROR="${FLUTTER_MIRROR:-}"
|
|
FLUTTER_MIRROR="${FLUTTER_MIRROR,,}"
|
|
if [[ -n "${FLUTTER_MIRROR}" ]]; then
|
|
return 0
|
|
fi
|
|
echo
|
|
echo "مخزن Flutter/Dart (pub get و engine) — برای بیلد رابط کاربری:"
|
|
echo " [1] Hesabix — f.mirror.hesabix.ir (پیشفرض؛ مناسب ایران)"
|
|
echo " [2] pub-azs.ir — مستقیم (ایران)"
|
|
echo " [3] چین — pub.flutter-io.cn / storage.flutter-io.cn"
|
|
echo " [4] آینه تسینگهوا (چین)"
|
|
echo " [5] آینه شانگهای SJTU (چین)"
|
|
echo " [6] رسمی — pub.dev / storage.googleapis.com"
|
|
echo " [7] آدرس سفارشی"
|
|
read -rp "انتخاب [1-7] (پیشفرض 1): " _flutter_choice
|
|
_flutter_choice=${_flutter_choice:-1}
|
|
case "${_flutter_choice}" in
|
|
2) FLUTTER_MIRROR=pub_azs ;;
|
|
3) FLUTTER_MIRROR=flutter_io_cn ;;
|
|
4) FLUTTER_MIRROR=tuna ;;
|
|
5) FLUTTER_MIRROR=sjtu ;;
|
|
6) FLUTTER_MIRROR=official ;;
|
|
7)
|
|
FLUTTER_MIRROR=custom
|
|
read -rp "PUB_HOSTED_URL (مثال https://pub.example): " _pub_url
|
|
read -rp "FLUTTER_STORAGE_BASE_URL (مثال https://storage.example): " _storage_url
|
|
if [[ -n "${_pub_url}" && -n "${_storage_url}" ]]; then
|
|
export PUB_HOSTED_URL="${_pub_url%/}"
|
|
export FLUTTER_STORAGE_BASE_URL="${_storage_url%/}"
|
|
fi
|
|
;;
|
|
*) FLUTTER_MIRROR=hesabix ;;
|
|
esac
|
|
export FLUTTER_MIRROR
|
|
}
|
|
|
|
hesabix_mirror_summary_pip() {
|
|
hesabix_apply_pip_mirror_env >/dev/null 2>&1 || true
|
|
if [[ "${PIP_MIRROR:-}" == "custom" ]]; then
|
|
echo " • PyPI (pip): custom — ${PIP_INDEX_URL:-}"
|
|
else
|
|
echo " • PyPI (pip): ${PIP_MIRROR:-hesabix} — ${PIP_INDEX_URL:-}"
|
|
fi
|
|
if [[ -n "${PIP_EXTRA_INDEX_URL:-}" && "${PIP_DISABLE_CHINA_FALLBACK:-0}" != "1" ]]; then
|
|
echo " • PyPI extra: ${PIP_EXTRA_INDEX_URL}"
|
|
fi
|
|
}
|
|
|
|
hesabix_mirror_summary_flutter() {
|
|
hesabix_apply_flutter_mirror_env >/dev/null 2>&1 || true
|
|
if [[ "${FLUTTER_MIRROR:-}" == "custom" ]]; then
|
|
echo " • Flutter pub: custom — ${PUB_HOSTED_URL:-}"
|
|
echo " • Flutter storage: ${FLUTTER_STORAGE_BASE_URL:-}"
|
|
else
|
|
echo " • Flutter pub: ${FLUTTER_MIRROR:-hesabix} — ${PUB_HOSTED_URL:-}"
|
|
echo " • Flutter storage: ${FLUTTER_STORAGE_BASE_URL:-}"
|
|
fi
|
|
}
|
|
|
|
# Write KEY=value into a sourced env file; quote so values with spaces are safe.
|
|
hesabix_write_env_assignment() {
|
|
printf '%s=%q\n' "$1" "${2:-}"
|
|
}
|
|
|
|
# Write mirror vars into .deploy_env (append/update keys).
|
|
hesabix_persist_mirror_to_deploy_env() {
|
|
local env_file="${1:-/opt/hesabix/.deploy_env}"
|
|
[[ -f "${env_file}" ]] || return 0
|
|
hesabix_apply_pip_mirror_env
|
|
hesabix_apply_flutter_mirror_env
|
|
local tmp
|
|
tmp=$(mktemp)
|
|
grep -vE '^(PIP_MIRROR|FLUTTER_MIRROR|PIP_INDEX_URL|PIP_EXTRA_INDEX_URL|PIP_TRUSTED_HOST|PUB_HOSTED_URL|FLUTTER_STORAGE_BASE_URL)=' "${env_file}" > "${tmp}" 2>/dev/null || true
|
|
{
|
|
cat "${tmp}"
|
|
hesabix_write_env_assignment PIP_MIRROR "${PIP_MIRROR:-hesabix}"
|
|
hesabix_write_env_assignment FLUTTER_MIRROR "${FLUTTER_MIRROR:-hesabix}"
|
|
hesabix_write_env_assignment PIP_INDEX_URL "${PIP_INDEX_URL:-}"
|
|
hesabix_write_env_assignment PIP_EXTRA_INDEX_URL "${PIP_EXTRA_INDEX_URL:-}"
|
|
hesabix_write_env_assignment PIP_TRUSTED_HOST "${PIP_TRUSTED_HOST:-}"
|
|
hesabix_write_env_assignment PUB_HOSTED_URL "${PUB_HOSTED_URL:-}"
|
|
hesabix_write_env_assignment FLUTTER_STORAGE_BASE_URL "${FLUTTER_STORAGE_BASE_URL:-}"
|
|
} > "${env_file}.new"
|
|
mv "${env_file}.new" "${env_file}"
|
|
chmod 600 "${env_file}" 2>/dev/null || true
|
|
rm -f "${tmp}"
|
|
}
|
|
|
|
# Backward-compatible aliases used by deploy.sh
|
|
configure_pip_hesabix_mirror() { hesabix_configure_pip_mirror "$@"; }
|
|
set_pip_mirror_env() { hesabix_apply_pip_mirror_env "$@"; }
|
|
set_flutter_mirror_env() { hesabix_apply_flutter_mirror_env "$@"; }
|