Watch
1
0
Fork
You've already forked Seyyed_arc
0
forked from hesabix/arc
Seyyed_arc/scripts/mirror_config.sh
2026-08-31 21:05:45 +00:00

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 "$@"; }