From 29999a27557ee3e38711e0c9904faa17f7f15c12 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Tue, 30 Jun 2026 11:42:07 +0300 Subject: [PATCH] =?UTF-8?q?fix(skills):=20=D0=BA=D0=BE=D1=80=D1=80=D0=B5?= =?UTF-8?q?=D0=BA=D1=82=D0=BD=D1=8B=D0=B9=20=D0=B7=D0=B0=D0=BF=D1=83=D1=81?= =?UTF-8?q?=D0=BA=20Python-=D0=BF=D0=BE=D1=80=D1=82=D0=BE=D0=B2=20=D0=BD?= =?UTF-8?q?=D0=B0=20macOS/Linux?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - subsystem-compile.py: авто-валидация через subprocess к subsystem-validate.py (вместо powershell.exe + .ps1), без проброса кода возврата — паритет с сиблингами - resolve_v8path (12 db/epf .py): резолв каталога платформы по ОС (1cv8 без .exe на *nix), авто-поиск /opt/1cv8/*; ibcmd только явным путём, 1cv8c убран - сообщения об ошибках платформо-нейтральные (ps1+py), коммент-заглушка PY-only в .ps1 - runner.mjs (v0.5): loadV8Context кросс-платформенный (1cv8/ibcmd без .exe) - тесты: stdoutContains маркер валидатора (#26), негативный кейс db-update/error-bad-v8dir - синхронный бамп версий ps1+py всех затронутых навыков Fixes #26, #27 Co-Authored-By: Korolev Pavel Co-Authored-By: Claude Opus 4.8 (1M context) --- .../skills/db-create/scripts/db-create.ps1 | 7 ++-- .claude/skills/db-create/scripts/db-create.py | 40 ++++++++++++------- .../skills/db-dump-cf/scripts/db-dump-cf.ps1 | 7 ++-- .../skills/db-dump-cf/scripts/db-dump-cf.py | 40 ++++++++++++------- .../skills/db-dump-dt/scripts/db-dump-dt.ps1 | 7 ++-- .../skills/db-dump-dt/scripts/db-dump-dt.py | 40 ++++++++++++------- .../db-dump-xml/scripts/db-dump-xml.ps1 | 7 ++-- .../skills/db-dump-xml/scripts/db-dump-xml.py | 40 ++++++++++++------- .../skills/db-load-cf/scripts/db-load-cf.ps1 | 7 ++-- .../skills/db-load-cf/scripts/db-load-cf.py | 40 ++++++++++++------- .../skills/db-load-dt/scripts/db-load-dt.ps1 | 7 ++-- .../skills/db-load-dt/scripts/db-load-dt.py | 40 ++++++++++++------- .../db-load-git/scripts/db-load-git.ps1 | 7 ++-- .../skills/db-load-git/scripts/db-load-git.py | 40 ++++++++++++------- .../db-load-xml/scripts/db-load-xml.ps1 | 7 ++-- .../skills/db-load-xml/scripts/db-load-xml.py | 40 ++++++++++++------- .claude/skills/db-run/scripts/db-run.ps1 | 7 ++-- .claude/skills/db-run/scripts/db-run.py | 40 ++++++++++++------- .../skills/db-update/scripts/db-update.ps1 | 7 ++-- .claude/skills/db-update/scripts/db-update.py | 40 ++++++++++++------- .../skills/epf-build/scripts/epf-build.ps1 | 7 ++-- .claude/skills/epf-build/scripts/epf-build.py | 40 ++++++++++++------- .claude/skills/epf-dump/scripts/epf-dump.ps1 | 7 ++-- .claude/skills/epf-dump/scripts/epf-dump.py | 40 ++++++++++++------- .../scripts/subsystem-compile.ps1 | 2 +- .../scripts/subsystem-compile.py | 9 +++-- .../cases/db-update/error-bad-v8dir.json | 5 +++ .../cases/subsystem-compile/minimal.json | 3 +- tests/skills/runner.mjs | 9 +++-- 29 files changed, 379 insertions(+), 213 deletions(-) create mode 100644 tests/skills/cases/db-update/error-bad-v8dir.json diff --git a/.claude/skills/db-create/scripts/db-create.ps1 b/.claude/skills/db-create/scripts/db-create.ps1 index a18ef69d..159466f2 100644 --- a/.claude/skills/db-create/scripts/db-create.ps1 +++ b/.claude/skills/db-create/scripts/db-create.ps1 @@ -1,5 +1,6 @@ -# db-create v1.4 — Create 1C information base +# db-create v1.5 — Create 1C information base # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills +# NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# .SYNOPSIS Создание информационной базы 1С @@ -96,7 +97,7 @@ if (-not $V8Path) { $V8Path = $found.FullName Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow } else { - Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found. Specify -V8Path" -ForegroundColor Red exit 1 } } @@ -105,7 +106,7 @@ if (Test-Path $V8Path -PathType Container) { } if (-not (Test-Path $V8Path)) { - Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found at $V8Path" -ForegroundColor Red exit 1 } diff --git a/.claude/skills/db-create/scripts/db-create.py b/.claude/skills/db-create/scripts/db-create.py index e965799c..37cd33c0 100644 --- a/.claude/skills/db-create/scripts/db-create.py +++ b/.claude/skills/db-create/scripts/db-create.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-create v1.4 — Create 1C information base +# db-create v1.5 — Create 1C information base # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -36,32 +36,44 @@ def _find_project_v8path(): d = parent +def _version_dir(p): + """Version dir for both Windows (.../1cv8//bin/1cv8.exe) and *nix (.../1cv8//1cv8).""" + parent = os.path.dirname(p) + if os.path.basename(parent).lower() == "bin": + parent = os.path.dirname(parent) + return os.path.basename(parent) + + def _version_key(p): - """Numeric sort key from version dir name (.../1cv8//bin/1cv8.exe).""" - ver = os.path.basename(os.path.dirname(os.path.dirname(p))) - return [int(x) for x in re.findall(r"\d+", ver)] + """Numeric sort key from version dir name.""" + return [int(x) for x in re.findall(r"\d+", _version_dir(p))] def resolve_v8path(v8path): - """Resolve path to 1cv8.exe.""" + """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" if not v8path: v8path = _find_project_v8path() if not v8path: - candidates = ( - glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") - + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") - ) + if os.name == "nt": + candidates = ( + glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") + + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") + ) + else: + # PY-only: PS-порт на *nix не исполняется, поэтому *nix-раскладки нет в .ps1. + candidates = glob.glob("/opt/1cv8/*/1cv8") if candidates: v8path = max(candidates, key=_version_key) - ver = os.path.basename(os.path.dirname(os.path.dirname(v8path))) - print(f"Auto-selected platform {ver}: {v8path}") + print(f"Auto-selected platform {_version_dir(v8path)}: {v8path}") else: - print("Error: 1cv8.exe not found. Specify -V8Path", file=sys.stderr) + print("Error: 1C executable not found. Specify -V8Path", file=sys.stderr) sys.exit(1) if os.path.isdir(v8path): - v8path = os.path.join(v8path, "1cv8.exe") + # PY-only: на *nix исполняемый называется "1cv8" (без .exe); ibcmd — только явным путём. + exe = "1cv8.exe" if os.name == "nt" else "1cv8" + v8path = os.path.join(v8path, exe) if not os.path.isfile(v8path): - print(f"Error: 1cv8.exe not found at {v8path}", file=sys.stderr) + print(f"Error: 1C executable not found at {v8path}", file=sys.stderr) sys.exit(1) return v8path diff --git a/.claude/skills/db-dump-cf/scripts/db-dump-cf.ps1 b/.claude/skills/db-dump-cf/scripts/db-dump-cf.ps1 index 7c9d29b4..d572906c 100644 --- a/.claude/skills/db-dump-cf/scripts/db-dump-cf.ps1 +++ b/.claude/skills/db-dump-cf/scripts/db-dump-cf.ps1 @@ -1,5 +1,6 @@ -# db-dump-cf v1.4 — Dump 1C configuration to CF file +# db-dump-cf v1.5 — Dump 1C configuration to CF file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills +# NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# .SYNOPSIS Выгрузка конфигурации 1С в CF-файл @@ -105,7 +106,7 @@ if (-not $V8Path) { $V8Path = $found.FullName Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow } else { - Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found. Specify -V8Path" -ForegroundColor Red exit 1 } } @@ -114,7 +115,7 @@ if (Test-Path $V8Path -PathType Container) { } if (-not (Test-Path $V8Path)) { - Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found at $V8Path" -ForegroundColor Red exit 1 } diff --git a/.claude/skills/db-dump-cf/scripts/db-dump-cf.py b/.claude/skills/db-dump-cf/scripts/db-dump-cf.py index 0400b6e3..9ecf0cfe 100644 --- a/.claude/skills/db-dump-cf/scripts/db-dump-cf.py +++ b/.claude/skills/db-dump-cf/scripts/db-dump-cf.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-dump-cf v1.4 — Dump 1C configuration to CF file +# db-dump-cf v1.5 — Dump 1C configuration to CF file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -36,32 +36,44 @@ def _find_project_v8path(): d = parent +def _version_dir(p): + """Version dir for both Windows (.../1cv8//bin/1cv8.exe) and *nix (.../1cv8//1cv8).""" + parent = os.path.dirname(p) + if os.path.basename(parent).lower() == "bin": + parent = os.path.dirname(parent) + return os.path.basename(parent) + + def _version_key(p): - """Numeric sort key from version dir name (.../1cv8//bin/1cv8.exe).""" - ver = os.path.basename(os.path.dirname(os.path.dirname(p))) - return [int(x) for x in re.findall(r"\d+", ver)] + """Numeric sort key from version dir name.""" + return [int(x) for x in re.findall(r"\d+", _version_dir(p))] def resolve_v8path(v8path): - """Resolve path to 1cv8.exe.""" + """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" if not v8path: v8path = _find_project_v8path() if not v8path: - candidates = ( - glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") - + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") - ) + if os.name == "nt": + candidates = ( + glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") + + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") + ) + else: + # PY-only: PS-порт на *nix не исполняется, поэтому *nix-раскладки нет в .ps1. + candidates = glob.glob("/opt/1cv8/*/1cv8") if candidates: v8path = max(candidates, key=_version_key) - ver = os.path.basename(os.path.dirname(os.path.dirname(v8path))) - print(f"Auto-selected platform {ver}: {v8path}") + print(f"Auto-selected platform {_version_dir(v8path)}: {v8path}") else: - print("Error: 1cv8.exe not found. Specify -V8Path", file=sys.stderr) + print("Error: 1C executable not found. Specify -V8Path", file=sys.stderr) sys.exit(1) if os.path.isdir(v8path): - v8path = os.path.join(v8path, "1cv8.exe") + # PY-only: на *nix исполняемый называется "1cv8" (без .exe); ibcmd — только явным путём. + exe = "1cv8.exe" if os.name == "nt" else "1cv8" + v8path = os.path.join(v8path, exe) if not os.path.isfile(v8path): - print(f"Error: 1cv8.exe not found at {v8path}", file=sys.stderr) + print(f"Error: 1C executable not found at {v8path}", file=sys.stderr) sys.exit(1) return v8path diff --git a/.claude/skills/db-dump-dt/scripts/db-dump-dt.ps1 b/.claude/skills/db-dump-dt/scripts/db-dump-dt.ps1 index 3655b512..c1c8aac0 100644 --- a/.claude/skills/db-dump-dt/scripts/db-dump-dt.ps1 +++ b/.claude/skills/db-dump-dt/scripts/db-dump-dt.ps1 @@ -1,5 +1,6 @@ -# db-dump-dt v1.3 — Dump 1C information base to DT file +# db-dump-dt v1.4 — Dump 1C information base to DT file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills +# NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# .SYNOPSIS Выгрузка информационной базы 1С в DT-файл @@ -89,7 +90,7 @@ if (-not $V8Path) { $V8Path = $found.FullName Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow } else { - Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found. Specify -V8Path" -ForegroundColor Red exit 1 } } @@ -98,7 +99,7 @@ if (Test-Path $V8Path -PathType Container) { } if (-not (Test-Path $V8Path)) { - Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found at $V8Path" -ForegroundColor Red exit 1 } diff --git a/.claude/skills/db-dump-dt/scripts/db-dump-dt.py b/.claude/skills/db-dump-dt/scripts/db-dump-dt.py index 29aafef7..e5b45cc6 100644 --- a/.claude/skills/db-dump-dt/scripts/db-dump-dt.py +++ b/.claude/skills/db-dump-dt/scripts/db-dump-dt.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-dump-dt v1.3 — Dump 1C information base to DT file +# db-dump-dt v1.4 — Dump 1C information base to DT file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -36,32 +36,44 @@ def _find_project_v8path(): d = parent +def _version_dir(p): + """Version dir for both Windows (.../1cv8//bin/1cv8.exe) and *nix (.../1cv8//1cv8).""" + parent = os.path.dirname(p) + if os.path.basename(parent).lower() == "bin": + parent = os.path.dirname(parent) + return os.path.basename(parent) + + def _version_key(p): - """Numeric sort key from version dir name (.../1cv8//bin/1cv8.exe).""" - ver = os.path.basename(os.path.dirname(os.path.dirname(p))) - return [int(x) for x in re.findall(r"\d+", ver)] + """Numeric sort key from version dir name.""" + return [int(x) for x in re.findall(r"\d+", _version_dir(p))] def resolve_v8path(v8path): - """Resolve path to 1cv8.exe.""" + """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" if not v8path: v8path = _find_project_v8path() if not v8path: - candidates = ( - glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") - + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") - ) + if os.name == "nt": + candidates = ( + glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") + + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") + ) + else: + # PY-only: PS-порт на *nix не исполняется, поэтому *nix-раскладки нет в .ps1. + candidates = glob.glob("/opt/1cv8/*/1cv8") if candidates: v8path = max(candidates, key=_version_key) - ver = os.path.basename(os.path.dirname(os.path.dirname(v8path))) - print(f"Auto-selected platform {ver}: {v8path}") + print(f"Auto-selected platform {_version_dir(v8path)}: {v8path}") else: - print("Error: 1cv8.exe not found. Specify -V8Path", file=sys.stderr) + print("Error: 1C executable not found. Specify -V8Path", file=sys.stderr) sys.exit(1) if os.path.isdir(v8path): - v8path = os.path.join(v8path, "1cv8.exe") + # PY-only: на *nix исполняемый называется "1cv8" (без .exe); ibcmd — только явным путём. + exe = "1cv8.exe" if os.name == "nt" else "1cv8" + v8path = os.path.join(v8path, exe) if not os.path.isfile(v8path): - print(f"Error: 1cv8.exe not found at {v8path}", file=sys.stderr) + print(f"Error: 1C executable not found at {v8path}", file=sys.stderr) sys.exit(1) return v8path diff --git a/.claude/skills/db-dump-xml/scripts/db-dump-xml.ps1 b/.claude/skills/db-dump-xml/scripts/db-dump-xml.ps1 index 5217c968..47344d5c 100644 --- a/.claude/skills/db-dump-xml/scripts/db-dump-xml.ps1 +++ b/.claude/skills/db-dump-xml/scripts/db-dump-xml.ps1 @@ -1,5 +1,6 @@ -# db-dump-xml v1.6 — Dump 1C configuration to XML files +# db-dump-xml v1.7 — Dump 1C configuration to XML files # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills +# NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# .SYNOPSIS Выгрузка конфигурации 1С в XML-файлы @@ -128,7 +129,7 @@ if (-not $V8Path) { $V8Path = $found.FullName Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow } else { - Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found. Specify -V8Path" -ForegroundColor Red exit 1 } } @@ -137,7 +138,7 @@ if (Test-Path $V8Path -PathType Container) { } if (-not (Test-Path $V8Path)) { - Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found at $V8Path" -ForegroundColor Red exit 1 } diff --git a/.claude/skills/db-dump-xml/scripts/db-dump-xml.py b/.claude/skills/db-dump-xml/scripts/db-dump-xml.py index fba0faa8..490fb505 100644 --- a/.claude/skills/db-dump-xml/scripts/db-dump-xml.py +++ b/.claude/skills/db-dump-xml/scripts/db-dump-xml.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-dump-xml v1.6 — Dump 1C configuration to XML files +# db-dump-xml v1.7 — Dump 1C configuration to XML files # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -36,32 +36,44 @@ def _find_project_v8path(): d = parent +def _version_dir(p): + """Version dir for both Windows (.../1cv8//bin/1cv8.exe) and *nix (.../1cv8//1cv8).""" + parent = os.path.dirname(p) + if os.path.basename(parent).lower() == "bin": + parent = os.path.dirname(parent) + return os.path.basename(parent) + + def _version_key(p): - """Numeric sort key from version dir name (.../1cv8//bin/1cv8.exe).""" - ver = os.path.basename(os.path.dirname(os.path.dirname(p))) - return [int(x) for x in re.findall(r"\d+", ver)] + """Numeric sort key from version dir name.""" + return [int(x) for x in re.findall(r"\d+", _version_dir(p))] def resolve_v8path(v8path): - """Resolve path to 1cv8.exe.""" + """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" if not v8path: v8path = _find_project_v8path() if not v8path: - candidates = ( - glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") - + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") - ) + if os.name == "nt": + candidates = ( + glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") + + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") + ) + else: + # PY-only: PS-порт на *nix не исполняется, поэтому *nix-раскладки нет в .ps1. + candidates = glob.glob("/opt/1cv8/*/1cv8") if candidates: v8path = max(candidates, key=_version_key) - ver = os.path.basename(os.path.dirname(os.path.dirname(v8path))) - print(f"Auto-selected platform {ver}: {v8path}") + print(f"Auto-selected platform {_version_dir(v8path)}: {v8path}") else: - print("Error: 1cv8.exe not found. Specify -V8Path", file=sys.stderr) + print("Error: 1C executable not found. Specify -V8Path", file=sys.stderr) sys.exit(1) if os.path.isdir(v8path): - v8path = os.path.join(v8path, "1cv8.exe") + # PY-only: на *nix исполняемый называется "1cv8" (без .exe); ibcmd — только явным путём. + exe = "1cv8.exe" if os.name == "nt" else "1cv8" + v8path = os.path.join(v8path, exe) if not os.path.isfile(v8path): - print(f"Error: 1cv8.exe not found at {v8path}", file=sys.stderr) + print(f"Error: 1C executable not found at {v8path}", file=sys.stderr) sys.exit(1) return v8path diff --git a/.claude/skills/db-load-cf/scripts/db-load-cf.ps1 b/.claude/skills/db-load-cf/scripts/db-load-cf.ps1 index a993073a..a4a865d8 100644 --- a/.claude/skills/db-load-cf/scripts/db-load-cf.ps1 +++ b/.claude/skills/db-load-cf/scripts/db-load-cf.ps1 @@ -1,5 +1,6 @@ -# db-load-cf v1.4 — Load 1C configuration from CF file +# db-load-cf v1.5 — Load 1C configuration from CF file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills +# NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# .SYNOPSIS Загрузка конфигурации 1С из CF-файла @@ -105,7 +106,7 @@ if (-not $V8Path) { $V8Path = $found.FullName Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow } else { - Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found. Specify -V8Path" -ForegroundColor Red exit 1 } } @@ -114,7 +115,7 @@ if (Test-Path $V8Path -PathType Container) { } if (-not (Test-Path $V8Path)) { - Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found at $V8Path" -ForegroundColor Red exit 1 } diff --git a/.claude/skills/db-load-cf/scripts/db-load-cf.py b/.claude/skills/db-load-cf/scripts/db-load-cf.py index a1ca8cd5..a2e68d83 100644 --- a/.claude/skills/db-load-cf/scripts/db-load-cf.py +++ b/.claude/skills/db-load-cf/scripts/db-load-cf.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-load-cf v1.4 — Load 1C configuration from CF file +# db-load-cf v1.5 — Load 1C configuration from CF file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -36,32 +36,44 @@ def _find_project_v8path(): d = parent +def _version_dir(p): + """Version dir for both Windows (.../1cv8//bin/1cv8.exe) and *nix (.../1cv8//1cv8).""" + parent = os.path.dirname(p) + if os.path.basename(parent).lower() == "bin": + parent = os.path.dirname(parent) + return os.path.basename(parent) + + def _version_key(p): - """Numeric sort key from version dir name (.../1cv8//bin/1cv8.exe).""" - ver = os.path.basename(os.path.dirname(os.path.dirname(p))) - return [int(x) for x in re.findall(r"\d+", ver)] + """Numeric sort key from version dir name.""" + return [int(x) for x in re.findall(r"\d+", _version_dir(p))] def resolve_v8path(v8path): - """Resolve path to 1cv8.exe.""" + """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" if not v8path: v8path = _find_project_v8path() if not v8path: - candidates = ( - glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") - + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") - ) + if os.name == "nt": + candidates = ( + glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") + + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") + ) + else: + # PY-only: PS-порт на *nix не исполняется, поэтому *nix-раскладки нет в .ps1. + candidates = glob.glob("/opt/1cv8/*/1cv8") if candidates: v8path = max(candidates, key=_version_key) - ver = os.path.basename(os.path.dirname(os.path.dirname(v8path))) - print(f"Auto-selected platform {ver}: {v8path}") + print(f"Auto-selected platform {_version_dir(v8path)}: {v8path}") else: - print("Error: 1cv8.exe not found. Specify -V8Path", file=sys.stderr) + print("Error: 1C executable not found. Specify -V8Path", file=sys.stderr) sys.exit(1) if os.path.isdir(v8path): - v8path = os.path.join(v8path, "1cv8.exe") + # PY-only: на *nix исполняемый называется "1cv8" (без .exe); ibcmd — только явным путём. + exe = "1cv8.exe" if os.name == "nt" else "1cv8" + v8path = os.path.join(v8path, exe) if not os.path.isfile(v8path): - print(f"Error: 1cv8.exe not found at {v8path}", file=sys.stderr) + print(f"Error: 1C executable not found at {v8path}", file=sys.stderr) sys.exit(1) return v8path diff --git a/.claude/skills/db-load-dt/scripts/db-load-dt.ps1 b/.claude/skills/db-load-dt/scripts/db-load-dt.ps1 index b2a8b01f..dbba0ae3 100644 --- a/.claude/skills/db-load-dt/scripts/db-load-dt.ps1 +++ b/.claude/skills/db-load-dt/scripts/db-load-dt.ps1 @@ -1,5 +1,6 @@ -# db-load-dt v1.3 — Load 1C information base from DT file +# db-load-dt v1.4 — Load 1C information base from DT file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills +# NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# .SYNOPSIS Загрузка информационной базы 1С из DT-файла @@ -102,7 +103,7 @@ if (-not $V8Path) { $V8Path = $found.FullName Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow } else { - Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found. Specify -V8Path" -ForegroundColor Red exit 1 } } @@ -111,7 +112,7 @@ if (Test-Path $V8Path -PathType Container) { } if (-not (Test-Path $V8Path)) { - Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found at $V8Path" -ForegroundColor Red exit 1 } diff --git a/.claude/skills/db-load-dt/scripts/db-load-dt.py b/.claude/skills/db-load-dt/scripts/db-load-dt.py index bb08de35..ef72172f 100644 --- a/.claude/skills/db-load-dt/scripts/db-load-dt.py +++ b/.claude/skills/db-load-dt/scripts/db-load-dt.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-load-dt v1.3 — Load 1C information base from DT file +# db-load-dt v1.4 — Load 1C information base from DT file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -36,32 +36,44 @@ def _find_project_v8path(): d = parent +def _version_dir(p): + """Version dir for both Windows (.../1cv8//bin/1cv8.exe) and *nix (.../1cv8//1cv8).""" + parent = os.path.dirname(p) + if os.path.basename(parent).lower() == "bin": + parent = os.path.dirname(parent) + return os.path.basename(parent) + + def _version_key(p): - """Numeric sort key from version dir name (.../1cv8//bin/1cv8.exe).""" - ver = os.path.basename(os.path.dirname(os.path.dirname(p))) - return [int(x) for x in re.findall(r"\d+", ver)] + """Numeric sort key from version dir name.""" + return [int(x) for x in re.findall(r"\d+", _version_dir(p))] def resolve_v8path(v8path): - """Resolve path to 1cv8.exe.""" + """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" if not v8path: v8path = _find_project_v8path() if not v8path: - candidates = ( - glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") - + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") - ) + if os.name == "nt": + candidates = ( + glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") + + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") + ) + else: + # PY-only: PS-порт на *nix не исполняется, поэтому *nix-раскладки нет в .ps1. + candidates = glob.glob("/opt/1cv8/*/1cv8") if candidates: v8path = max(candidates, key=_version_key) - ver = os.path.basename(os.path.dirname(os.path.dirname(v8path))) - print(f"Auto-selected platform {ver}: {v8path}") + print(f"Auto-selected platform {_version_dir(v8path)}: {v8path}") else: - print("Error: 1cv8.exe not found. Specify -V8Path", file=sys.stderr) + print("Error: 1C executable not found. Specify -V8Path", file=sys.stderr) sys.exit(1) if os.path.isdir(v8path): - v8path = os.path.join(v8path, "1cv8.exe") + # PY-only: на *nix исполняемый называется "1cv8" (без .exe); ibcmd — только явным путём. + exe = "1cv8.exe" if os.name == "nt" else "1cv8" + v8path = os.path.join(v8path, exe) if not os.path.isfile(v8path): - print(f"Error: 1cv8.exe not found at {v8path}", file=sys.stderr) + print(f"Error: 1C executable not found at {v8path}", file=sys.stderr) sys.exit(1) return v8path diff --git a/.claude/skills/db-load-git/scripts/db-load-git.ps1 b/.claude/skills/db-load-git/scripts/db-load-git.ps1 index 811c6564..0b86628d 100644 --- a/.claude/skills/db-load-git/scripts/db-load-git.ps1 +++ b/.claude/skills/db-load-git/scripts/db-load-git.ps1 @@ -1,5 +1,6 @@ -# db-load-git v1.8 — Load Git changes into 1C database +# db-load-git v1.9 — Load Git changes into 1C database # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills +# NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# .SYNOPSIS Загрузка изменений из Git в базу 1С @@ -149,7 +150,7 @@ if (-not $DryRun) { $V8Path = $found.FullName Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow } else { - Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found. Specify -V8Path" -ForegroundColor Red exit 1 } } @@ -158,7 +159,7 @@ if (-not $DryRun) { } if (-not (Test-Path $V8Path)) { - Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found at $V8Path" -ForegroundColor Red exit 1 } } diff --git a/.claude/skills/db-load-git/scripts/db-load-git.py b/.claude/skills/db-load-git/scripts/db-load-git.py index 73cc823a..6cb141ec 100644 --- a/.claude/skills/db-load-git/scripts/db-load-git.py +++ b/.claude/skills/db-load-git/scripts/db-load-git.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-load-git v1.8 — Load Git changes into 1C database +# db-load-git v1.9 — Load Git changes into 1C database # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -36,32 +36,44 @@ def _find_project_v8path(): d = parent +def _version_dir(p): + """Version dir for both Windows (.../1cv8//bin/1cv8.exe) and *nix (.../1cv8//1cv8).""" + parent = os.path.dirname(p) + if os.path.basename(parent).lower() == "bin": + parent = os.path.dirname(parent) + return os.path.basename(parent) + + def _version_key(p): - """Numeric sort key from version dir name (.../1cv8//bin/1cv8.exe).""" - ver = os.path.basename(os.path.dirname(os.path.dirname(p))) - return [int(x) for x in re.findall(r"\d+", ver)] + """Numeric sort key from version dir name.""" + return [int(x) for x in re.findall(r"\d+", _version_dir(p))] def resolve_v8path(v8path): - """Resolve path to 1cv8.exe.""" + """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" if not v8path: v8path = _find_project_v8path() if not v8path: - candidates = ( - glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") - + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") - ) + if os.name == "nt": + candidates = ( + glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") + + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") + ) + else: + # PY-only: PS-порт на *nix не исполняется, поэтому *nix-раскладки нет в .ps1. + candidates = glob.glob("/opt/1cv8/*/1cv8") if candidates: v8path = max(candidates, key=_version_key) - ver = os.path.basename(os.path.dirname(os.path.dirname(v8path))) - print(f"Auto-selected platform {ver}: {v8path}") + print(f"Auto-selected platform {_version_dir(v8path)}: {v8path}") else: - print("Error: 1cv8.exe not found. Specify -V8Path", file=sys.stderr) + print("Error: 1C executable not found. Specify -V8Path", file=sys.stderr) sys.exit(1) if os.path.isdir(v8path): - v8path = os.path.join(v8path, "1cv8.exe") + # PY-only: на *nix исполняемый называется "1cv8" (без .exe); ibcmd — только явным путём. + exe = "1cv8.exe" if os.name == "nt" else "1cv8" + v8path = os.path.join(v8path, exe) if not os.path.isfile(v8path): - print(f"Error: 1cv8.exe not found at {v8path}", file=sys.stderr) + print(f"Error: 1C executable not found at {v8path}", file=sys.stderr) sys.exit(1) return v8path diff --git a/.claude/skills/db-load-xml/scripts/db-load-xml.ps1 b/.claude/skills/db-load-xml/scripts/db-load-xml.ps1 index 4746702a..4f840dd1 100644 --- a/.claude/skills/db-load-xml/scripts/db-load-xml.ps1 +++ b/.claude/skills/db-load-xml/scripts/db-load-xml.ps1 @@ -1,5 +1,6 @@ -# db-load-xml v1.10 — Load 1C configuration from XML files +# db-load-xml v1.11 — Load 1C configuration from XML files # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills +# NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# .SYNOPSIS Загрузка конфигурации 1С из XML-файлов @@ -137,7 +138,7 @@ if (-not $V8Path) { $V8Path = $found.FullName Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow } else { - Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found. Specify -V8Path" -ForegroundColor Red exit 1 } } @@ -146,7 +147,7 @@ if (Test-Path $V8Path -PathType Container) { } if (-not (Test-Path $V8Path)) { - Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found at $V8Path" -ForegroundColor Red exit 1 } diff --git a/.claude/skills/db-load-xml/scripts/db-load-xml.py b/.claude/skills/db-load-xml/scripts/db-load-xml.py index cc18569e..a9759ff4 100644 --- a/.claude/skills/db-load-xml/scripts/db-load-xml.py +++ b/.claude/skills/db-load-xml/scripts/db-load-xml.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-load-xml v1.10 — Load 1C configuration from XML files +# db-load-xml v1.11 — Load 1C configuration from XML files # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -36,32 +36,44 @@ def _find_project_v8path(): d = parent +def _version_dir(p): + """Version dir for both Windows (.../1cv8//bin/1cv8.exe) and *nix (.../1cv8//1cv8).""" + parent = os.path.dirname(p) + if os.path.basename(parent).lower() == "bin": + parent = os.path.dirname(parent) + return os.path.basename(parent) + + def _version_key(p): - """Numeric sort key from version dir name (.../1cv8//bin/1cv8.exe).""" - ver = os.path.basename(os.path.dirname(os.path.dirname(p))) - return [int(x) for x in re.findall(r"\d+", ver)] + """Numeric sort key from version dir name.""" + return [int(x) for x in re.findall(r"\d+", _version_dir(p))] def resolve_v8path(v8path): - """Resolve path to 1cv8.exe.""" + """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" if not v8path: v8path = _find_project_v8path() if not v8path: - candidates = ( - glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") - + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") - ) + if os.name == "nt": + candidates = ( + glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") + + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") + ) + else: + # PY-only: PS-порт на *nix не исполняется, поэтому *nix-раскладки нет в .ps1. + candidates = glob.glob("/opt/1cv8/*/1cv8") if candidates: v8path = max(candidates, key=_version_key) - ver = os.path.basename(os.path.dirname(os.path.dirname(v8path))) - print(f"Auto-selected platform {ver}: {v8path}") + print(f"Auto-selected platform {_version_dir(v8path)}: {v8path}") else: - print("Error: 1cv8.exe not found. Specify -V8Path", file=sys.stderr) + print("Error: 1C executable not found. Specify -V8Path", file=sys.stderr) sys.exit(1) if os.path.isdir(v8path): - v8path = os.path.join(v8path, "1cv8.exe") + # PY-only: на *nix исполняемый называется "1cv8" (без .exe); ibcmd — только явным путём. + exe = "1cv8.exe" if os.name == "nt" else "1cv8" + v8path = os.path.join(v8path, exe) if not os.path.isfile(v8path): - print(f"Error: 1cv8.exe not found at {v8path}", file=sys.stderr) + print(f"Error: 1C executable not found at {v8path}", file=sys.stderr) sys.exit(1) return v8path diff --git a/.claude/skills/db-run/scripts/db-run.ps1 b/.claude/skills/db-run/scripts/db-run.ps1 index 560f9fef..c040db37 100644 --- a/.claude/skills/db-run/scripts/db-run.ps1 +++ b/.claude/skills/db-run/scripts/db-run.ps1 @@ -1,5 +1,6 @@ -# db-run v1.1 — Launch 1C:Enterprise +# db-run v1.2 — Launch 1C:Enterprise # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills +# NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# .SYNOPSIS Запуск 1С:Предприятие @@ -108,7 +109,7 @@ if (-not $V8Path) { $V8Path = $found.FullName Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow } else { - Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found. Specify -V8Path" -ForegroundColor Red exit 1 } } @@ -117,7 +118,7 @@ if (Test-Path $V8Path -PathType Container) { } if (-not (Test-Path $V8Path)) { - Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found at $V8Path" -ForegroundColor Red exit 1 } diff --git a/.claude/skills/db-run/scripts/db-run.py b/.claude/skills/db-run/scripts/db-run.py index fda5bc11..3b1e4e74 100644 --- a/.claude/skills/db-run/scripts/db-run.py +++ b/.claude/skills/db-run/scripts/db-run.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-run v1.1 — Launch 1C:Enterprise +# db-run v1.2 — Launch 1C:Enterprise # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -32,32 +32,44 @@ def _find_project_v8path(): d = parent +def _version_dir(p): + """Version dir for both Windows (.../1cv8//bin/1cv8.exe) and *nix (.../1cv8//1cv8).""" + parent = os.path.dirname(p) + if os.path.basename(parent).lower() == "bin": + parent = os.path.dirname(parent) + return os.path.basename(parent) + + def _version_key(p): - """Numeric sort key from version dir name (.../1cv8//bin/1cv8.exe).""" - ver = os.path.basename(os.path.dirname(os.path.dirname(p))) - return [int(x) for x in re.findall(r"\d+", ver)] + """Numeric sort key from version dir name.""" + return [int(x) for x in re.findall(r"\d+", _version_dir(p))] def resolve_v8path(v8path): - """Resolve path to 1cv8.exe.""" + """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" if not v8path: v8path = _find_project_v8path() if not v8path: - candidates = ( - glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") - + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") - ) + if os.name == "nt": + candidates = ( + glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") + + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") + ) + else: + # PY-only: PS-порт на *nix не исполняется, поэтому *nix-раскладки нет в .ps1. + candidates = glob.glob("/opt/1cv8/*/1cv8") if candidates: v8path = max(candidates, key=_version_key) - ver = os.path.basename(os.path.dirname(os.path.dirname(v8path))) - print(f"Auto-selected platform {ver}: {v8path}") + print(f"Auto-selected platform {_version_dir(v8path)}: {v8path}") else: - print("Error: 1cv8.exe not found. Specify -V8Path", file=sys.stderr) + print("Error: 1C executable not found. Specify -V8Path", file=sys.stderr) sys.exit(1) if os.path.isdir(v8path): - v8path = os.path.join(v8path, "1cv8.exe") + # PY-only: на *nix исполняемый называется "1cv8" (без .exe); ibcmd — только явным путём. + exe = "1cv8.exe" if os.name == "nt" else "1cv8" + v8path = os.path.join(v8path, exe) if not os.path.isfile(v8path): - print(f"Error: 1cv8.exe not found at {v8path}", file=sys.stderr) + print(f"Error: 1C executable not found at {v8path}", file=sys.stderr) sys.exit(1) return v8path diff --git a/.claude/skills/db-update/scripts/db-update.ps1 b/.claude/skills/db-update/scripts/db-update.ps1 index 52940032..c6ca1230 100644 --- a/.claude/skills/db-update/scripts/db-update.ps1 +++ b/.claude/skills/db-update/scripts/db-update.ps1 @@ -1,5 +1,6 @@ -# db-update v1.4 — Update 1C database configuration +# db-update v1.5 — Update 1C database configuration # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills +# NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# .SYNOPSIS Обновление конфигурации базы данных 1С @@ -118,7 +119,7 @@ if (-not $V8Path) { $V8Path = $found.FullName Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow } else { - Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found. Specify -V8Path" -ForegroundColor Red exit 1 } } @@ -127,7 +128,7 @@ if (Test-Path $V8Path -PathType Container) { } if (-not (Test-Path $V8Path)) { - Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found at $V8Path" -ForegroundColor Red exit 1 } diff --git a/.claude/skills/db-update/scripts/db-update.py b/.claude/skills/db-update/scripts/db-update.py index 331c84de..4d6e1bbc 100644 --- a/.claude/skills/db-update/scripts/db-update.py +++ b/.claude/skills/db-update/scripts/db-update.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-update v1.4 — Update 1C database configuration +# db-update v1.5 — Update 1C database configuration # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -36,32 +36,44 @@ def _find_project_v8path(): d = parent +def _version_dir(p): + """Version dir for both Windows (.../1cv8//bin/1cv8.exe) and *nix (.../1cv8//1cv8).""" + parent = os.path.dirname(p) + if os.path.basename(parent).lower() == "bin": + parent = os.path.dirname(parent) + return os.path.basename(parent) + + def _version_key(p): - """Numeric sort key from version dir name (.../1cv8//bin/1cv8.exe).""" - ver = os.path.basename(os.path.dirname(os.path.dirname(p))) - return [int(x) for x in re.findall(r"\d+", ver)] + """Numeric sort key from version dir name.""" + return [int(x) for x in re.findall(r"\d+", _version_dir(p))] def resolve_v8path(v8path): - """Resolve path to 1cv8.exe.""" + """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" if not v8path: v8path = _find_project_v8path() if not v8path: - candidates = ( - glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") - + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") - ) + if os.name == "nt": + candidates = ( + glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") + + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") + ) + else: + # PY-only: PS-порт на *nix не исполняется, поэтому *nix-раскладки нет в .ps1. + candidates = glob.glob("/opt/1cv8/*/1cv8") if candidates: v8path = max(candidates, key=_version_key) - ver = os.path.basename(os.path.dirname(os.path.dirname(v8path))) - print(f"Auto-selected platform {ver}: {v8path}") + print(f"Auto-selected platform {_version_dir(v8path)}: {v8path}") else: - print("Error: 1cv8.exe not found. Specify -V8Path", file=sys.stderr) + print("Error: 1C executable not found. Specify -V8Path", file=sys.stderr) sys.exit(1) if os.path.isdir(v8path): - v8path = os.path.join(v8path, "1cv8.exe") + # PY-only: на *nix исполняемый называется "1cv8" (без .exe); ibcmd — только явным путём. + exe = "1cv8.exe" if os.name == "nt" else "1cv8" + v8path = os.path.join(v8path, exe) if not os.path.isfile(v8path): - print(f"Error: 1cv8.exe not found at {v8path}", file=sys.stderr) + print(f"Error: 1C executable not found at {v8path}", file=sys.stderr) sys.exit(1) return v8path diff --git a/.claude/skills/epf-build/scripts/epf-build.ps1 b/.claude/skills/epf-build/scripts/epf-build.ps1 index 12a05b31..186b326f 100644 --- a/.claude/skills/epf-build/scripts/epf-build.ps1 +++ b/.claude/skills/epf-build/scripts/epf-build.ps1 @@ -1,5 +1,6 @@ -# epf-build v1.4 — Build external data processor or report (EPF/ERF) from XML sources +# epf-build v1.5 — Build external data processor or report (EPF/ERF) from XML sources # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills +# NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# .SYNOPSIS Сборка внешней обработки/отчёта 1С из XML-исходников @@ -99,7 +100,7 @@ if (-not $V8Path) { $V8Path = $found.FullName Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow } else { - Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found. Specify -V8Path" -ForegroundColor Red exit 1 } } @@ -108,7 +109,7 @@ if (Test-Path $V8Path -PathType Container) { } if (-not (Test-Path $V8Path)) { - Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found at $V8Path" -ForegroundColor Red exit 1 } diff --git a/.claude/skills/epf-build/scripts/epf-build.py b/.claude/skills/epf-build/scripts/epf-build.py index fd1111c0..4deb68d2 100644 --- a/.claude/skills/epf-build/scripts/epf-build.py +++ b/.claude/skills/epf-build/scripts/epf-build.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# epf-build v1.4 — Build external data processor or report (EPF/ERF) from XML sources +# epf-build v1.5 — Build external data processor or report (EPF/ERF) from XML sources # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -36,32 +36,44 @@ def _find_project_v8path(): d = parent +def _version_dir(p): + """Version dir for both Windows (.../1cv8//bin/1cv8.exe) and *nix (.../1cv8//1cv8).""" + parent = os.path.dirname(p) + if os.path.basename(parent).lower() == "bin": + parent = os.path.dirname(parent) + return os.path.basename(parent) + + def _version_key(p): - """Numeric sort key from version dir name (.../1cv8//bin/1cv8.exe).""" - ver = os.path.basename(os.path.dirname(os.path.dirname(p))) - return [int(x) for x in re.findall(r"\d+", ver)] + """Numeric sort key from version dir name.""" + return [int(x) for x in re.findall(r"\d+", _version_dir(p))] def resolve_v8path(v8path): - """Resolve path to 1cv8.exe.""" + """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" if not v8path: v8path = _find_project_v8path() if not v8path: - candidates = ( - glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") - + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") - ) + if os.name == "nt": + candidates = ( + glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") + + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") + ) + else: + # PY-only: PS-порт на *nix не исполняется, поэтому *nix-раскладки нет в .ps1. + candidates = glob.glob("/opt/1cv8/*/1cv8") if candidates: v8path = max(candidates, key=_version_key) - ver = os.path.basename(os.path.dirname(os.path.dirname(v8path))) - print(f"Auto-selected platform {ver}: {v8path}") + print(f"Auto-selected platform {_version_dir(v8path)}: {v8path}") else: - print("Error: 1cv8.exe not found. Specify -V8Path", file=sys.stderr) + print("Error: 1C executable not found. Specify -V8Path", file=sys.stderr) sys.exit(1) if os.path.isdir(v8path): - v8path = os.path.join(v8path, "1cv8.exe") + # PY-only: на *nix исполняемый называется "1cv8" (без .exe); ibcmd — только явным путём. + exe = "1cv8.exe" if os.name == "nt" else "1cv8" + v8path = os.path.join(v8path, exe) if not os.path.isfile(v8path): - print(f"Error: 1cv8.exe not found at {v8path}", file=sys.stderr) + print(f"Error: 1C executable not found at {v8path}", file=sys.stderr) sys.exit(1) return v8path diff --git a/.claude/skills/epf-dump/scripts/epf-dump.ps1 b/.claude/skills/epf-dump/scripts/epf-dump.ps1 index 34a2f20b..436e9976 100644 --- a/.claude/skills/epf-dump/scripts/epf-dump.ps1 +++ b/.claude/skills/epf-dump/scripts/epf-dump.ps1 @@ -1,5 +1,6 @@ -# epf-dump v1.4 — Dump external data processor or report (EPF/ERF) to XML sources +# epf-dump v1.5 — Dump external data processor or report (EPF/ERF) to XML sources # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills +# NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# .SYNOPSIS Разборка внешней обработки/отчёта 1С в XML-исходники @@ -106,7 +107,7 @@ if (-not $V8Path) { $V8Path = $found.FullName Write-Host "Auto-selected platform $($found.Directory.Parent.Name): $V8Path" -ForegroundColor Yellow } else { - Write-Host "Error: 1cv8.exe not found. Specify -V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found. Specify -V8Path" -ForegroundColor Red exit 1 } } @@ -115,7 +116,7 @@ if (Test-Path $V8Path -PathType Container) { } if (-not (Test-Path $V8Path)) { - Write-Host "Error: 1cv8.exe not found at $V8Path" -ForegroundColor Red + Write-Host "Error: 1C executable not found at $V8Path" -ForegroundColor Red exit 1 } diff --git a/.claude/skills/epf-dump/scripts/epf-dump.py b/.claude/skills/epf-dump/scripts/epf-dump.py index b29fdc29..022c5876 100644 --- a/.claude/skills/epf-dump/scripts/epf-dump.py +++ b/.claude/skills/epf-dump/scripts/epf-dump.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# epf-dump v1.4 — Dump external data processor or report (EPF/ERF) to XML sources +# epf-dump v1.5 — Dump external data processor or report (EPF/ERF) to XML sources # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse @@ -36,32 +36,44 @@ def _find_project_v8path(): d = parent +def _version_dir(p): + """Version dir for both Windows (.../1cv8//bin/1cv8.exe) and *nix (.../1cv8//1cv8).""" + parent = os.path.dirname(p) + if os.path.basename(parent).lower() == "bin": + parent = os.path.dirname(parent) + return os.path.basename(parent) + + def _version_key(p): - """Numeric sort key from version dir name (.../1cv8//bin/1cv8.exe).""" - ver = os.path.basename(os.path.dirname(os.path.dirname(p))) - return [int(x) for x in re.findall(r"\d+", ver)] + """Numeric sort key from version dir name.""" + return [int(x) for x in re.findall(r"\d+", _version_dir(p))] def resolve_v8path(v8path): - """Resolve path to 1cv8.exe.""" + """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" if not v8path: v8path = _find_project_v8path() if not v8path: - candidates = ( - glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") - + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") - ) + if os.name == "nt": + candidates = ( + glob.glob(r"C:\Program Files\1cv8\*\bin\1cv8.exe") + + glob.glob(r"C:\Program Files (x86)\1cv8\*\bin\1cv8.exe") + ) + else: + # PY-only: PS-порт на *nix не исполняется, поэтому *nix-раскладки нет в .ps1. + candidates = glob.glob("/opt/1cv8/*/1cv8") if candidates: v8path = max(candidates, key=_version_key) - ver = os.path.basename(os.path.dirname(os.path.dirname(v8path))) - print(f"Auto-selected platform {ver}: {v8path}") + print(f"Auto-selected platform {_version_dir(v8path)}: {v8path}") else: - print("Error: 1cv8.exe not found. Specify -V8Path", file=sys.stderr) + print("Error: 1C executable not found. Specify -V8Path", file=sys.stderr) sys.exit(1) if os.path.isdir(v8path): - v8path = os.path.join(v8path, "1cv8.exe") + # PY-only: на *nix исполняемый называется "1cv8" (без .exe); ibcmd — только явным путём. + exe = "1cv8.exe" if os.name == "nt" else "1cv8" + v8path = os.path.join(v8path, exe) if not os.path.isfile(v8path): - print(f"Error: 1cv8.exe not found at {v8path}", file=sys.stderr) + print(f"Error: 1C executable not found at {v8path}", file=sys.stderr) sys.exit(1) return v8path diff --git a/.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1 b/.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1 index ded1b325..3a19581f 100644 --- a/.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1 +++ b/.claude/skills/subsystem-compile/scripts/subsystem-compile.ps1 @@ -1,4 +1,4 @@ -# subsystem-compile v1.7 — Create 1C subsystem from JSON definition +# subsystem-compile v1.8 — Create 1C subsystem from JSON definition # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$DefinitionFile, diff --git a/.claude/skills/subsystem-compile/scripts/subsystem-compile.py b/.claude/skills/subsystem-compile/scripts/subsystem-compile.py index 20affe62..f3f56aad 100644 --- a/.claude/skills/subsystem-compile/scripts/subsystem-compile.py +++ b/.claude/skills/subsystem-compile/scripts/subsystem-compile.py @@ -1,10 +1,11 @@ #!/usr/bin/env python3 -# subsystem-compile v1.7 — Create 1C subsystem from JSON definition +# subsystem-compile v1.8 — Create 1C subsystem from JSON definition # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import json import os import re +import subprocess import sys import uuid import xml.etree.ElementTree as ET @@ -591,11 +592,11 @@ def main(): # --- 6. Auto-validate --- if not args.NoValidate: script_dir = os.path.dirname(os.path.abspath(__file__)) - validate_script = os.path.normpath(os.path.join(script_dir, '..', '..', 'subsystem-validate', 'scripts', 'subsystem-validate.ps1')) - if os.path.exists(validate_script): + validate_script = os.path.normpath(os.path.join(script_dir, '..', '..', 'subsystem-validate', 'scripts', 'subsystem-validate.py')) + if os.path.isfile(validate_script): print() print("--- Running subsystem-validate ---") - os.system(f'powershell.exe -NoProfile -File "{validate_script}" -SubsystemPath "{target_xml}"') + subprocess.run([sys.executable, validate_script, "-SubsystemPath", target_xml]) # --- 7. Summary --- print() diff --git a/tests/skills/cases/db-update/error-bad-v8dir.json b/tests/skills/cases/db-update/error-bad-v8dir.json new file mode 100644 index 00000000..986b1b44 --- /dev/null +++ b/tests/skills/cases/db-update/error-bad-v8dir.json @@ -0,0 +1,5 @@ +{ + "name": "Ошибка: каталог -V8Path без исполняемого 1C", + "args_extra": ["-V8Path", "{workDir}"], + "expectError": true +} diff --git a/tests/skills/cases/subsystem-compile/minimal.json b/tests/skills/cases/subsystem-compile/minimal.json index a9ba0fac..5b1d89e9 100644 --- a/tests/skills/cases/subsystem-compile/minimal.json +++ b/tests/skills/cases/subsystem-compile/minimal.json @@ -5,6 +5,7 @@ }, "validatePath": "Subsystems/Тест", "expect": { - "files": ["Subsystems/Тест.xml"] + "files": ["Subsystems/Тест.xml"], + "stdoutContains": "=== Validation OK: Subsystem.Тест" } } diff --git a/tests/skills/runner.mjs b/tests/skills/runner.mjs index e47560b0..ec9790c0 100644 --- a/tests/skills/runner.mjs +++ b/tests/skills/runner.mjs @@ -1,5 +1,5 @@ #!/usr/bin/env node -// skill-test-runner v0.4 — Snapshot-based regression tests for 1C skill scripts +// skill-test-runner v0.5 — Snapshot-based regression tests for 1C skill scripts // Usage: node tests/skills/runner.mjs [filter] [--update-snapshots] [--runtime python] [--json report.json] [--concurrency N] [--with-validation] import { execFileSync, execFile } from 'child_process'; @@ -970,9 +970,12 @@ function loadV8Context() { 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; + // Platform executable names: Windows uses .exe; *nix (macOS/Linux) plain names. + const exeName = process.platform === 'win32' ? '1cv8.exe' : '1cv8'; + const ibcmdName = process.platform === 'win32' ? 'ibcmd.exe' : 'ibcmd'; + const v8exe = v8bin && existsSync(join(v8bin, exeName)) ? join(v8bin, exeName) : null; if (!v8exe) return null; - const ibcmdExe = v8bin && existsSync(join(v8bin, 'ibcmd.exe')) ? join(v8bin, 'ibcmd.exe') : null; + const ibcmdExe = v8bin && existsSync(join(v8bin, ibcmdName)) ? join(v8bin, ibcmdName) : null; const defaultDb = proj.databases?.find(d => d.id === proj.default) || proj.databases?.[0]; return { v8path: v8bin,