From abb3580d6049429235f927afe957e187fcd339f5 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Sun, 12 Jul 2026 12:54:41 +0300 Subject: [PATCH] =?UTF-8?q?fix(tests):=20verify-snapshots=20=D1=80=D0=B5?= =?UTF-8?q?=D0=B7=D0=BE=D0=BB=D0=B2=D0=B8=D1=82=20=D0=BF=D0=BB=D0=B0=D1=82?= =?UTF-8?q?=D1=84=D0=BE=D1=80=D0=BC=D1=83=201=D0=A1=20=D0=BD=D0=B0=20macOS?= =?UTF-8?q?/*nix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit loadV8Context() гейткипил по наличию 1cv8.exe → на маке (/opt/1cv8//1cv8, без .exe) возвращал null → «1C platform not found» даже при валидном v8path. Резолв исполняемого файла теперь по ОС (V8_EXE), проверяет и / и /bin/, плюс auto-detect по /opt/1cv8/* с числовой сортировкой версий. Windows-путь (bin/1cv8.exe) не тронут. Co-Authored-By: Claude Opus 4.8 (1M context) --- tests/skills/verify-snapshots.mjs | 59 ++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 8 deletions(-) diff --git a/tests/skills/verify-snapshots.mjs b/tests/skills/verify-snapshots.mjs index baedaf16..a936d06e 100644 --- a/tests/skills/verify-snapshots.mjs +++ b/tests/skills/verify-snapshots.mjs @@ -58,16 +58,59 @@ function parseArgs(argv) { // ─── Platform context ─────────────────────────────────────────────────────── +// Имя исполняемого файла платформы зависит от ОС: Windows — 1cv8.exe, *nix (macOS/Linux) — 1cv8. +const V8_EXE = process.platform === 'win32' ? '1cv8.exe' : '1cv8'; + +// Числовой ключ версии из имени папки (лексикографическая сортировка врёт: "8.3.9" > "8.3.27"). +function versionKey(dir) { + return (basename(dir).match(/\d+/g) || []).map(Number); +} + +function compareVersionKeys(a, b) { + for (let i = 0; i < Math.max(a.length, b.length); i++) { + const d = (a[i] || 0) - (b[i] || 0); + if (d) return d; + } + return 0; +} + +// Резолвит исполняемый файл платформы внутри каталога v8bin. +// На *nix 1cv8 лежит прямо в / (наш /opt/1cv8//1cv8), на Windows — в /bin/. +function resolveV8Exe(v8bin) { + if (!v8bin) return null; + const direct = join(v8bin, V8_EXE); + if (existsSync(direct)) return direct; + const inBin = join(v8bin, 'bin', V8_EXE); + if (existsSync(inBin)) return inBin; + return null; +} + +// Auto-detect платформы, когда v8path не задан в .v8-project.json — берём максимальную версию. +function autodetectV8bin() { + if (process.platform === 'win32') return null; // на Windows полагаемся на .v8-project.json / bin-раскладку + const root = '/opt/1cv8'; + if (!existsSync(root)) return null; + const dirs = readdirSync(root) + .map(d => join(root, d)) + .filter(d => { try { return statSync(d).isDirectory() && existsSync(join(d, V8_EXE)); } catch { return false; } }); + if (!dirs.length) return null; + return dirs.sort((a, b) => compareVersionKeys(versionKey(a), versionKey(b))).pop(); +} + function loadV8Context() { const projectFile = join(REPO_ROOT, '.v8-project.json'); - if (!existsSync(projectFile)) return null; - try { - const proj = JSON.parse(readFileSync(projectFile, 'utf8')); - const v8bin = proj.v8path; - const v8exe = v8bin ? (existsSync(join(v8bin, '1cv8.exe')) ? join(v8bin, '1cv8.exe') : null) : null; - if (!v8exe) return null; - return { v8path: v8bin, v8exe }; - } catch { return null; } + let v8bin = null; + if (existsSync(projectFile)) { + try { v8bin = JSON.parse(readFileSync(projectFile, 'utf8')).v8path || null; } catch { /* ignore */ } + } + let v8exe = resolveV8Exe(v8bin); + if (!v8exe) { + // v8path пуст/не резолвится — пробуем авто-детект (актуально на маке с /opt/1cv8//). + const detected = autodetectV8bin(); + if (detected) { v8bin = detected; v8exe = resolveV8Exe(detected); } + } + if (!v8exe) return null; + return { v8path: v8bin, v8exe }; } // ─── Script execution ───────────────────────────────────────────────────────