Files
gplan-2/tools/gate_platform.sh
T
2026-11-08 03:47:33 +08:00

110 lines
5.0 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# 闸件跨平台件——平台探测/路径形式/带超时执行/Godot 孤儿清杀,Git Bash 与 macOS/Linux 双栖。
# 单点定义:run_all_gates.sh / probe_gate.sh / render_gate.sh / golden_baseline_refresh.sh 共用(source 引入)。
# 纪律:闸脚本禁裸调 coreutils timeout 与 Windows 专用件(taskkill/PowerShell/ps -W/tasklist/cygpath)——
# 一律走本件封装;macOS 为 BSD 工具链(无 coreutils timeout,sed/stat 语义不同),裸调必断
# (2026-11-03 远端 CI 迁移裁决:runner=Mac 本机 host 模式,禁再增 Windows 专用直调)。
# 平台判定以 uname 为准(Git Bash=MINGW*,macOS=Darwin,Linux=Linux)。
gate_is_win() {
case "$(uname -s 2>/dev/null)" in
MINGW*|MSYS*|CYGWIN*|Windows_NT) return 0 ;;
*) return 1 ;;
esac
}
# Godot --path 接受的项目路径形式:Windows 需 cygpath -m 混合斜杠,其他平台原样。
gate_game_path() {
if gate_is_win; then cygpath -m "$1"; else printf '%s' "$1"; fi
}
# 杀整棵进程树(<pid>)——递归杀子进程后杀本进程。macOS/Linux 走 pgrep -P;
# Windows 侧 MSYS kill 对其可见进程有效,带 wrapper 树的场景仍由调用方原 taskkill /T 逻辑负责。
# 注意:Windows Git Bash 实测无 pgrep/pkill(2026-11-08 修复批)——本函数在 Windows 退化成只杀
# 顶格进程,引擎子进程残留由调用方段末 kill_orphans 清场兜底(probe_gate/render_gate 均有段后清点)。
gate_kill_tree() {
local p c
kill -9 "$1" 2>/dev/null
for c in $(pgrep -P "$1" 2>/dev/null); do gate_kill_tree "$c"; done
}
# 带超时执行(coreutils timeout 的纯 bash 替代,双平台同语义):
# gate_run_timeout <秒> <日志路径> <命令...>
# 命令输出重定向到日志;退出码=命令退出码,超时=124(与 coreutils 语义一致,判据与既有闸一致)。
# 实现=后台启动+守卫轮询(守卫每 0.2 秒醒一次,看两样:停止文件在不在/到点没;
# 命令先完时父流程放停止文件,守卫看见即自己退场——没有嵌套长 sleep,从机制上无孤儿可留;
# 2026-11-08 修复批:旧版 mktemp 建标志文件「建时即真」致退出码恒 124+守卫被杀留孤儿 sleep
# 占输出管道至满档);到点未见停止文件=真超时:落标志文件+杀整树+回 124。
gate_run_timeout() {
local t="$1" log="$2"; shift 2
local kf stop
kf="${TMPDIR:-/tmp}/gatetime.$$.$RANDOM.kf" # 只赋路径、不建文件——建时即真=旧缺陷病根(probe_gate run_suite 同款)
stop="${TMPDIR:-/tmp}/gatetime.$$.$RANDOM.stop"
rm -f "$kf" "$stop"
"$@" >"$log" 2>&1 &
local pid=$!
( end=$((SECONDS+t))
until [ -f "$stop" ] || [ "$SECONDS" -ge "$end" ]; do
sleep 0.2 2>/dev/null || sleep 1
done
if [ ! -f "$stop" ]; then
touch "$kf"
gate_kill_tree "$pid"
fi
true ) &
local guard=$!
wait "$pid"; local st=$?
touch "$stop" # 放停止文件=通知守卫收工,0.2 秒内自退,无需 kill
wait "$guard" 2>/dev/null
if [ -f "$kf" ]; then
gate_kill_tree "$pid"
st=124
fi
rm -f "$kf" "$stop"
return "$st"
}
# 列命令行含 <game路径> 的 Godot 进程 PID(孤儿清杀与批末残留清点共用)。
# Windows:PowerShell WMI 按进程名+命令行匹配(console wrapper+真引擎都算);
# macOS/Linux:ps 全表按「可执行含 godot+命令行含本 game 路径」过滤(ps 两平台同形)。
gate_orphans() {
local gp="$1"
if gate_is_win; then
local tmpd tmpf
tmpd="$(mktemp -d "${TMPDIR:-/tmp}/gateorph_XXXXXX")" # macOS BSD mktemp 禁 X 后带后缀(本分支 Windows 专用,模板统一防复用)
tmpf="$tmpd/k.ps1"
local gp_win
gp_win="$(cygpath -m "$gp")"
printf "Get-CimInstance Win32_Process -Filter \"Name like 'Godot%%'\" | Where-Object { \$_.CommandLine -like '*%s*' } | ForEach-Object { \$_.ProcessId }\n" "$gp_win" > "$tmpf"
powershell -NoProfile -ExecutionPolicy Bypass -File "$(cygpath -w "$tmpf")" 2>/dev/null | tr -d '\r'
rm -rf "$tmpd"
else
ps -axo pid=,command= 2>/dev/null | awk -v g="$gp" 'tolower($0) ~ /godot/ && index($0, g) {print $1}'
fi
}
gate_kill_orphans() { # gate_kill_orphans <game路径>
local p
for p in $(gate_orphans "$1"); do
if gate_is_win; then taskkill //F //PID "$p" >/dev/null 2>&1
else kill -9 "$p" 2>/dev/null; fi
done
}
# 全局 Godot 进程计数(其他会话的仅报数不算账——批末残留清点的对照面)。
gate_godot_count_all() {
if gate_is_win; then tasklist 2>/dev/null | grep -ci '^Godot' || true
else ps -axo comm= 2>/dev/null | grep -ci 'godot' || true
fi
}
# golden 基线平台子目录名——渲染基线按平台各存一份(Windows 显卡字形/抗锯齿与 macOS CoreText
# 差异使跨平台逐像素比对必失配,2026-11-03 用户裁:按平台各存基线,平台内部照常严格比对)。
gate_platform_id() {
case "$(uname -s 2>/dev/null)" in
MINGW*|MSYS*|CYGWIN*|Windows_NT) echo "windows" ;;
Darwin) echo "mac" ;;
*) echo "linux" ;;
esac
}