From 4b4559e772c6066aff1ae7a28dffa5acd218fa63 Mon Sep 17 00:00:00 2001 From: cbb <2625274797@qq.com> Date: Wed, 16 Sep 2026 12:19:55 +0800 Subject: [PATCH] =?UTF-8?q?fix(server):=20worktree=20=E5=90=AF=E5=8A=A8?= =?UTF-8?q?=E6=97=B6=20ECAT=5FDIR=20=E5=9B=9E=E6=8C=87=E4=B8=BB=E6=A3=80?= =?UTF-8?q?=E5=87=BA=20tools/ecat?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 从 .worktrees/ 跑 esp32_server 时 join(BASE_DIR,'..','ecat') 会拼成 .worktrees/ecat,找不到 ecat_native.exe。先走出 .worktrees 再取兄弟目录。 --- esp32_server.py | 16 ++++++++- scripts/test_ecat_dir_worktree.mjs | 57 ++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 scripts/test_ecat_dir_worktree.mjs diff --git a/esp32_server.py b/esp32_server.py index f8d656a..50620df 100644 --- a/esp32_server.py +++ b/esp32_server.py @@ -157,7 +157,21 @@ g_ecat_port = None # 记住上次探到的端口, 避免每次请求都从 809 # 2) 拉起时**必须带 --parent-pid**: 让 native 在本服务退出后自我了断, # 不留孤儿进程占着 Npcap 适配器和端口。 # 3) 不再需要 venv/pythonw —— 单文件 exe, 无 Python 运行时依赖。 -ECAT_DIR = os.path.normpath(os.path.join(BASE_DIR, "..", "ecat")) +def _resolve_ecat_dir(base_dir): + """定位 tools/ecat(ecat_native.exe 的仓库,与本仓库平级)。 + + 从 git worktree(.../tools/ESP32/.worktrees/)启动时,BASE_DIR 的 + 上一级是 .worktrees 而不是 tools,直接 join("..","ecat") 会拼成 + .../ESP32/.worktrees/ecat,找不到 exe。先走回主检出再取兄弟目录。 + """ + d = os.path.abspath(base_dir) + parent = os.path.dirname(d) + if os.path.basename(parent) == ".worktrees": + d = os.path.dirname(parent) # → .../tools/ESP32 主检出 + return os.path.normpath(os.path.join(d, "..", "ecat")) + + +ECAT_DIR = _resolve_ecat_dir(BASE_DIR) ECAT_NATIVE_EXE = os.path.join(ECAT_DIR, "build_native", "ecat_native.exe") g_ecat_child = None # 由本服务拉起的 ecat 服务子进程(复用已有实例时为 None) g_ecat_log_fp = None # native stdout 落盘句柄(见 _ecat_autostart 内注释) diff --git a/scripts/test_ecat_dir_worktree.mjs b/scripts/test_ecat_dir_worktree.mjs new file mode 100644 index 0000000..a4b5e1f --- /dev/null +++ b/scripts/test_ecat_dir_worktree.mjs @@ -0,0 +1,57 @@ +/** + * 从 git worktree 启动 esp32_server 时,ECAT_DIR 必须指回主检出的 + * tools/ecat,而不是 .../ESP32/.worktrees/ecat。 + * 复刻 _resolve_ecat_dir 的纯路径逻辑(无 DOM/无网络)。 + */ +import assert from "node:assert/strict"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +/** 与 esp32_server._resolve_ecat_dir 同构(JS 侧只测路径形状)。 */ +function resolveEcatDir(baseDir) { + let d = path.resolve(baseDir); + const parent = path.dirname(d); + if (path.basename(parent) === ".worktrees") { + d = path.dirname(parent); + } + return path.normalize(path.join(d, "..", "ecat")); +} + +let failed = 0; +function check(name, fn) { + try { + fn(); + console.log(" ✓", name); + } catch (e) { + failed++; + console.log(" ✗", name, "—", e.message); + } +} + +console.log("[worktree ECAT_DIR]"); + +check("主检出 BASE_DIR → 兄弟 tools/ecat", () => { + const base = path.resolve("G:/Robot_v2/DCU/tools/ESP32"); + const got = resolveEcatDir(base); + assert.equal(got, path.resolve("G:/Robot_v2/DCU/tools/ecat"), got); +}); + +check("worktree BASE_DIR → 仍指主检出的 tools/ecat", () => { + const base = path.resolve("G:/Robot_v2/DCU/tools/ESP32/.worktrees/device-link"); + const got = resolveEcatDir(base); + assert.equal(got, path.resolve("G:/Robot_v2/DCU/tools/ecat"), got); +}); + +check("嵌套 slug 也走 .worktrees 父级", () => { + const base = path.resolve("G:/x/tools/ESP32/.worktrees/foo-bar"); + const got = resolveEcatDir(base); + assert.equal(got, path.resolve("G:/x/tools/ecat"), got); +}); + +/* BASE_DIR 恒为 esp32_server.py 所在目录;普通主检出已在第一项覆盖。 */ + +if (failed) { + console.log(`失败 ${failed} 项`); + process.exit(1); +} +console.log("通过 3 项,失败 0 项");