feat(db-*,epf-*,erf-*,web-publish): v8path на уровне записи базы

В одном проекте базы могут жить на разных версиях платформы, а версию формата
XML-выгрузки задаёт та платформа, которая выгружает: без выбора платформы по базе
срабатывает автопоиск и берёт самую старшую установленную — то есть самый новый
формат, который коллега на младшей платформе уже не загрузит.

Теперь порядок такой: явный -V8Path -> v8path записи базы -> корневой v8path ->
автопоиск. Запись базы ищет сам скрипт тем же матчем, которым добывал реквизиты
хранилища (Find-ProjectDatabase): файловую по path, серверную по server + ref.

- в 9 навыков, где матча не было, скопирован блок из авторитета db-repo;
- списки потребителей трёх семей в check-inline-drift расширены; заведена семья
  platform: resolve_v8path — обёртка меняла сигнатуру, а под гардом не была;
- раннер подставляет {workDir}/{fakePlatform} и в содержимое preRun.writeFile,
  иначе кейс про выбор платформы нельзя написать кроссплатформенно;
- в SKILL.md платформа теперь берётся ПОСЛЕ разрешения базы, строка про
  автоопределение через Program Files убрана как деталь реализации.

Живой прогон: две базы в одном проекте при корневом v8path = 8.5 дали формат
2.17 (8.3.24) и 2.20 (8.3.27), оба порта.

Closes #93

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-09-19 20:35:20 +03:00
co-authored by Claude Opus 5
parent 303db4e9f9
commit 874ae650ca
56 changed files with 1249 additions and 193 deletions
+2 -2
View File
@@ -25,13 +25,13 @@ allowed-tools:
## Параметры подключения ## Параметры подключения
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу: Прочитай `.v8-project.json` из корня проекта и разреши базу:
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую 1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json` 2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches` 3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
4. Если ветка не совпала — используй `default` 4. Если ветка не совпала — используй `default`
Если `v8path` не задан — скрипт сам попытается определить платформу. Платформа — `v8path` найденной записи базы, иначе корневой `v8path`. Не задан ни там, ни там — `-V8Path` не передавай.
## Команда ## Команда
@@ -1,4 +1,4 @@
# db-cfe-admin v1.0 — Configuration extensions in a 1C infobase: list, check, properties, delete # db-cfe-admin v1.1 — Configuration extensions in a 1C infobase: list, check, properties, delete
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. # NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется.
<# <#
@@ -110,9 +110,10 @@ $OutputEncoding = [System.Text.Encoding]::UTF8
# Копии держит одинаковыми tests/skills/check-inline-drift.mjs — правку вносить в навык-эталон. # Копии держит одинаковыми tests/skills/check-inline-drift.mjs — правку вносить в навык-эталон.
$Extension = $Name $Extension = $Name
# --- Реквизиты хранилища из .v8-project.json --- # --- Запись базы в .v8-project.json ---
# Модель их не передаёт: скрипт сопоставляет параметры соединения с записью в databases[] # Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# и берёт repository оттуда. Тот же приём, что в cf-edit.ps1 (сопоставление по configSrc). # сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.ps1 (сопоставление по configSrc).
function Find-V8Project([string]$startDir) { function Find-V8Project([string]$startDir) {
$d = $startDir $d = $startDir
for ($i = 0; $i -lt 20 -and $d; $i++) { for ($i = 0; $i -lt 20 -and $d; $i++) {
@@ -396,6 +397,10 @@ Assert-InfoBaseExists $InfoBasePath
# --- Resolve V8Path --- # --- Resolve V8Path ---
function Find-ProjectV8Path { function Find-ProjectV8Path {
# v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
# платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
$dbRec = Find-ProjectDatabase
if ($dbRec -and $dbRec.v8path) { return [string]$dbRec.v8path }
$dir = (Get-Location).Path $dir = (Get-Location).Path
while ($dir) { while ($dir) {
$pf = Join-Path $dir ".v8-project.json" $pf = Join-Path $dir ".v8-project.json"
@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# db-cfe-admin v1.0 — Configuration extensions in a 1C infobase: list, check, properties, delete # db-cfe-admin v1.1 — Configuration extensions in a 1C infobase: list, check, properties, delete
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse import argparse
@@ -38,8 +38,15 @@ def ci_parse_args(parser, argv=None):
def _find_project_v8path(): def _find_project_v8path(args):
"""Walk up from CWD to find .v8-project.json and read its v8path.""" """Walk up from CWD to find .v8-project.json and read its v8path.
v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
"""
db = find_project_database(args)
if db and db.get("v8path"):
return db["v8path"]
d = os.getcwd() d = os.getcwd()
while True: while True:
pf = os.path.join(d, ".v8-project.json") pf = os.path.join(d, ".v8-project.json")
@@ -88,9 +95,10 @@ V8_SECRET_KEYS = ["/P", "/UC", "/WSP", "/AWSP", "/ConfigurationRepositoryP"]
IBCMD_SECRET_KEYS = ["--password", "--token", "--db-pwd"] IBCMD_SECRET_KEYS = ["--password", "--token", "--db-pwd"]
# --- Реквизиты хранилища из .v8-project.json --- # --- Запись базы в .v8-project.json ---
# Модель их не передаёт: скрипт сопоставляет параметры соединения с записью в databases[] # Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# и берёт repository оттуда. Тот же приём, что в cf-edit.py (сопоставление по configSrc). # сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.py (сопоставление по configSrc).
def _sg_find_v8project(start_dir): def _sg_find_v8project(start_dir):
d = start_dir d = start_dir
for _ in range(20): for _ in range(20):
@@ -329,10 +337,10 @@ def _version_key(p):
return [int(x) for x in re.findall(r"\d+", _version_dir(p))] return [int(x) for x in re.findall(r"\d+", _version_dir(p))]
def resolve_v8path(v8path): def resolve_v8path(v8path, args):
"""Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly)."""
if not v8path: if not v8path:
v8path = _find_project_v8path() v8path = _find_project_v8path(args)
if not v8path: if not v8path:
if os.name == "nt": if os.name == "nt":
candidates = ( candidates = (
@@ -629,7 +637,7 @@ def main():
args.InfoBasePath = clean_path(args.InfoBasePath, "-InfoBasePath") args.InfoBasePath = clean_path(args.InfoBasePath, "-InfoBasePath")
assert_infobase_exists(args.InfoBasePath) assert_infobase_exists(args.InfoBasePath)
v8path = resolve_v8path(args.V8Path) v8path = resolve_v8path(args.V8Path, args)
# --- Утилиты платформы: нужны обе, выбор по команде --- # --- Утилиты платформы: нужны обе, выбор по команде ---
# -V8Path указывает на каталог bin либо на любой из двух файлов; второй берётся соседом. # -V8Path указывает на каталог bin либо на любой из двух файлов; второй берётся соседом.
+2 -2
View File
@@ -24,8 +24,8 @@ allowed-tools:
## Параметры подключения ## Параметры подключения
Прочитай `.v8-project.json` из корня проекта для `v8path` (путь к платформе). Прочитай `.v8-project.json` из корня проекта. Платформа — `v8path` записи создаваемой базы,
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files). если она уже в реестре, иначе корневой `v8path`. Не задан ни там, ни там — `-V8Path` не передавай.
После создания базы предложи зарегистрировать через `/db-list add`. После создания базы предложи зарегистрировать через `/db-list add`.
## Команда ## Команда
+45 -1
View File
@@ -1,4 +1,4 @@
# db-create v1.14 — Create 1C information base # db-create v1.15 — Create 1C information base
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. # NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется.
<# <#
@@ -243,8 +243,52 @@ $V8Path = ConvertTo-CleanPath $V8Path '-V8Path'
$InfoBasePath = ConvertTo-CleanPath $InfoBasePath '-InfoBasePath' $InfoBasePath = ConvertTo-CleanPath $InfoBasePath '-InfoBasePath'
$UseTemplate = ConvertTo-CleanPath $UseTemplate '-UseTemplate' $UseTemplate = ConvertTo-CleanPath $UseTemplate '-UseTemplate'
# --- Запись базы в .v8-project.json ---
# Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.ps1 (сопоставление по configSrc).
function Find-V8Project([string]$startDir) {
$d = $startDir
for ($i = 0; $i -lt 20 -and $d; $i++) {
$pj = Join-Path $d ".v8-project.json"
if (Test-Path $pj) { return $pj }
$parent = [System.IO.Path]::GetDirectoryName($d)
if ($parent -eq $d) { break }
$d = $parent
}
return $null
}
function Test-SamePath {
param([string]$A, [string]$B)
if (-not $A -or -not $B) { return $false }
try {
$na = [System.IO.Path]::GetFullPath($A).TrimEnd('\', '/')
$nb = [System.IO.Path]::GetFullPath($B).TrimEnd('\', '/')
return $na.Equals($nb, [System.StringComparison]::OrdinalIgnoreCase)
} catch { return $false }
}
function Find-ProjectDatabase {
# Запись базы в реестре, соответствующая переданному соединению. $null, если не найдена.
$pf = Find-V8Project (Get-Location).Path
if (-not $pf) { return $null }
try { $proj = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json } catch { return $null }
if (-not $proj.databases) { return $null }
foreach ($db in $proj.databases) {
if ($InfoBasePath -and $db.path -and (Test-SamePath $db.path $InfoBasePath)) { return $db }
if ($InfoBaseServer -and $InfoBaseRef -and $db.server -and $db.ref) {
if ($db.server.Equals($InfoBaseServer, [System.StringComparison]::OrdinalIgnoreCase) -and
$db.ref.Equals($InfoBaseRef, [System.StringComparison]::OrdinalIgnoreCase)) { return $db }
}
}
return $null
}
# --- Resolve V8Path --- # --- Resolve V8Path ---
function Find-ProjectV8Path { function Find-ProjectV8Path {
# v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
# платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
$dbRec = Find-ProjectDatabase
if ($dbRec -and $dbRec.v8path) { return [string]$dbRec.v8path }
$dir = (Get-Location).Path $dir = (Get-Location).Path
while ($dir) { while ($dir) {
$pf = Join-Path $dir ".v8-project.json" $pf = Join-Path $dir ".v8-project.json"
+60 -6
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# db-create v1.14 — Create 1C information base # db-create v1.15 — Create 1C information base
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse import argparse
@@ -37,8 +37,62 @@ def ci_parse_args(parser, argv=None):
def _find_project_v8path(): # --- Запись базы в .v8-project.json ---
"""Walk up from CWD to find .v8-project.json and read its v8path.""" # Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.py (сопоставление по configSrc).
def _sg_find_v8project(start_dir):
d = start_dir
for _ in range(20):
if not d:
break
pj = os.path.join(d, ".v8-project.json")
if os.path.isfile(pj):
return pj
parent = os.path.dirname(d)
if parent == d:
break
d = parent
return None
def same_path(a, b):
if not a or not b:
return False
try:
return os.path.abspath(a).rstrip("\\/").lower() == os.path.abspath(b).rstrip("\\/").lower()
except Exception:
return False
def find_project_database(args):
"""Запись базы в реестре, соответствующая переданному соединению. None, если не найдена."""
pf = _sg_find_v8project(os.getcwd())
if not pf:
return None
try:
with open(pf, encoding="utf-8-sig") as f:
proj = json.load(f)
except Exception:
return None
for db in proj.get("databases") or []:
if args.InfoBasePath and db.get("path") and same_path(db["path"], args.InfoBasePath):
return db
if args.InfoBaseServer and args.InfoBaseRef and db.get("server") and db.get("ref"):
if (db["server"].lower() == args.InfoBaseServer.lower()
and db["ref"].lower() == args.InfoBaseRef.lower()):
return db
return None
def _find_project_v8path(args):
"""Walk up from CWD to find .v8-project.json and read its v8path.
v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
"""
db = find_project_database(args)
if db and db.get("v8path"):
return db["v8path"]
d = os.getcwd() d = os.getcwd()
while True: while True:
pf = os.path.join(d, ".v8-project.json") pf = os.path.join(d, ".v8-project.json")
@@ -243,10 +297,10 @@ def _version_key(p):
return [int(x) for x in re.findall(r"\d+", _version_dir(p))] return [int(x) for x in re.findall(r"\d+", _version_dir(p))]
def resolve_v8path(v8path): def resolve_v8path(v8path, args):
"""Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly)."""
if not v8path: if not v8path:
v8path = _find_project_v8path() v8path = _find_project_v8path(args)
if not v8path: if not v8path:
if os.name == "nt": if os.name == "nt":
candidates = ( candidates = (
@@ -418,7 +472,7 @@ def main():
args.InfoBasePath = clean_path(args.InfoBasePath, "-InfoBasePath") args.InfoBasePath = clean_path(args.InfoBasePath, "-InfoBasePath")
args.UseTemplate = clean_path(args.UseTemplate, "-UseTemplate") args.UseTemplate = clean_path(args.UseTemplate, "-UseTemplate")
v8path = resolve_v8path(args.V8Path) v8path = resolve_v8path(args.V8Path, args)
engine = "ibcmd" if os.path.basename(v8path).lower().startswith("ibcmd") else "1cv8" engine = "ibcmd" if os.path.basename(v8path).lower().startswith("ibcmd") else "1cv8"
# --- Resolve additional arguments for the selected engine --- # --- Resolve additional arguments for the selected engine ---
+2 -2
View File
@@ -23,12 +23,12 @@ allowed-tools:
## Параметры подключения ## Параметры подключения
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу: Прочитай `.v8-project.json` из корня проекта и разреши базу:
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую 1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json` 2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches` 3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
4. Если ветка не совпала — используй `default` 4. Если ветка не совпала — используй `default`
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files). Платформа — `v8path` найденной записи базы, иначе корневой `v8path`. Не задан ни там, ни там — `-V8Path` не передавай.
Если файла нет — предложи `/db-list add`. Если файла нет — предложи `/db-list add`.
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`. Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
@@ -1,4 +1,4 @@
# db-dump-cf v1.16 — Dump 1C configuration to CF file # db-dump-cf v1.17 — Dump 1C configuration to CF file
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. # NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется.
<# <#
@@ -272,8 +272,52 @@ function Assert-InfoBaseExists {
Assert-InfoBaseExists $InfoBasePath Assert-InfoBaseExists $InfoBasePath
# --- Запись базы в .v8-project.json ---
# Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.ps1 (сопоставление по configSrc).
function Find-V8Project([string]$startDir) {
$d = $startDir
for ($i = 0; $i -lt 20 -and $d; $i++) {
$pj = Join-Path $d ".v8-project.json"
if (Test-Path $pj) { return $pj }
$parent = [System.IO.Path]::GetDirectoryName($d)
if ($parent -eq $d) { break }
$d = $parent
}
return $null
}
function Test-SamePath {
param([string]$A, [string]$B)
if (-not $A -or -not $B) { return $false }
try {
$na = [System.IO.Path]::GetFullPath($A).TrimEnd('\', '/')
$nb = [System.IO.Path]::GetFullPath($B).TrimEnd('\', '/')
return $na.Equals($nb, [System.StringComparison]::OrdinalIgnoreCase)
} catch { return $false }
}
function Find-ProjectDatabase {
# Запись базы в реестре, соответствующая переданному соединению. $null, если не найдена.
$pf = Find-V8Project (Get-Location).Path
if (-not $pf) { return $null }
try { $proj = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json } catch { return $null }
if (-not $proj.databases) { return $null }
foreach ($db in $proj.databases) {
if ($InfoBasePath -and $db.path -and (Test-SamePath $db.path $InfoBasePath)) { return $db }
if ($InfoBaseServer -and $InfoBaseRef -and $db.server -and $db.ref) {
if ($db.server.Equals($InfoBaseServer, [System.StringComparison]::OrdinalIgnoreCase) -and
$db.ref.Equals($InfoBaseRef, [System.StringComparison]::OrdinalIgnoreCase)) { return $db }
}
}
return $null
}
# --- Resolve V8Path --- # --- Resolve V8Path ---
function Find-ProjectV8Path { function Find-ProjectV8Path {
# v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
# платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
$dbRec = Find-ProjectDatabase
if ($dbRec -and $dbRec.v8path) { return [string]$dbRec.v8path }
$dir = (Get-Location).Path $dir = (Get-Location).Path
while ($dir) { while ($dir) {
$pf = Join-Path $dir ".v8-project.json" $pf = Join-Path $dir ".v8-project.json"
@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# db-dump-cf v1.16 — Dump 1C configuration to CF file # db-dump-cf v1.17 — Dump 1C configuration to CF file
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse import argparse
@@ -37,8 +37,62 @@ def ci_parse_args(parser, argv=None):
def _find_project_v8path(): # --- Запись базы в .v8-project.json ---
"""Walk up from CWD to find .v8-project.json and read its v8path.""" # Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.py (сопоставление по configSrc).
def _sg_find_v8project(start_dir):
d = start_dir
for _ in range(20):
if not d:
break
pj = os.path.join(d, ".v8-project.json")
if os.path.isfile(pj):
return pj
parent = os.path.dirname(d)
if parent == d:
break
d = parent
return None
def same_path(a, b):
if not a or not b:
return False
try:
return os.path.abspath(a).rstrip("\\/").lower() == os.path.abspath(b).rstrip("\\/").lower()
except Exception:
return False
def find_project_database(args):
"""Запись базы в реестре, соответствующая переданному соединению. None, если не найдена."""
pf = _sg_find_v8project(os.getcwd())
if not pf:
return None
try:
with open(pf, encoding="utf-8-sig") as f:
proj = json.load(f)
except Exception:
return None
for db in proj.get("databases") or []:
if args.InfoBasePath and db.get("path") and same_path(db["path"], args.InfoBasePath):
return db
if args.InfoBaseServer and args.InfoBaseRef and db.get("server") and db.get("ref"):
if (db["server"].lower() == args.InfoBaseServer.lower()
and db["ref"].lower() == args.InfoBaseRef.lower()):
return db
return None
def _find_project_v8path(args):
"""Walk up from CWD to find .v8-project.json and read its v8path.
v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
"""
db = find_project_database(args)
if db and db.get("v8path"):
return db["v8path"]
d = os.getcwd() d = os.getcwd()
while True: while True:
pf = os.path.join(d, ".v8-project.json") pf = os.path.join(d, ".v8-project.json")
@@ -243,10 +297,10 @@ def _version_key(p):
return [int(x) for x in re.findall(r"\d+", _version_dir(p))] return [int(x) for x in re.findall(r"\d+", _version_dir(p))]
def resolve_v8path(v8path): def resolve_v8path(v8path, args):
"""Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly)."""
if not v8path: if not v8path:
v8path = _find_project_v8path() v8path = _find_project_v8path(args)
if not v8path: if not v8path:
if os.name == "nt": if os.name == "nt":
candidates = ( candidates = (
@@ -439,7 +493,7 @@ def main():
assert_infobase_exists(args.InfoBasePath) assert_infobase_exists(args.InfoBasePath)
args.OutputFile = clean_path(args.OutputFile, "-OutputFile") args.OutputFile = clean_path(args.OutputFile, "-OutputFile")
v8path = resolve_v8path(args.V8Path) v8path = resolve_v8path(args.V8Path, args)
engine = "ibcmd" if os.path.basename(v8path).lower().startswith("ibcmd") else "1cv8" engine = "ibcmd" if os.path.basename(v8path).lower().startswith("ibcmd") else "1cv8"
# --- Resolve additional arguments for the selected engine --- # --- Resolve additional arguments for the selected engine ---
+2 -2
View File
@@ -26,12 +26,12 @@ allowed-tools:
## Параметры подключения ## Параметры подключения
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу: Прочитай `.v8-project.json` из корня проекта и разреши базу:
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую 1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json` 2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches` 3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
4. Если ветка не совпала — используй `default` 4. Если ветка не совпала — используй `default`
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files). Платформа — `v8path` найденной записи базы, иначе корневой `v8path`. Не задан ни там, ни там — `-V8Path` не передавай.
Если файла нет — предложи `/db-list add`. Если файла нет — предложи `/db-list add`.
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`. Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
@@ -1,4 +1,4 @@
# db-dump-dt v1.15 — Dump 1C information base to DT file # db-dump-dt v1.16 — Dump 1C information base to DT file
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. # NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется.
<# <#
@@ -256,8 +256,52 @@ function Assert-InfoBaseExists {
Assert-InfoBaseExists $InfoBasePath Assert-InfoBaseExists $InfoBasePath
# --- Запись базы в .v8-project.json ---
# Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.ps1 (сопоставление по configSrc).
function Find-V8Project([string]$startDir) {
$d = $startDir
for ($i = 0; $i -lt 20 -and $d; $i++) {
$pj = Join-Path $d ".v8-project.json"
if (Test-Path $pj) { return $pj }
$parent = [System.IO.Path]::GetDirectoryName($d)
if ($parent -eq $d) { break }
$d = $parent
}
return $null
}
function Test-SamePath {
param([string]$A, [string]$B)
if (-not $A -or -not $B) { return $false }
try {
$na = [System.IO.Path]::GetFullPath($A).TrimEnd('\', '/')
$nb = [System.IO.Path]::GetFullPath($B).TrimEnd('\', '/')
return $na.Equals($nb, [System.StringComparison]::OrdinalIgnoreCase)
} catch { return $false }
}
function Find-ProjectDatabase {
# Запись базы в реестре, соответствующая переданному соединению. $null, если не найдена.
$pf = Find-V8Project (Get-Location).Path
if (-not $pf) { return $null }
try { $proj = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json } catch { return $null }
if (-not $proj.databases) { return $null }
foreach ($db in $proj.databases) {
if ($InfoBasePath -and $db.path -and (Test-SamePath $db.path $InfoBasePath)) { return $db }
if ($InfoBaseServer -and $InfoBaseRef -and $db.server -and $db.ref) {
if ($db.server.Equals($InfoBaseServer, [System.StringComparison]::OrdinalIgnoreCase) -and
$db.ref.Equals($InfoBaseRef, [System.StringComparison]::OrdinalIgnoreCase)) { return $db }
}
}
return $null
}
# --- Resolve V8Path --- # --- Resolve V8Path ---
function Find-ProjectV8Path { function Find-ProjectV8Path {
# v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
# платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
$dbRec = Find-ProjectDatabase
if ($dbRec -and $dbRec.v8path) { return [string]$dbRec.v8path }
$dir = (Get-Location).Path $dir = (Get-Location).Path
while ($dir) { while ($dir) {
$pf = Join-Path $dir ".v8-project.json" $pf = Join-Path $dir ".v8-project.json"
@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# db-dump-dt v1.15 — Dump 1C information base to DT file # db-dump-dt v1.16 — Dump 1C information base to DT file
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse import argparse
@@ -37,8 +37,62 @@ def ci_parse_args(parser, argv=None):
def _find_project_v8path(): # --- Запись базы в .v8-project.json ---
"""Walk up from CWD to find .v8-project.json and read its v8path.""" # Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.py (сопоставление по configSrc).
def _sg_find_v8project(start_dir):
d = start_dir
for _ in range(20):
if not d:
break
pj = os.path.join(d, ".v8-project.json")
if os.path.isfile(pj):
return pj
parent = os.path.dirname(d)
if parent == d:
break
d = parent
return None
def same_path(a, b):
if not a or not b:
return False
try:
return os.path.abspath(a).rstrip("\\/").lower() == os.path.abspath(b).rstrip("\\/").lower()
except Exception:
return False
def find_project_database(args):
"""Запись базы в реестре, соответствующая переданному соединению. None, если не найдена."""
pf = _sg_find_v8project(os.getcwd())
if not pf:
return None
try:
with open(pf, encoding="utf-8-sig") as f:
proj = json.load(f)
except Exception:
return None
for db in proj.get("databases") or []:
if args.InfoBasePath and db.get("path") and same_path(db["path"], args.InfoBasePath):
return db
if args.InfoBaseServer and args.InfoBaseRef and db.get("server") and db.get("ref"):
if (db["server"].lower() == args.InfoBaseServer.lower()
and db["ref"].lower() == args.InfoBaseRef.lower()):
return db
return None
def _find_project_v8path(args):
"""Walk up from CWD to find .v8-project.json and read its v8path.
v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
"""
db = find_project_database(args)
if db and db.get("v8path"):
return db["v8path"]
d = os.getcwd() d = os.getcwd()
while True: while True:
pf = os.path.join(d, ".v8-project.json") pf = os.path.join(d, ".v8-project.json")
@@ -243,10 +297,10 @@ def _version_key(p):
return [int(x) for x in re.findall(r"\d+", _version_dir(p))] return [int(x) for x in re.findall(r"\d+", _version_dir(p))]
def resolve_v8path(v8path): def resolve_v8path(v8path, args):
"""Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly)."""
if not v8path: if not v8path:
v8path = _find_project_v8path() v8path = _find_project_v8path(args)
if not v8path: if not v8path:
if os.name == "nt": if os.name == "nt":
candidates = ( candidates = (
@@ -437,7 +491,7 @@ def main():
assert_infobase_exists(args.InfoBasePath) assert_infobase_exists(args.InfoBasePath)
args.OutputFile = clean_path(args.OutputFile, "-OutputFile") args.OutputFile = clean_path(args.OutputFile, "-OutputFile")
v8path = resolve_v8path(args.V8Path) v8path = resolve_v8path(args.V8Path, args)
engine = "ibcmd" if os.path.basename(v8path).lower().startswith("ibcmd") else "1cv8" engine = "ibcmd" if os.path.basename(v8path).lower().startswith("ibcmd") else "1cv8"
# --- Resolve additional arguments for the selected engine --- # --- Resolve additional arguments for the selected engine ---
+2 -2
View File
@@ -24,12 +24,12 @@ allowed-tools:
## Параметры подключения ## Параметры подключения
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу: Прочитай `.v8-project.json` из корня проекта и разреши базу:
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую 1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json` 2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches` 3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
4. Если ветка не совпала — используй `default` 4. Если ветка не совпала — используй `default`
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files). Платформа — `v8path` найденной записи базы, иначе корневой `v8path`. Не задан ни там, ни там — `-V8Path` не передавай.
Если файла нет — предложи `/db-list add`. Если файла нет — предложи `/db-list add`.
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`. Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
Если в записи базы указан `configSrc` — используй как каталог выгрузки по умолчанию. Если в записи базы указан `configSrc` — используй как каталог выгрузки по умолчанию.
@@ -1,4 +1,4 @@
# db-dump-xml v1.21 — Dump 1C configuration to XML files # db-dump-xml v1.22 — Dump 1C configuration to XML files
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. # NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется.
<# <#
@@ -125,9 +125,10 @@ param(
$OutputEncoding = [System.Text.Encoding]::UTF8 $OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
# --- Реквизиты хранилища из .v8-project.json --- # --- Запись базы в .v8-project.json ---
# Модель их не передаёт: скрипт сопоставляет параметры соединения с записью в databases[] # Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# и берёт repository оттуда. Тот же приём, что в cf-edit.ps1 (сопоставление по configSrc). # сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.ps1 (сопоставление по configSrc).
function Find-V8Project([string]$startDir) { function Find-V8Project([string]$startDir) {
$d = $startDir $d = $startDir
for ($i = 0; $i -lt 20 -and $d; $i++) { for ($i = 0; $i -lt 20 -and $d; $i++) {
@@ -395,6 +396,10 @@ Assert-InfoBaseExists $InfoBasePath
# --- Resolve V8Path --- # --- Resolve V8Path ---
function Find-ProjectV8Path { function Find-ProjectV8Path {
# v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
# платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
$dbRec = Find-ProjectDatabase
if ($dbRec -and $dbRec.v8path) { return [string]$dbRec.v8path }
$dir = (Get-Location).Path $dir = (Get-Location).Path
while ($dir) { while ($dir) {
$pf = Join-Path $dir ".v8-project.json" $pf = Join-Path $dir ".v8-project.json"
@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# db-dump-xml v1.21 — Dump 1C configuration to XML files # db-dump-xml v1.22 — Dump 1C configuration to XML files
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse import argparse
@@ -37,8 +37,15 @@ def ci_parse_args(parser, argv=None):
def _find_project_v8path(): def _find_project_v8path(args):
"""Walk up from CWD to find .v8-project.json and read its v8path.""" """Walk up from CWD to find .v8-project.json and read its v8path.
v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
"""
db = find_project_database(args)
if db and db.get("v8path"):
return db["v8path"]
d = os.getcwd() d = os.getcwd()
while True: while True:
pf = os.path.join(d, ".v8-project.json") pf = os.path.join(d, ".v8-project.json")
@@ -87,9 +94,10 @@ V8_SECRET_KEYS = ["/P", "/UC", "/WSP", "/AWSP", "/ConfigurationRepositoryP"]
IBCMD_SECRET_KEYS = ["--password", "--token", "--db-pwd"] IBCMD_SECRET_KEYS = ["--password", "--token", "--db-pwd"]
# --- Реквизиты хранилища из .v8-project.json --- # --- Запись базы в .v8-project.json ---
# Модель их не передаёт: скрипт сопоставляет параметры соединения с записью в databases[] # Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# и берёт repository оттуда. Тот же приём, что в cf-edit.py (сопоставление по configSrc). # сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.py (сопоставление по configSrc).
def _sg_find_v8project(start_dir): def _sg_find_v8project(start_dir):
d = start_dir d = start_dir
for _ in range(20): for _ in range(20):
@@ -328,10 +336,10 @@ def _version_key(p):
return [int(x) for x in re.findall(r"\d+", _version_dir(p))] return [int(x) for x in re.findall(r"\d+", _version_dir(p))]
def resolve_v8path(v8path): def resolve_v8path(v8path, args):
"""Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly)."""
if not v8path: if not v8path:
v8path = _find_project_v8path() v8path = _find_project_v8path(args)
if not v8path: if not v8path:
if os.name == "nt": if os.name == "nt":
candidates = ( candidates = (
@@ -542,7 +550,7 @@ def main():
args.ConfigDir = clean_path(args.ConfigDir, "-ConfigDir") args.ConfigDir = clean_path(args.ConfigDir, "-ConfigDir")
# --- Resolve V8Path --- # --- Resolve V8Path ---
v8path = resolve_v8path(args.V8Path) v8path = resolve_v8path(args.V8Path, args)
engine = "ibcmd" if os.path.basename(v8path).lower().startswith("ibcmd") else "1cv8" engine = "ibcmd" if os.path.basename(v8path).lower().startswith("ibcmd") else "1cv8"
# --- Resolve additional arguments for the selected engine --- # --- Resolve additional arguments for the selected engine ---
+10 -2
View File
@@ -36,6 +36,7 @@ allowed-tools:
"name": "Разработка", "name": "Разработка",
"type": "file", "type": "file",
"path": "C:\\Bases\\MyApp_Dev", "path": "C:\\Bases\\MyApp_Dev",
"v8path": "C:\\Program Files\\1cv8\\8.3.27.1688\\bin",
"user": "Admin", "user": "Admin",
"password": "", "password": "",
"aliases": ["dev", "разработка"], "aliases": ["dev", "разработка"],
@@ -92,6 +93,7 @@ allowed-tools:
| `path` | string | для file | Путь к каталогу файловой базы | | `path` | string | для file | Путь к каталогу файловой базы |
| `server` | string | для server | Адрес сервера 1С | | `server` | string | для server | Адрес сервера 1С |
| `ref` | string | для server | Имя базы на сервере | | `ref` | string | для server | Имя базы на сервере |
| `v8path` | string | нет | Платформа именно этой базы — перекрывает корневой `v8path` (см. ниже) |
| `user` | string | нет | Имя пользователя 1С | | `user` | string | нет | Имя пользователя 1С |
| `password` | string | нет | Пароль | | `password` | string | нет | Пароль |
| `aliases` | string[] | нет | Альтернативные имена для быстрого доступа | | `aliases` | string[] | нет | Альтернативные имена для быстрого доступа |
@@ -145,9 +147,15 @@ allowed-tools:
После выполнения: если использованная база не зарегистрирована — предложи добавить через `/db-list add`. После выполнения: если использованная база не зарегистрирована — предложи добавить через `/db-list add`.
### Автоопределение платформы ### Выбор платформы
Если `v8path` не задан в конфиге: Порядок: явный `-V8Path` в вызове → `v8path` записи базы → корневой `v8path` → автоопределение.
Запись базы находит сам скрипт, сопоставляя параметры соединения с `databases[]`, — передавать
`-V8Path` руками не нужно. Поле у базы нужно, когда базы проекта живут на разных версиях платформы:
формат XML-выгрузки задаёт та платформа, которая выгружает, а автоопределение берёт самую старшую
установленную.
Если `v8path` не задан нигде:
```powershell ```powershell
$v8 = Get-ChildItem "C:\Program Files\1cv8\*\bin\1cv8.exe" | Sort-Object -Descending | Select-Object -First 1 $v8 = Get-ChildItem "C:\Program Files\1cv8\*\bin\1cv8.exe" | Sort-Object -Descending | Select-Object -First 1
+2 -2
View File
@@ -24,12 +24,12 @@ allowed-tools:
## Параметры подключения ## Параметры подключения
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу: Прочитай `.v8-project.json` из корня проекта и разреши базу:
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую 1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json` 2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches` 3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
4. Если ветка не совпала — используй `default` 4. Если ветка не совпала — используй `default`
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files). Платформа — `v8path` найденной записи базы, иначе корневой `v8path`. Не задан ни там, ни там — `-V8Path` не передавай.
Если файла нет — предложи `/db-list add`. Если файла нет — предложи `/db-list add`.
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`. Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
@@ -1,4 +1,4 @@
# db-load-cf v1.17 — Load 1C configuration from CF file # db-load-cf v1.18 — Load 1C configuration from CF file
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. # NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется.
<# <#
@@ -299,8 +299,41 @@ function Assert-InfoBaseExists {
Assert-InfoBaseExists $InfoBasePath Assert-InfoBaseExists $InfoBasePath
# --- Запись базы в .v8-project.json ---
# Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.ps1 (сопоставление по configSrc).
function Test-SamePath {
param([string]$A, [string]$B)
if (-not $A -or -not $B) { return $false }
try {
$na = [System.IO.Path]::GetFullPath($A).TrimEnd('\', '/')
$nb = [System.IO.Path]::GetFullPath($B).TrimEnd('\', '/')
return $na.Equals($nb, [System.StringComparison]::OrdinalIgnoreCase)
} catch { return $false }
}
function Find-ProjectDatabase {
# Запись базы в реестре, соответствующая переданному соединению. $null, если не найдена.
$pf = Find-V8Project (Get-Location).Path
if (-not $pf) { return $null }
try { $proj = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json } catch { return $null }
if (-not $proj.databases) { return $null }
foreach ($db in $proj.databases) {
if ($InfoBasePath -and $db.path -and (Test-SamePath $db.path $InfoBasePath)) { return $db }
if ($InfoBaseServer -and $InfoBaseRef -and $db.server -and $db.ref) {
if ($db.server.Equals($InfoBaseServer, [System.StringComparison]::OrdinalIgnoreCase) -and
$db.ref.Equals($InfoBaseRef, [System.StringComparison]::OrdinalIgnoreCase)) { return $db }
}
}
return $null
}
# --- Resolve V8Path --- # --- Resolve V8Path ---
function Find-ProjectV8Path { function Find-ProjectV8Path {
# v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
# платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
$dbRec = Find-ProjectDatabase
if ($dbRec -and $dbRec.v8path) { return [string]$dbRec.v8path }
$dir = (Get-Location).Path $dir = (Get-Location).Path
while ($dir) { while ($dir) {
$pf = Join-Path $dir ".v8-project.json" $pf = Join-Path $dir ".v8-project.json"
@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# db-load-cf v1.17 — Load 1C configuration from CF file # db-load-cf v1.18 — Load 1C configuration from CF file
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse import argparse
@@ -37,8 +37,48 @@ def ci_parse_args(parser, argv=None):
def _find_project_v8path(): # --- Запись базы в .v8-project.json ---
"""Walk up from CWD to find .v8-project.json and read its v8path.""" # Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.py (сопоставление по configSrc).
def same_path(a, b):
if not a or not b:
return False
try:
return os.path.abspath(a).rstrip("\\/").lower() == os.path.abspath(b).rstrip("\\/").lower()
except Exception:
return False
def find_project_database(args):
"""Запись базы в реестре, соответствующая переданному соединению. None, если не найдена."""
pf = _sg_find_v8project(os.getcwd())
if not pf:
return None
try:
with open(pf, encoding="utf-8-sig") as f:
proj = json.load(f)
except Exception:
return None
for db in proj.get("databases") or []:
if args.InfoBasePath and db.get("path") and same_path(db["path"], args.InfoBasePath):
return db
if args.InfoBaseServer and args.InfoBaseRef and db.get("server") and db.get("ref"):
if (db["server"].lower() == args.InfoBaseServer.lower()
and db["ref"].lower() == args.InfoBaseRef.lower()):
return db
return None
def _find_project_v8path(args):
"""Walk up from CWD to find .v8-project.json and read its v8path.
v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
"""
db = find_project_database(args)
if db and db.get("v8path"):
return db["v8path"]
d = os.getcwd() d = os.getcwd()
while True: while True:
pf = os.path.join(d, ".v8-project.json") pf = os.path.join(d, ".v8-project.json")
@@ -243,10 +283,10 @@ def _version_key(p):
return [int(x) for x in re.findall(r"\d+", _version_dir(p))] return [int(x) for x in re.findall(r"\d+", _version_dir(p))]
def resolve_v8path(v8path): def resolve_v8path(v8path, args):
"""Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly)."""
if not v8path: if not v8path:
v8path = _find_project_v8path() v8path = _find_project_v8path(args)
if not v8path: if not v8path:
if os.name == "nt": if os.name == "nt":
candidates = ( candidates = (
@@ -548,7 +588,7 @@ def main():
assert_infobase_exists(args.InfoBasePath) assert_infobase_exists(args.InfoBasePath)
args.InputFile = clean_path(args.InputFile, "-InputFile") args.InputFile = clean_path(args.InputFile, "-InputFile")
v8path = resolve_v8path(args.V8Path) v8path = resolve_v8path(args.V8Path, args)
engine = "ibcmd" if os.path.basename(v8path).lower().startswith("ibcmd") else "1cv8" engine = "ibcmd" if os.path.basename(v8path).lower().startswith("ibcmd") else "1cv8"
# --- Resolve additional arguments for the selected engine --- # --- Resolve additional arguments for the selected engine ---
+2 -2
View File
@@ -40,12 +40,12 @@ allowed-tools:
## Параметры подключения ## Параметры подключения
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу: Прочитай `.v8-project.json` из корня проекта и разреши базу:
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую 1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json` 2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches` 3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
4. Если ветка не совпала — используй `default` 4. Если ветка не совпала — используй `default`
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files). Платформа — `v8path` найденной записи базы, иначе корневой `v8path`. Не задан ни там, ни там — `-V8Path` не передавай.
Если файла нет — предложи `/db-list add`. Если файла нет — предложи `/db-list add`.
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`. Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
@@ -1,4 +1,4 @@
# db-load-dt v1.16 — Load 1C information base from DT file # db-load-dt v1.17 — Load 1C information base from DT file
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. # NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется.
<# <#
@@ -286,8 +286,52 @@ function Assert-InfoBaseExists {
Assert-InfoBaseExists $InfoBasePath Assert-InfoBaseExists $InfoBasePath
# --- Запись базы в .v8-project.json ---
# Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.ps1 (сопоставление по configSrc).
function Find-V8Project([string]$startDir) {
$d = $startDir
for ($i = 0; $i -lt 20 -and $d; $i++) {
$pj = Join-Path $d ".v8-project.json"
if (Test-Path $pj) { return $pj }
$parent = [System.IO.Path]::GetDirectoryName($d)
if ($parent -eq $d) { break }
$d = $parent
}
return $null
}
function Test-SamePath {
param([string]$A, [string]$B)
if (-not $A -or -not $B) { return $false }
try {
$na = [System.IO.Path]::GetFullPath($A).TrimEnd('\', '/')
$nb = [System.IO.Path]::GetFullPath($B).TrimEnd('\', '/')
return $na.Equals($nb, [System.StringComparison]::OrdinalIgnoreCase)
} catch { return $false }
}
function Find-ProjectDatabase {
# Запись базы в реестре, соответствующая переданному соединению. $null, если не найдена.
$pf = Find-V8Project (Get-Location).Path
if (-not $pf) { return $null }
try { $proj = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json } catch { return $null }
if (-not $proj.databases) { return $null }
foreach ($db in $proj.databases) {
if ($InfoBasePath -and $db.path -and (Test-SamePath $db.path $InfoBasePath)) { return $db }
if ($InfoBaseServer -and $InfoBaseRef -and $db.server -and $db.ref) {
if ($db.server.Equals($InfoBaseServer, [System.StringComparison]::OrdinalIgnoreCase) -and
$db.ref.Equals($InfoBaseRef, [System.StringComparison]::OrdinalIgnoreCase)) { return $db }
}
}
return $null
}
# --- Resolve V8Path --- # --- Resolve V8Path ---
function Find-ProjectV8Path { function Find-ProjectV8Path {
# v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
# платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
$dbRec = Find-ProjectDatabase
if ($dbRec -and $dbRec.v8path) { return [string]$dbRec.v8path }
$dir = (Get-Location).Path $dir = (Get-Location).Path
while ($dir) { while ($dir) {
$pf = Join-Path $dir ".v8-project.json" $pf = Join-Path $dir ".v8-project.json"
@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# db-load-dt v1.16 — Load 1C information base from DT file # db-load-dt v1.17 — Load 1C information base from DT file
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse import argparse
@@ -37,8 +37,62 @@ def ci_parse_args(parser, argv=None):
def _find_project_v8path(): # --- Запись базы в .v8-project.json ---
"""Walk up from CWD to find .v8-project.json and read its v8path.""" # Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.py (сопоставление по configSrc).
def _sg_find_v8project(start_dir):
d = start_dir
for _ in range(20):
if not d:
break
pj = os.path.join(d, ".v8-project.json")
if os.path.isfile(pj):
return pj
parent = os.path.dirname(d)
if parent == d:
break
d = parent
return None
def same_path(a, b):
if not a or not b:
return False
try:
return os.path.abspath(a).rstrip("\\/").lower() == os.path.abspath(b).rstrip("\\/").lower()
except Exception:
return False
def find_project_database(args):
"""Запись базы в реестре, соответствующая переданному соединению. None, если не найдена."""
pf = _sg_find_v8project(os.getcwd())
if not pf:
return None
try:
with open(pf, encoding="utf-8-sig") as f:
proj = json.load(f)
except Exception:
return None
for db in proj.get("databases") or []:
if args.InfoBasePath and db.get("path") and same_path(db["path"], args.InfoBasePath):
return db
if args.InfoBaseServer and args.InfoBaseRef and db.get("server") and db.get("ref"):
if (db["server"].lower() == args.InfoBaseServer.lower()
and db["ref"].lower() == args.InfoBaseRef.lower()):
return db
return None
def _find_project_v8path(args):
"""Walk up from CWD to find .v8-project.json and read its v8path.
v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
"""
db = find_project_database(args)
if db and db.get("v8path"):
return db["v8path"]
d = os.getcwd() d = os.getcwd()
while True: while True:
pf = os.path.join(d, ".v8-project.json") pf = os.path.join(d, ".v8-project.json")
@@ -243,10 +297,10 @@ def _version_key(p):
return [int(x) for x in re.findall(r"\d+", _version_dir(p))] return [int(x) for x in re.findall(r"\d+", _version_dir(p))]
def resolve_v8path(v8path): def resolve_v8path(v8path, args):
"""Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly)."""
if not v8path: if not v8path:
v8path = _find_project_v8path() v8path = _find_project_v8path(args)
if not v8path: if not v8path:
if os.name == "nt": if os.name == "nt":
candidates = ( candidates = (
@@ -457,7 +511,7 @@ def main():
assert_infobase_exists(args.InfoBasePath) assert_infobase_exists(args.InfoBasePath)
args.InputFile = clean_path(args.InputFile, "-InputFile") args.InputFile = clean_path(args.InputFile, "-InputFile")
v8path = resolve_v8path(args.V8Path) v8path = resolve_v8path(args.V8Path, args)
engine = "ibcmd" if os.path.basename(v8path).lower().startswith("ibcmd") else "1cv8" engine = "ibcmd" if os.path.basename(v8path).lower().startswith("ibcmd") else "1cv8"
# --- Resolve additional arguments for the selected engine --- # --- Resolve additional arguments for the selected engine ---
+2 -2
View File
@@ -25,12 +25,12 @@ allowed-tools:
## Параметры подключения ## Параметры подключения
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу: Прочитай `.v8-project.json` из корня проекта и разреши базу:
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую 1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json` 2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches` 3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
4. Если ветка не совпала — используй `default` 4. Если ветка не совпала — используй `default`
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files). Платформа — `v8path` найденной записи базы, иначе корневой `v8path`. Не задан ни там, ни там — `-V8Path` не передавай.
Если файла нет — предложи `/db-list add`. Если файла нет — предложи `/db-list add`.
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`. Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
Если в записи базы указан `configSrc` — используй как каталог конфигурации. Если в записи базы указан `configSrc` — используй как каталог конфигурации.
@@ -1,4 +1,4 @@
# db-load-git v1.26 — Load Git changes into 1C database # db-load-git v1.27 — Load Git changes into 1C database
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. # NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется.
<# <#
@@ -139,9 +139,10 @@ param(
$OutputEncoding = [System.Text.Encoding]::UTF8 $OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
# --- Реквизиты хранилища из .v8-project.json --- # --- Запись базы в .v8-project.json ---
# Модель их не передаёт: скрипт сопоставляет параметры соединения с записью в databases[] # Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# и берёт repository оттуда. Тот же приём, что в cf-edit.ps1 (сопоставление по configSrc). # сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.ps1 (сопоставление по configSrc).
function Find-V8Project([string]$startDir) { function Find-V8Project([string]$startDir) {
$d = $startDir $d = $startDir
for ($i = 0; $i -lt 20 -and $d; $i++) { for ($i = 0; $i -lt 20 -and $d; $i++) {
@@ -427,6 +428,10 @@ function Get-ObjectXmlFromSubFile {
# --- Resolve V8Path (skip if DryRun) --- # --- Resolve V8Path (skip if DryRun) ---
if (-not $DryRun) { if (-not $DryRun) {
function Find-ProjectV8Path { function Find-ProjectV8Path {
# v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
# платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
$dbRec = Find-ProjectDatabase
if ($dbRec -and $dbRec.v8path) { return [string]$dbRec.v8path }
$dir = (Get-Location).Path $dir = (Get-Location).Path
while ($dir) { while ($dir) {
$pf = Join-Path $dir ".v8-project.json" $pf = Join-Path $dir ".v8-project.json"
@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# db-load-git v1.26 — Load Git changes into 1C database # db-load-git v1.27 — Load Git changes into 1C database
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse import argparse
@@ -37,8 +37,15 @@ def ci_parse_args(parser, argv=None):
def _find_project_v8path(): def _find_project_v8path(args):
"""Walk up from CWD to find .v8-project.json and read its v8path.""" """Walk up from CWD to find .v8-project.json and read its v8path.
v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
"""
db = find_project_database(args)
if db and db.get("v8path"):
return db["v8path"]
d = os.getcwd() d = os.getcwd()
while True: while True:
pf = os.path.join(d, ".v8-project.json") pf = os.path.join(d, ".v8-project.json")
@@ -87,9 +94,10 @@ V8_SECRET_KEYS = ["/P", "/UC", "/WSP", "/AWSP", "/ConfigurationRepositoryP"]
IBCMD_SECRET_KEYS = ["--password", "--token", "--db-pwd"] IBCMD_SECRET_KEYS = ["--password", "--token", "--db-pwd"]
# --- Реквизиты хранилища из .v8-project.json --- # --- Запись базы в .v8-project.json ---
# Модель их не передаёт: скрипт сопоставляет параметры соединения с записью в databases[] # Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# и берёт repository оттуда. Тот же приём, что в cf-edit.py (сопоставление по configSrc). # сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.py (сопоставление по configSrc).
def _sg_find_v8project(start_dir): def _sg_find_v8project(start_dir):
d = start_dir d = start_dir
for _ in range(20): for _ in range(20):
@@ -349,10 +357,10 @@ def _version_key(p):
return [int(x) for x in re.findall(r"\d+", _version_dir(p))] return [int(x) for x in re.findall(r"\d+", _version_dir(p))]
def resolve_v8path(v8path): def resolve_v8path(v8path, args):
"""Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly)."""
if not v8path: if not v8path:
v8path = _find_project_v8path() v8path = _find_project_v8path(args)
if not v8path: if not v8path:
if os.name == "nt": if os.name == "nt":
candidates = ( candidates = (
@@ -714,7 +722,7 @@ def main():
# --- Resolve V8Path (skip if DryRun) --- # --- Resolve V8Path (skip if DryRun) ---
v8path = None v8path = None
if not args.DryRun: if not args.DryRun:
v8path = resolve_v8path(args.V8Path) v8path = resolve_v8path(args.V8Path, args)
# --- Detect engine + validate connection (skip if DryRun) --- # --- Detect engine + validate connection (skip if DryRun) ---
engine = "1cv8" engine = "1cv8"
+2 -2
View File
@@ -25,12 +25,12 @@ allowed-tools:
## Параметры подключения ## Параметры подключения
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу: Прочитай `.v8-project.json` из корня проекта и разреши базу:
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую 1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json` 2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches` 3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
4. Если ветка не совпала — используй `default` 4. Если ветка не совпала — используй `default`
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files). Платформа — `v8path` найденной записи базы, иначе корневой `v8path`. Не задан ни там, ни там — `-V8Path` не передавай.
Если файла нет — предложи `/db-list add`. Если файла нет — предложи `/db-list add`.
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`. Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
Если в записи базы указан `configSrc` — используй как каталог загрузки по умолчанию. Если в записи базы указан `configSrc` — используй как каталог загрузки по умолчанию.
@@ -1,4 +1,4 @@
# db-load-xml v1.28 — Load 1C configuration from XML files # db-load-xml v1.29 — Load 1C configuration from XML files
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. # NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется.
<# <#
@@ -135,9 +135,10 @@ param(
$OutputEncoding = [System.Text.Encoding]::UTF8 $OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
# --- Реквизиты хранилища из .v8-project.json --- # --- Запись базы в .v8-project.json ---
# Модель их не передаёт: скрипт сопоставляет параметры соединения с записью в databases[] # Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# и берёт repository оттуда. Тот же приём, что в cf-edit.ps1 (сопоставление по configSrc). # сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.ps1 (сопоставление по configSrc).
function Find-V8Project([string]$startDir) { function Find-V8Project([string]$startDir) {
$d = $startDir $d = $startDir
for ($i = 0; $i -lt 20 -and $d; $i++) { for ($i = 0; $i -lt 20 -and $d; $i++) {
@@ -448,6 +449,10 @@ Assert-InfoBaseExists $InfoBasePath
# --- Resolve V8Path --- # --- Resolve V8Path ---
function Find-ProjectV8Path { function Find-ProjectV8Path {
# v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
# платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
$dbRec = Find-ProjectDatabase
if ($dbRec -and $dbRec.v8path) { return [string]$dbRec.v8path }
$dir = (Get-Location).Path $dir = (Get-Location).Path
while ($dir) { while ($dir) {
$pf = Join-Path $dir ".v8-project.json" $pf = Join-Path $dir ".v8-project.json"
@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# db-load-xml v1.28 — Load 1C configuration from XML files # db-load-xml v1.29 — Load 1C configuration from XML files
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse import argparse
@@ -37,8 +37,15 @@ def ci_parse_args(parser, argv=None):
def _find_project_v8path(): def _find_project_v8path(args):
"""Walk up from CWD to find .v8-project.json and read its v8path.""" """Walk up from CWD to find .v8-project.json and read its v8path.
v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
"""
db = find_project_database(args)
if db and db.get("v8path"):
return db["v8path"]
d = os.getcwd() d = os.getcwd()
while True: while True:
pf = os.path.join(d, ".v8-project.json") pf = os.path.join(d, ".v8-project.json")
@@ -87,9 +94,10 @@ V8_SECRET_KEYS = ["/P", "/UC", "/WSP", "/AWSP", "/ConfigurationRepositoryP"]
IBCMD_SECRET_KEYS = ["--password", "--token", "--db-pwd"] IBCMD_SECRET_KEYS = ["--password", "--token", "--db-pwd"]
# --- Реквизиты хранилища из .v8-project.json --- # --- Запись базы в .v8-project.json ---
# Модель их не передаёт: скрипт сопоставляет параметры соединения с записью в databases[] # Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# и берёт repository оттуда. Тот же приём, что в cf-edit.py (сопоставление по configSrc). # сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.py (сопоставление по configSrc).
def _sg_find_v8project(start_dir): def _sg_find_v8project(start_dir):
d = start_dir d = start_dir
for _ in range(20): for _ in range(20):
@@ -349,10 +357,10 @@ def _version_key(p):
return [int(x) for x in re.findall(r"\d+", _version_dir(p))] return [int(x) for x in re.findall(r"\d+", _version_dir(p))]
def resolve_v8path(v8path): def resolve_v8path(v8path, args):
"""Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly)."""
if not v8path: if not v8path:
v8path = _find_project_v8path() v8path = _find_project_v8path(args)
if not v8path: if not v8path:
if os.name == "nt": if os.name == "nt":
candidates = ( candidates = (
@@ -692,7 +700,7 @@ def main():
args.ListFile = clean_path(args.ListFile, "-ListFile") args.ListFile = clean_path(args.ListFile, "-ListFile")
# --- Resolve V8Path --- # --- Resolve V8Path ---
v8path = resolve_v8path(args.V8Path) v8path = resolve_v8path(args.V8Path, args)
engine = "ibcmd" if os.path.basename(v8path).lower().startswith("ibcmd") else "1cv8" engine = "ibcmd" if os.path.basename(v8path).lower().startswith("ibcmd") else "1cv8"
+3 -1
View File
@@ -63,12 +63,14 @@ allowed-tools:
## Параметры подключения ## Параметры подключения
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` и разреши базу: Прочитай `.v8-project.json` из корня проекта и разреши базу:
1. Если пользователь указал параметры подключения — используй напрямую 1. Если пользователь указал параметры подключения — используй напрямую
2. Если указал базу по имени — ищи по id / alias / name 2. Если указал базу по имени — ищи по id / alias / name
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches` 3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
4. Если ветка не совпала — используй `default` 4. Если ветка не совпала — используй `default`
Платформа — `v8path` найденной записи базы, иначе корневой `v8path`. Не задан ни там, ни там — `-V8Path` не передавай.
Реквизиты хранилища передавать не нужно: запись базы находится по переданным параметрам Реквизиты хранилища передавать не нужно: запись базы находится по переданным параметрам
соединения (`-InfoBasePath` либо `-InfoBaseServer` + `-InfoBaseRef`), реквизиты берутся из её соединения (`-InfoBasePath` либо `-InfoBaseServer` + `-InfoBaseRef`), реквизиты берутся из её
`repository`. Задать их явно можно параметрами `-Repository*`. `repository`. Задать их явно можно параметрами `-Repository*`.
+9 -4
View File
@@ -1,4 +1,4 @@
# db-repo v1.14 — 1C configuration repository operations # db-repo v1.15 — 1C configuration repository operations
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# NB: движок только 1cv8 — ibcmd работу с хранилищем не поддерживает (нет такого режима). # NB: движок только 1cv8 — ibcmd работу с хранилищем не поддерживает (нет такого режима).
<# <#
@@ -322,6 +322,10 @@ Assert-InfoBaseExists $InfoBasePath
# --- Resolve V8Path --- # --- Resolve V8Path ---
function Find-ProjectV8Path { function Find-ProjectV8Path {
# v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
# платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
$dbRec = Find-ProjectDatabase
if ($dbRec -and $dbRec.v8path) { return [string]$dbRec.v8path }
$dir = (Get-Location).Path $dir = (Get-Location).Path
while ($dir) { while ($dir) {
$pf = Join-Path $dir ".v8-project.json" $pf = Join-Path $dir ".v8-project.json"
@@ -499,9 +503,10 @@ function Invoke-PlatformProcess {
return [pscustomobject]@{ Output = $out; ExitCode = $p.ExitCode } return [pscustomobject]@{ Output = $out; ExitCode = $p.ExitCode }
} }
# --- Реквизиты хранилища из .v8-project.json --- # --- Запись базы в .v8-project.json ---
# Модель их не передаёт: скрипт сопоставляет параметры соединения с записью в databases[] # Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# и берёт repository оттуда. Тот же приём, что в cf-edit.ps1 (сопоставление по configSrc). # сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.ps1 (сопоставление по configSrc).
function Find-V8Project([string]$startDir) { function Find-V8Project([string]$startDir) {
$d = $startDir $d = $startDir
for ($i = 0; $i -lt 20 -and $d; $i++) { for ($i = 0; $i -lt 20 -and $d; $i++) {
+17 -9
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# db-repo v1.14 — 1C configuration repository operations # db-repo v1.15 — 1C configuration repository operations
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# NB: движок только 1cv8 — ibcmd работу с хранилищем не поддерживает (нет такого режима). # NB: движок только 1cv8 — ibcmd работу с хранилищем не поддерживает (нет такого режима).
"""Работа с хранилищем конфигурации 1С. """Работа с хранилищем конфигурации 1С.
@@ -78,8 +78,15 @@ def ci_parse_args(parser, argv=None):
return parser.parse_args(argv) return parser.parse_args(argv)
def _find_project_v8path(): def _find_project_v8path(args):
"""Walk up from CWD to find .v8-project.json and read its v8path.""" """Walk up from CWD to find .v8-project.json and read its v8path.
v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
"""
db = find_project_database(args)
if db and db.get("v8path"):
return db["v8path"]
d = os.getcwd() d = os.getcwd()
while True: while True:
pf = os.path.join(d, ".v8-project.json") pf = os.path.join(d, ".v8-project.json")
@@ -224,10 +231,10 @@ def _version_key(p):
return [int(x) for x in re.findall(r"\d+", _version_dir(p))] return [int(x) for x in re.findall(r"\d+", _version_dir(p))]
def resolve_v8path(v8path): def resolve_v8path(v8path, args):
"""Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly)."""
if not v8path: if not v8path:
v8path = _find_project_v8path() v8path = _find_project_v8path(args)
if not v8path: if not v8path:
if os.name == "nt": if os.name == "nt":
candidates = ( candidates = (
@@ -405,9 +412,10 @@ def resolve_extra_args(v8_extra, hints):
return extra return extra
# --- Реквизиты хранилища из .v8-project.json --- # --- Запись базы в .v8-project.json ---
# Модель их не передаёт: скрипт сопоставляет параметры соединения с записью в databases[] # Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# и берёт repository оттуда. Тот же приём, что в cf-edit.py (сопоставление по configSrc). # сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.py (сопоставление по configSrc).
def _sg_find_v8project(start_dir): def _sg_find_v8project(start_dir):
d = start_dir d = start_dir
for _ in range(20): for _ in range(20):
@@ -983,7 +991,7 @@ def main():
args.V8Path = clean_path(args.V8Path, "-V8Path") args.V8Path = clean_path(args.V8Path, "-V8Path")
args.InfoBasePath = clean_path(args.InfoBasePath, "-InfoBasePath") args.InfoBasePath = clean_path(args.InfoBasePath, "-InfoBasePath")
assert_infobase_exists(args.InfoBasePath) assert_infobase_exists(args.InfoBasePath)
v8path = resolve_v8path(args.V8Path) v8path = resolve_v8path(args.V8Path, args)
if not args.Command: if not args.Command:
print("Error: -Command is required. Known: %s" % ", ".join(sorted(COMMAND_KEYS))) print("Error: -Command is required. Known: %s" % ", ".join(sorted(COMMAND_KEYS)))
+2 -2
View File
@@ -24,12 +24,12 @@ allowed-tools:
## Параметры подключения ## Параметры подключения
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу: Прочитай `.v8-project.json` из корня проекта и разреши базу:
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую 1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json` 2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches` 3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
4. Если ветка не совпала — используй `default` 4. Если ветка не совпала — используй `default`
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files). Платформа — `v8path` найденной записи базы, иначе корневой `v8path`. Не задан ни там, ни там — `-V8Path` не передавай.
Если файла нет — предложи `/db-list add`. Если файла нет — предложи `/db-list add`.
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`. Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
+45 -1
View File
@@ -1,4 +1,4 @@
# db-run v1.10 — Launch 1C:Enterprise # db-run v1.11 — Launch 1C:Enterprise
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. # NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется.
<# <#
@@ -262,8 +262,52 @@ $V8Path = ConvertTo-CleanPath $V8Path '-V8Path'
$InfoBasePath = ConvertTo-CleanPath $InfoBasePath '-InfoBasePath' $InfoBasePath = ConvertTo-CleanPath $InfoBasePath '-InfoBasePath'
$Execute = ConvertTo-CleanPath $Execute '-Execute' $Execute = ConvertTo-CleanPath $Execute '-Execute'
# --- Запись базы в .v8-project.json ---
# Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.ps1 (сопоставление по configSrc).
function Find-V8Project([string]$startDir) {
$d = $startDir
for ($i = 0; $i -lt 20 -and $d; $i++) {
$pj = Join-Path $d ".v8-project.json"
if (Test-Path $pj) { return $pj }
$parent = [System.IO.Path]::GetDirectoryName($d)
if ($parent -eq $d) { break }
$d = $parent
}
return $null
}
function Test-SamePath {
param([string]$A, [string]$B)
if (-not $A -or -not $B) { return $false }
try {
$na = [System.IO.Path]::GetFullPath($A).TrimEnd('\', '/')
$nb = [System.IO.Path]::GetFullPath($B).TrimEnd('\', '/')
return $na.Equals($nb, [System.StringComparison]::OrdinalIgnoreCase)
} catch { return $false }
}
function Find-ProjectDatabase {
# Запись базы в реестре, соответствующая переданному соединению. $null, если не найдена.
$pf = Find-V8Project (Get-Location).Path
if (-not $pf) { return $null }
try { $proj = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json } catch { return $null }
if (-not $proj.databases) { return $null }
foreach ($db in $proj.databases) {
if ($InfoBasePath -and $db.path -and (Test-SamePath $db.path $InfoBasePath)) { return $db }
if ($InfoBaseServer -and $InfoBaseRef -and $db.server -and $db.ref) {
if ($db.server.Equals($InfoBaseServer, [System.StringComparison]::OrdinalIgnoreCase) -and
$db.ref.Equals($InfoBaseRef, [System.StringComparison]::OrdinalIgnoreCase)) { return $db }
}
}
return $null
}
# --- Resolve V8Path --- # --- Resolve V8Path ---
function Find-ProjectV8Path { function Find-ProjectV8Path {
# v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
# платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
$dbRec = Find-ProjectDatabase
if ($dbRec -and $dbRec.v8path) { return [string]$dbRec.v8path }
$dir = (Get-Location).Path $dir = (Get-Location).Path
while ($dir) { while ($dir) {
$pf = Join-Path $dir ".v8-project.json" $pf = Join-Path $dir ".v8-project.json"
+60 -6
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# db-run v1.10 — Launch 1C:Enterprise # db-run v1.11 — Launch 1C:Enterprise
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse import argparse
@@ -34,8 +34,62 @@ def ci_parse_args(parser, argv=None):
def _find_project_v8path(): # --- Запись базы в .v8-project.json ---
"""Walk up from CWD to find .v8-project.json and read its v8path.""" # Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.py (сопоставление по configSrc).
def _sg_find_v8project(start_dir):
d = start_dir
for _ in range(20):
if not d:
break
pj = os.path.join(d, ".v8-project.json")
if os.path.isfile(pj):
return pj
parent = os.path.dirname(d)
if parent == d:
break
d = parent
return None
def same_path(a, b):
if not a or not b:
return False
try:
return os.path.abspath(a).rstrip("\\/").lower() == os.path.abspath(b).rstrip("\\/").lower()
except Exception:
return False
def find_project_database(args):
"""Запись базы в реестре, соответствующая переданному соединению. None, если не найдена."""
pf = _sg_find_v8project(os.getcwd())
if not pf:
return None
try:
with open(pf, encoding="utf-8-sig") as f:
proj = json.load(f)
except Exception:
return None
for db in proj.get("databases") or []:
if args.InfoBasePath and db.get("path") and same_path(db["path"], args.InfoBasePath):
return db
if args.InfoBaseServer and args.InfoBaseRef and db.get("server") and db.get("ref"):
if (db["server"].lower() == args.InfoBaseServer.lower()
and db["ref"].lower() == args.InfoBaseRef.lower()):
return db
return None
def _find_project_v8path(args):
"""Walk up from CWD to find .v8-project.json and read its v8path.
v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
"""
db = find_project_database(args)
if db and db.get("v8path"):
return db["v8path"]
d = os.getcwd() d = os.getcwd()
while True: while True:
pf = os.path.join(d, ".v8-project.json") pf = os.path.join(d, ".v8-project.json")
@@ -258,10 +312,10 @@ def _version_key(p):
return [int(x) for x in re.findall(r"\d+", _version_dir(p))] return [int(x) for x in re.findall(r"\d+", _version_dir(p))]
def resolve_v8path(v8path): def resolve_v8path(v8path, args):
"""Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly)."""
if not v8path: if not v8path:
v8path = _find_project_v8path() v8path = _find_project_v8path(args)
if not v8path: if not v8path:
if os.name == "nt": if os.name == "nt":
candidates = ( candidates = (
@@ -324,7 +378,7 @@ def main():
args.InfoBasePath = clean_path(args.InfoBasePath, "-InfoBasePath") args.InfoBasePath = clean_path(args.InfoBasePath, "-InfoBasePath")
args.Execute = clean_path(args.Execute, "-Execute") args.Execute = clean_path(args.Execute, "-Execute")
v8path = resolve_v8path(args.V8Path) v8path = resolve_v8path(args.V8Path, args)
# --- Resolve additional arguments --- # --- Resolve additional arguments ---
# 1C:Enterprise is always launched by 1cv8 — ibcmd has no interactive mode. # 1C:Enterprise is always launched by 1cv8 — ibcmd has no interactive mode.
+2 -2
View File
@@ -25,12 +25,12 @@ allowed-tools:
## Параметры подключения ## Параметры подключения
Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` (путь к платформе) и разреши базу: Прочитай `.v8-project.json` из корня проекта и разреши базу:
1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую 1. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json` 2. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
3. Если не указал — сопоставь текущую ветку Git с `databases[].branches` 3. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
4. Если ветка не совпала — используй `default` 4. Если ветка не совпала — используй `default`
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files). Платформа — `v8path` найденной записи базы, иначе корневой `v8path`. Не задан ни там, ни там — `-V8Path` не передавай.
Если файла нет — предложи `/db-list add`. Если файла нет — предложи `/db-list add`.
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`. Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
@@ -1,4 +1,4 @@
# db-update v1.20 — Update 1C database configuration # db-update v1.21 — Update 1C database configuration
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. # NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется.
<# <#
@@ -124,9 +124,10 @@ if ($Dynamic) { $Dynamic = if (@('on', 'yes', '+') -contains $Dynamic.ToLower())
$OutputEncoding = [System.Text.Encoding]::UTF8 $OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
# --- Реквизиты хранилища из .v8-project.json --- # --- Запись базы в .v8-project.json ---
# Модель их не передаёт: скрипт сопоставляет параметры соединения с записью в databases[] # Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# и берёт repository оттуда. Тот же приём, что в cf-edit.ps1 (сопоставление по configSrc). # сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.ps1 (сопоставление по configSrc).
function Find-V8Project([string]$startDir) { function Find-V8Project([string]$startDir) {
$d = $startDir $d = $startDir
for ($i = 0; $i -lt 20 -and $d; $i++) { for ($i = 0; $i -lt 20 -and $d; $i++) {
@@ -410,6 +411,10 @@ Assert-InfoBaseExists $InfoBasePath
# --- Resolve V8Path --- # --- Resolve V8Path ---
function Find-ProjectV8Path { function Find-ProjectV8Path {
# v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
# платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
$dbRec = Find-ProjectDatabase
if ($dbRec -and $dbRec.v8path) { return [string]$dbRec.v8path }
$dir = (Get-Location).Path $dir = (Get-Location).Path
while ($dir) { while ($dir) {
$pf = Join-Path $dir ".v8-project.json" $pf = Join-Path $dir ".v8-project.json"
+17 -9
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# db-update v1.20 — Update 1C database configuration # db-update v1.21 — Update 1C database configuration
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse import argparse
@@ -37,8 +37,15 @@ def ci_parse_args(parser, argv=None):
def _find_project_v8path(): def _find_project_v8path(args):
"""Walk up from CWD to find .v8-project.json and read its v8path.""" """Walk up from CWD to find .v8-project.json and read its v8path.
v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
"""
db = find_project_database(args)
if db and db.get("v8path"):
return db["v8path"]
d = os.getcwd() d = os.getcwd()
while True: while True:
pf = os.path.join(d, ".v8-project.json") pf = os.path.join(d, ".v8-project.json")
@@ -87,9 +94,10 @@ V8_SECRET_KEYS = ["/P", "/UC", "/WSP", "/AWSP", "/ConfigurationRepositoryP"]
IBCMD_SECRET_KEYS = ["--password", "--token", "--db-pwd"] IBCMD_SECRET_KEYS = ["--password", "--token", "--db-pwd"]
# --- Реквизиты хранилища из .v8-project.json --- # --- Запись базы в .v8-project.json ---
# Модель их не передаёт: скрипт сопоставляет параметры соединения с записью в databases[] # Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# и берёт repository оттуда. Тот же приём, что в cf-edit.py (сопоставление по configSrc). # сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.py (сопоставление по configSrc).
def _sg_find_v8project(start_dir): def _sg_find_v8project(start_dir):
d = start_dir d = start_dir
for _ in range(20): for _ in range(20):
@@ -328,10 +336,10 @@ def _version_key(p):
return [int(x) for x in re.findall(r"\d+", _version_dir(p))] return [int(x) for x in re.findall(r"\d+", _version_dir(p))]
def resolve_v8path(v8path): def resolve_v8path(v8path, args):
"""Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly)."""
if not v8path: if not v8path:
v8path = _find_project_v8path() v8path = _find_project_v8path(args)
if not v8path: if not v8path:
if os.name == "nt": if os.name == "nt":
candidates = ( candidates = (
@@ -659,7 +667,7 @@ def main():
args.InfoBasePath = clean_path(args.InfoBasePath, "-InfoBasePath") args.InfoBasePath = clean_path(args.InfoBasePath, "-InfoBasePath")
assert_infobase_exists(args.InfoBasePath) assert_infobase_exists(args.InfoBasePath)
v8path = resolve_v8path(args.V8Path) v8path = resolve_v8path(args.V8Path, args)
engine = "ibcmd" if os.path.basename(v8path).lower().startswith("ibcmd") else "1cv8" engine = "ibcmd" if os.path.basename(v8path).lower().startswith("ibcmd") else "1cv8"
+2 -2
View File
@@ -28,14 +28,14 @@ allowed-tools:
Предпочтительно использовать конкретную базу — это надёжнее. Временная база всё равно поднимается Предпочтительно использовать конкретную базу — это надёжнее. Временная база всё равно поднимается
под проверку исходников, если она не отключена. под проверку исходников, если она не отключена.
1. Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` и разреши базу: 1. Прочитай `.v8-project.json` из корня проекта и разреши базу:
2. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую 2. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
3. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json` 3. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
4. Если не указал — сопоставь текущую ветку Git с `databases[].branches` 4. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
5. Если ветка не совпала — используй `default` 5. Если ветка не совпала — используй `default`
6. Если `.v8-project.json` нет или база не найдена — не указывай параметры подключения: скрипт автоматически создаст временную базу. Для EPF со ссылочными типами (CatalogRef, DocumentRef и т.д.) генерируются заглушки метаданных. Временная база удаляется после сборки. 6. Если `.v8-project.json` нет или база не найдена — не указывай параметры подключения: скрипт автоматически создаст временную базу. Для EPF со ссылочными типами (CatalogRef, DocumentRef и т.д.) генерируются заглушки метаданных. Временная база удаляется после сборки.
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files). Платформа — `v8path` найденной записи базы, иначе корневой `v8path`. Не задан ни там, ни там — `-V8Path` не передавай.
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`. Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
## Команда ## Команда
+34 -1
View File
@@ -1,4 +1,4 @@
# epf-build v1.17 — Build external data processor or report (EPF/ERF) from XML sources # epf-build v1.18 — Build external data processor or report (EPF/ERF) from XML sources
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. # NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется.
<# <#
@@ -276,8 +276,41 @@ function Assert-InfoBaseExists {
Assert-InfoBaseExists $InfoBasePath Assert-InfoBaseExists $InfoBasePath
# --- Запись базы в .v8-project.json ---
# Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.ps1 (сопоставление по configSrc).
function Test-SamePath {
param([string]$A, [string]$B)
if (-not $A -or -not $B) { return $false }
try {
$na = [System.IO.Path]::GetFullPath($A).TrimEnd('\', '/')
$nb = [System.IO.Path]::GetFullPath($B).TrimEnd('\', '/')
return $na.Equals($nb, [System.StringComparison]::OrdinalIgnoreCase)
} catch { return $false }
}
function Find-ProjectDatabase {
# Запись базы в реестре, соответствующая переданному соединению. $null, если не найдена.
$pf = Find-V8Project (Get-Location).Path
if (-not $pf) { return $null }
try { $proj = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json } catch { return $null }
if (-not $proj.databases) { return $null }
foreach ($db in $proj.databases) {
if ($InfoBasePath -and $db.path -and (Test-SamePath $db.path $InfoBasePath)) { return $db }
if ($InfoBaseServer -and $InfoBaseRef -and $db.server -and $db.ref) {
if ($db.server.Equals($InfoBaseServer, [System.StringComparison]::OrdinalIgnoreCase) -and
$db.ref.Equals($InfoBaseRef, [System.StringComparison]::OrdinalIgnoreCase)) { return $db }
}
}
return $null
}
# --- Resolve V8Path --- # --- Resolve V8Path ---
function Find-ProjectV8Path { function Find-ProjectV8Path {
# v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
# платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
$dbRec = Find-ProjectDatabase
if ($dbRec -and $dbRec.v8path) { return [string]$dbRec.v8path }
$dir = (Get-Location).Path $dir = (Get-Location).Path
while ($dir) { while ($dir) {
$pf = Join-Path $dir ".v8-project.json" $pf = Join-Path $dir ".v8-project.json"
+46 -6
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# epf-build v1.17 — Build external data processor or report (EPF/ERF) from XML sources # epf-build v1.18 — Build external data processor or report (EPF/ERF) from XML sources
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse import argparse
@@ -38,8 +38,48 @@ def ci_parse_args(parser, argv=None):
def _find_project_v8path(): # --- Запись базы в .v8-project.json ---
"""Walk up from CWD to find .v8-project.json and read its v8path.""" # Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.py (сопоставление по configSrc).
def same_path(a, b):
if not a or not b:
return False
try:
return os.path.abspath(a).rstrip("\\/").lower() == os.path.abspath(b).rstrip("\\/").lower()
except Exception:
return False
def find_project_database(args):
"""Запись базы в реестре, соответствующая переданному соединению. None, если не найдена."""
pf = _sg_find_v8project(os.getcwd())
if not pf:
return None
try:
with open(pf, encoding="utf-8-sig") as f:
proj = json.load(f)
except Exception:
return None
for db in proj.get("databases") or []:
if args.InfoBasePath and db.get("path") and same_path(db["path"], args.InfoBasePath):
return db
if args.InfoBaseServer and args.InfoBaseRef and db.get("server") and db.get("ref"):
if (db["server"].lower() == args.InfoBaseServer.lower()
and db["ref"].lower() == args.InfoBaseRef.lower()):
return db
return None
def _find_project_v8path(args):
"""Walk up from CWD to find .v8-project.json and read its v8path.
v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
"""
db = find_project_database(args)
if db and db.get("v8path"):
return db["v8path"]
d = os.getcwd() d = os.getcwd()
while True: while True:
pf = os.path.join(d, ".v8-project.json") pf = os.path.join(d, ".v8-project.json")
@@ -244,10 +284,10 @@ def _version_key(p):
return [int(x) for x in re.findall(r"\d+", _version_dir(p))] return [int(x) for x in re.findall(r"\d+", _version_dir(p))]
def resolve_v8path(v8path): def resolve_v8path(v8path, args):
"""Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly)."""
if not v8path: if not v8path:
v8path = _find_project_v8path() v8path = _find_project_v8path(args)
if not v8path: if not v8path:
if os.name == "nt": if os.name == "nt":
candidates = ( candidates = (
@@ -576,7 +616,7 @@ def main():
args.OutputFile = clean_path(args.OutputFile, "-OutputFile") args.OutputFile = clean_path(args.OutputFile, "-OutputFile")
# --- Resolve V8Path --- # --- Resolve V8Path ---
v8path = resolve_v8path(args.V8Path) v8path = resolve_v8path(args.V8Path, args)
engine = "ibcmd" if os.path.basename(v8path).lower().startswith("ibcmd") else "1cv8" engine = "ibcmd" if os.path.basename(v8path).lower().startswith("ibcmd") else "1cv8"
# --- Resolve additional arguments for the selected engine --- # --- Resolve additional arguments for the selected engine ---
+2 -2
View File
@@ -26,14 +26,14 @@ allowed-tools:
Для разборки EPF/ERF требуется информационная база с конфигурацией. Без базы ссылочные типы безвозвратно теряются. Для разборки EPF/ERF требуется информационная база с конфигурацией. Без базы ссылочные типы безвозвратно теряются.
1. Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` и разреши базу: 1. Прочитай `.v8-project.json` из корня проекта и разреши базу:
2. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую 2. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
3. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json` 3. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
4. Если не указал — сопоставь текущую ветку Git с `databases[].branches` 4. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
5. Если ветка не совпала — используй `default` 5. Если ветка не совпала — используй `default`
6. Если `.v8-project.json` нет или база не найдена — **сообщи пользователю об ошибке**. Для dump база обязательна: в пустой базе ссылочные типы (CatalogRef, DocumentRef и т.д.) безвозвратно сбрасываются в строки. Предложи указать базу или зарегистрировать через `/db-list add`. 6. Если `.v8-project.json` нет или база не найдена — **сообщи пользователю об ошибке**. Для dump база обязательна: в пустой базе ссылочные типы (CatalogRef, DocumentRef и т.д.) безвозвратно сбрасываются в строки. Предложи указать базу или зарегистрировать через `/db-list add`.
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files). Платформа — `v8path` найденной записи базы, иначе корневой `v8path`. Не задан ни там, ни там — `-V8Path` не передавай.
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`. Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
## Команда ## Команда
+45 -1
View File
@@ -1,4 +1,4 @@
# epf-dump v1.15 — Dump external data processor or report (EPF/ERF) to XML sources # epf-dump v1.16 — Dump external data processor or report (EPF/ERF) to XML sources
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
# NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. # NB: *nix-раскладку платформы (/opt/1cv8/<ver>/1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется.
<# <#
@@ -267,8 +267,52 @@ function Assert-InfoBaseExists {
Assert-InfoBaseExists $InfoBasePath Assert-InfoBaseExists $InfoBasePath
# --- Запись базы в .v8-project.json ---
# Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.ps1 (сопоставление по configSrc).
function Find-V8Project([string]$startDir) {
$d = $startDir
for ($i = 0; $i -lt 20 -and $d; $i++) {
$pj = Join-Path $d ".v8-project.json"
if (Test-Path $pj) { return $pj }
$parent = [System.IO.Path]::GetDirectoryName($d)
if ($parent -eq $d) { break }
$d = $parent
}
return $null
}
function Test-SamePath {
param([string]$A, [string]$B)
if (-not $A -or -not $B) { return $false }
try {
$na = [System.IO.Path]::GetFullPath($A).TrimEnd('\', '/')
$nb = [System.IO.Path]::GetFullPath($B).TrimEnd('\', '/')
return $na.Equals($nb, [System.StringComparison]::OrdinalIgnoreCase)
} catch { return $false }
}
function Find-ProjectDatabase {
# Запись базы в реестре, соответствующая переданному соединению. $null, если не найдена.
$pf = Find-V8Project (Get-Location).Path
if (-not $pf) { return $null }
try { $proj = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json } catch { return $null }
if (-not $proj.databases) { return $null }
foreach ($db in $proj.databases) {
if ($InfoBasePath -and $db.path -and (Test-SamePath $db.path $InfoBasePath)) { return $db }
if ($InfoBaseServer -and $InfoBaseRef -and $db.server -and $db.ref) {
if ($db.server.Equals($InfoBaseServer, [System.StringComparison]::OrdinalIgnoreCase) -and
$db.ref.Equals($InfoBaseRef, [System.StringComparison]::OrdinalIgnoreCase)) { return $db }
}
}
return $null
}
# --- Resolve V8Path --- # --- Resolve V8Path ---
function Find-ProjectV8Path { function Find-ProjectV8Path {
# v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
# платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
$dbRec = Find-ProjectDatabase
if ($dbRec -and $dbRec.v8path) { return [string]$dbRec.v8path }
$dir = (Get-Location).Path $dir = (Get-Location).Path
while ($dir) { while ($dir) {
$pf = Join-Path $dir ".v8-project.json" $pf = Join-Path $dir ".v8-project.json"
+60 -6
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# epf-dump v1.15 — Dump external data processor or report (EPF/ERF) to XML sources # epf-dump v1.16 — Dump external data processor or report (EPF/ERF) to XML sources
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse import argparse
@@ -37,8 +37,62 @@ def ci_parse_args(parser, argv=None):
def _find_project_v8path(): # --- Запись базы в .v8-project.json ---
"""Walk up from CWD to find .v8-project.json and read its v8path.""" # Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.py (сопоставление по configSrc).
def _sg_find_v8project(start_dir):
d = start_dir
for _ in range(20):
if not d:
break
pj = os.path.join(d, ".v8-project.json")
if os.path.isfile(pj):
return pj
parent = os.path.dirname(d)
if parent == d:
break
d = parent
return None
def same_path(a, b):
if not a or not b:
return False
try:
return os.path.abspath(a).rstrip("\\/").lower() == os.path.abspath(b).rstrip("\\/").lower()
except Exception:
return False
def find_project_database(args):
"""Запись базы в реестре, соответствующая переданному соединению. None, если не найдена."""
pf = _sg_find_v8project(os.getcwd())
if not pf:
return None
try:
with open(pf, encoding="utf-8-sig") as f:
proj = json.load(f)
except Exception:
return None
for db in proj.get("databases") or []:
if args.InfoBasePath and db.get("path") and same_path(db["path"], args.InfoBasePath):
return db
if args.InfoBaseServer and args.InfoBaseRef and db.get("server") and db.get("ref"):
if (db["server"].lower() == args.InfoBaseServer.lower()
and db["ref"].lower() == args.InfoBaseRef.lower()):
return db
return None
def _find_project_v8path(args):
"""Walk up from CWD to find .v8-project.json and read its v8path.
v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
"""
db = find_project_database(args)
if db and db.get("v8path"):
return db["v8path"]
d = os.getcwd() d = os.getcwd()
while True: while True:
pf = os.path.join(d, ".v8-project.json") pf = os.path.join(d, ".v8-project.json")
@@ -243,10 +297,10 @@ def _version_key(p):
return [int(x) for x in re.findall(r"\d+", _version_dir(p))] return [int(x) for x in re.findall(r"\d+", _version_dir(p))]
def resolve_v8path(v8path): def resolve_v8path(v8path, args):
"""Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly).""" """Resolve path to a 1C executable (1cv8; ibcmd only when given explicitly)."""
if not v8path: if not v8path:
v8path = _find_project_v8path() v8path = _find_project_v8path(args)
if not v8path: if not v8path:
if os.name == "nt": if os.name == "nt":
candidates = ( candidates = (
@@ -446,7 +500,7 @@ def main():
args.OutputDir = clean_path(args.OutputDir, "-OutputDir") args.OutputDir = clean_path(args.OutputDir, "-OutputDir")
# --- Resolve V8Path --- # --- Resolve V8Path ---
v8path = resolve_v8path(args.V8Path) v8path = resolve_v8path(args.V8Path, args)
engine = "ibcmd" if os.path.basename(v8path).lower().startswith("ibcmd") else "1cv8" engine = "ibcmd" if os.path.basename(v8path).lower().startswith("ibcmd") else "1cv8"
# --- Resolve additional arguments for the selected engine --- # --- Resolve additional arguments for the selected engine ---
+2 -2
View File
@@ -28,14 +28,14 @@ allowed-tools:
Предпочтительно использовать конкретную базу — это надёжнее. Временная база всё равно поднимается Предпочтительно использовать конкретную базу — это надёжнее. Временная база всё равно поднимается
под проверку исходников, если она не отключена. под проверку исходников, если она не отключена.
1. Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` и разреши базу: 1. Прочитай `.v8-project.json` из корня проекта и разреши базу:
2. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую 2. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
3. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json` 3. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
4. Если не указал — сопоставь текущую ветку Git с `databases[].branches` 4. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
5. Если ветка не совпала — используй `default` 5. Если ветка не совпала — используй `default`
6. Если `.v8-project.json` нет или база не найдена — не указывай параметры подключения: скрипт автоматически создаст временную базу. Для ERF со ссылочными типами (CatalogRef, DocumentRef и т.д.) генерируются заглушки метаданных. Временная база удаляется после сборки. 6. Если `.v8-project.json` нет или база не найдена — не указывай параметры подключения: скрипт автоматически создаст временную базу. Для ERF со ссылочными типами (CatalogRef, DocumentRef и т.д.) генерируются заглушки метаданных. Временная база удаляется после сборки.
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files). Платформа — `v8path` найденной записи базы, иначе корневой `v8path`. Не задан ни там, ни там — `-V8Path` не передавай.
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`. Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
## Команда ## Команда
+2 -2
View File
@@ -26,14 +26,14 @@ allowed-tools:
Для разборки EPF/ERF требуется информационная база с конфигурацией. Без базы ссылочные типы безвозвратно теряются. Для разборки EPF/ERF требуется информационная база с конфигурацией. Без базы ссылочные типы безвозвратно теряются.
1. Прочитай `.v8-project.json` из корня проекта. Возьми `v8path` и разреши базу: 1. Прочитай `.v8-project.json` из корня проекта и разреши базу:
2. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую 2. Если пользователь указал параметры подключения (путь, сервер) — используй напрямую
3. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json` 3. Если указал базу по имени — ищи по id / alias / name в `.v8-project.json`
4. Если не указал — сопоставь текущую ветку Git с `databases[].branches` 4. Если не указал — сопоставь текущую ветку Git с `databases[].branches`
5. Если ветка не совпала — используй `default` 5. Если ветка не совпала — используй `default`
6. Если `.v8-project.json` нет или база не найдена — **сообщи пользователю об ошибке**. Для dump база обязательна: в пустой базе ссылочные типы (CatalogRef, DocumentRef и т.д.) безвозвратно сбрасываются в строки. Предложи указать базу или зарегистрировать через `/db-list add`. 6. Если `.v8-project.json` нет или база не найдена — **сообщи пользователю об ошибке**. Для dump база обязательна: в пустой базе ссылочные типы (CatalogRef, DocumentRef и т.д.) безвозвратно сбрасываются в строки. Предложи указать базу или зарегистрировать через `/db-list add`.
Если `v8path` не задан — скрипт сам попытается определить платформу (`.v8-project.json` → Program Files). Платформа — `v8path` найденной записи базы, иначе корневой `v8path`. Не задан ни там, ни там — `-V8Path` не передавай.
Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`. Если использованная база не зарегистрирована — после выполнения предложи добавить через `/db-list add`.
## Команда ## Команда
+1 -1
View File
@@ -31,7 +31,7 @@ allowed-tools:
4. Если ветка не совпала — используй `default` 4. Если ветка не совпала — используй `default`
**ОБЯЗАТЕЛЬНО передавай все найденные параметры:** **ОБЯЗАТЕЛЬНО передавай все найденные параметры:**
- **`-V8Path`** — из `v8path` в `.v8-project.json`. Если не передать, скрипт автоопределит версию платформы, что может выбрать не ту версию - **`-V8Path`** — `v8path` найденной записи базы, иначе корневой `v8path`. Не задан ни там, ни там — не передавай, но версия платформы тогда выберется автоматически и может оказаться не той
- **`-UserName`** — из поля `user` найденной записи базы (если есть) - **`-UserName`** — из поля `user` найденной записи базы (если есть)
- **`-Password`** — из поля `password` найденной записи базы (если есть) - **`-Password`** — из поля `password` найденной записи базы (если есть)
- **`-ApachePath`** — из `webPath` в `.v8-project.json` (если есть) - **`-ApachePath`** — из `webPath` в `.v8-project.json` (если есть)
@@ -1,4 +1,4 @@
# web-publish v1.9 — Publish 1C infobase via Apache (+_version_dir/_version_key: общий эталон db-семейства) # web-publish v1.10 — Publish 1C infobase via Apache (+_version_dir/_version_key: общий эталон db-семейства)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
<# <#
.SYNOPSIS .SYNOPSIS
@@ -86,8 +86,52 @@ param(
$OutputEncoding = [System.Text.Encoding]::UTF8 $OutputEncoding = [System.Text.Encoding]::UTF8
[Console]::OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
# --- Запись базы в .v8-project.json ---
# Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.ps1 (сопоставление по configSrc).
function Find-V8Project([string]$startDir) {
$d = $startDir
for ($i = 0; $i -lt 20 -and $d; $i++) {
$pj = Join-Path $d ".v8-project.json"
if (Test-Path $pj) { return $pj }
$parent = [System.IO.Path]::GetDirectoryName($d)
if ($parent -eq $d) { break }
$d = $parent
}
return $null
}
function Test-SamePath {
param([string]$A, [string]$B)
if (-not $A -or -not $B) { return $false }
try {
$na = [System.IO.Path]::GetFullPath($A).TrimEnd('\', '/')
$nb = [System.IO.Path]::GetFullPath($B).TrimEnd('\', '/')
return $na.Equals($nb, [System.StringComparison]::OrdinalIgnoreCase)
} catch { return $false }
}
function Find-ProjectDatabase {
# Запись базы в реестре, соответствующая переданному соединению. $null, если не найдена.
$pf = Find-V8Project (Get-Location).Path
if (-not $pf) { return $null }
try { $proj = Get-Content $pf -Raw -Encoding UTF8 | ConvertFrom-Json } catch { return $null }
if (-not $proj.databases) { return $null }
foreach ($db in $proj.databases) {
if ($InfoBasePath -and $db.path -and (Test-SamePath $db.path $InfoBasePath)) { return $db }
if ($InfoBaseServer -and $InfoBaseRef -and $db.server -and $db.ref) {
if ($db.server.Equals($InfoBaseServer, [System.StringComparison]::OrdinalIgnoreCase) -and
$db.ref.Equals($InfoBaseRef, [System.StringComparison]::OrdinalIgnoreCase)) { return $db }
}
}
return $null
}
# --- Resolve V8Path --- # --- Resolve V8Path ---
function Find-ProjectV8Path { function Find-ProjectV8Path {
# v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
# платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
$dbRec = Find-ProjectDatabase
if ($dbRec -and $dbRec.v8path) { return [string]$dbRec.v8path }
$dir = (Get-Location).Path $dir = (Get-Location).Path
while ($dir) { while ($dir) {
$pf = Join-Path $dir ".v8-project.json" $pf = Join-Path $dir ".v8-project.json"
@@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# web-publish v1.9 — Publish 1C infobase via Apache (+_version_dir/_version_key: общий эталон db-семейства) # web-publish v1.10 — Publish 1C infobase via Apache (+_version_dir/_version_key: общий эталон db-семейства)
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
""" """
@@ -47,8 +47,62 @@ def ci_parse_args(parser, argv=None):
def _find_project_v8path(): # --- Запись базы в .v8-project.json ---
"""Walk up from CWD to find .v8-project.json and read its v8path.""" # Модель не передаёт ни путь к платформе конкретной базы, ни реквизиты хранилища: скрипт
# сопоставляет параметры соединения с записью в databases[] и берёт их оттуда. Тот же приём,
# что в cf-edit.py (сопоставление по configSrc).
def _sg_find_v8project(start_dir):
d = start_dir
for _ in range(20):
if not d:
break
pj = os.path.join(d, ".v8-project.json")
if os.path.isfile(pj):
return pj
parent = os.path.dirname(d)
if parent == d:
break
d = parent
return None
def same_path(a, b):
if not a or not b:
return False
try:
return os.path.abspath(a).rstrip("\\/").lower() == os.path.abspath(b).rstrip("\\/").lower()
except Exception:
return False
def find_project_database(args):
"""Запись базы в реестре, соответствующая переданному соединению. None, если не найдена."""
pf = _sg_find_v8project(os.getcwd())
if not pf:
return None
try:
with open(pf, encoding="utf-8-sig") as f:
proj = json.load(f)
except Exception:
return None
for db in proj.get("databases") or []:
if args.InfoBasePath and db.get("path") and same_path(db["path"], args.InfoBasePath):
return db
if args.InfoBaseServer and args.InfoBaseRef and db.get("server") and db.get("ref"):
if (db["server"].lower() == args.InfoBaseServer.lower()
and db["ref"].lower() == args.InfoBaseRef.lower()):
return db
return None
def _find_project_v8path(args):
"""Walk up from CWD to find .v8-project.json and read its v8path.
v8path записи базы сильнее корневого: в одном проекте базы живут на разных версиях
платформы, а версию формата выгрузки задаёт та платформа, которая выгружает.
"""
db = find_project_database(args)
if db and db.get("v8path"):
return db["v8path"]
d = os.getcwd() d = os.getcwd()
while True: while True:
pf = os.path.join(d, ".v8-project.json") pf = os.path.join(d, ".v8-project.json")
@@ -135,7 +189,7 @@ def main():
# --- Resolve V8Path --- # --- Resolve V8Path ---
v8_path = args.V8Path v8_path = args.V8Path
if not v8_path: if not v8_path:
v8_path = _find_project_v8path() v8_path = _find_project_v8path(args)
if not v8_path: if not v8_path:
candidates = ( candidates = (
glob.glob(r'C:\Program Files\1cv8\*\bin\1cv8.exe') glob.glob(r'C:\Program Files\1cv8\*\bin\1cv8.exe')
+1
View File
@@ -6,6 +6,7 @@
"name": "Разработка", "name": "Разработка",
"type": "file", "type": "file",
"path": "C:\\Bases\\MyApp_Dev", "path": "C:\\Bases\\MyApp_Dev",
"v8path": "C:\\Program Files\\1cv8\\8.3.27.1688\\bin",
"user": "Администратор", "user": "Администратор",
"password": "", "password": "",
"aliases": [ "aliases": [
+3 -1
View File
@@ -139,7 +139,9 @@ Claude вызовет `/db-run dev`.
> Собери обработку, платформа C:\Program Files\1cv8\8.3.24.1691\bin\ibcmd.exe > Собери обработку, платформа C:\Program Files\1cv8\8.3.24.1691\bin\ibcmd.exe
``` ```
- **в файле настроек** — прописать в `v8path` не каталог `bin`, а сам файл `...\bin\ibcmd.exe` - **в файле настроек** — прописать в `v8path` не каталог `bin`, а сам файл `...\bin\ibcmd.exe`
(тогда через `ibcmd` пойдут все операции). (тогда через `ibcmd` пойдут все операции). Это работает и в `v8path` отдельной базы — там же
задаётся её платформа, если базы проекта живут на разных версиях
(см. [конфигурацию проекта](v8-project-guide.md#платформа-базы-v8path)).
Через `ibcmd` работают: `db-create`, `db-load-xml`/`db-dump-xml` (в том числе по отдельным объектам Через `ibcmd` работают: `db-create`, `db-load-xml`/`db-dump-xml` (в том числе по отдельным объектам
и со всеми расширениями), `db-load-cf`/`db-dump-cf`, `db-load-dt`/`db-dump-dt`, `db-update`, и со всеми расширениями), `db-load-cf`/`db-dump-cf`, `db-load-dt`/`db-dump-dt`, `db-update`,
+33 -1
View File
@@ -22,6 +22,7 @@
"name": "Разработка", // отображаемое имя "name": "Разработка", // отображаемое имя
"type": "file", // "file" или "server" "type": "file", // "file" или "server"
"path": "C:\\Bases\\MyApp_Dev", // каталог (для file) "path": "C:\\Bases\\MyApp_Dev", // каталог (для file)
"v8path": "C:\\Program Files\\1cv8\\8.3.27.1688\\bin", // платформа именно этой базы (см. ниже)
"user": "Admin", // пользователь 1С "user": "Admin", // пользователь 1С
"password": "", // пароль "password": "", // пароль
"aliases": ["dev", "разработка"], // альтернативные имена "aliases": ["dev", "разработка"], // альтернативные имена
@@ -98,6 +99,7 @@
| `path` | string | для file | Каталог файловой базы | `/db-list add` | | `path` | string | для file | Каталог файловой базы | `/db-list add` |
| `server` | string | для server | Адрес сервера 1С | `/db-list add` | | `server` | string | для server | Адрес сервера 1С | `/db-list add` |
| `ref` | string | для server | Имя базы на сервере | `/db-list add` | | `ref` | string | для server | Имя базы на сервере | `/db-list add` |
| `v8path` | string | нет | Платформа этой базы — перекрывает корневой `v8path` (см. ниже) | Руками |
| `user` | string | нет | Пользователь 1С | `/db-list add` или руками | | `user` | string | нет | Пользователь 1С | `/db-list add` или руками |
| `password` | string | нет | Пароль | `/db-list add` или руками | | `password` | string | нет | Пароль | `/db-list add` или руками |
| `aliases` | string[] | нет | Альтернативные имена для обращения к базе | `/db-list add` или руками | | `aliases` | string[] | нет | Альтернативные имена для обращения к базе | `/db-list add` или руками |
@@ -110,6 +112,33 @@
| `repository` | object | нет | Хранилище конфигурации: `path`, `user`, `password` (см. ниже) | Руками | | `repository` | object | нет | Хранилище конфигурации: `path`, `user`, `password` (см. ниже) | Руками |
| `extensions` | array | нет | Расширения конфигурации: `name`, `src`, необязательное `repository` (см. ниже) | Руками | | `extensions` | array | нет | Расширения конфигурации: `name`, `src`, необязательное `repository` (см. ниже) | Руками |
### Платформа базы (`v8path`)
Корневой `v8path` — платформа проекта, `databases[].v8path` — платформа **этой** базы. Порядок
выбора у всех навыков, запускающих платформу:
1. явный `-V8Path` в вызове;
2. `v8path` записи базы, соответствующей переданному соединению;
3. корневой `v8path`;
4. автопоиск — **самая старшая** установленная платформа.
Запись ищет сам скрипт: сопоставляет параметры соединения с `databases[]` — файловую базу по
`path`, серверную по паре `server` + `ref`. Передавать `-V8Path` вручную не нужно.
Поле закрывает два случая:
- **базы проекта живут на разных версиях платформы** — каждая открывается своей;
- **формат XML-выгрузки** (`version` в `Configuration.xml`) задаёт та платформа, **которая
выгружает**; режим совместимости конфигурации на него не влияет. Выгрузка с 8.5 даёт формат 2.21,
и коллега на 8.3.27 её уже не загрузит: «Неизвестная версия формата». Прибив базе платформу, вы
прибиваете и формат её исходников. Без поля сработает автопоиск и возьмёт самую свежую
установленную платформу — то есть самый новый формат.
Значение — тот же вид пути, что и у корневого: каталог `bin`, либо сам `1cv8.exe`/`ibcmd.exe`
(см. «Движок: 1cv8 или ibcmd»). Путь машинный, а `.v8-project.json` у каждого свой — договориться
внутри команды о версии всё равно придётся, поле лишь не даёт ошибиться при переключении между
базами.
### Хранилище конфигурации (`repository`, `extensions[]`) ### Хранилище конфигурации (`repository`, `extensions[]`)
База, подключённая к хранилищу конфигурации, не принимает **ни одной** операции конфигуратора без База, подключённая к хранилищу конфигурации, не принимает **ни одной** операции конфигуратора без
@@ -194,6 +223,8 @@
5. Если не найдено — Claude спросит пользователя 5. Если не найдено — Claude спросит пользователя
6. Если база не зарегистрирована — Claude предложит `/db-list add` 6. Если база не зарегистрирована — Claude предложит `/db-list add`
Платформу для найденной базы подставляет сам скрипт — см. «Платформа базы (`v8path`)».
## Настройки инструментов ## Настройки инструментов
### `webPath` — Apache HTTP Server ### `webPath` — Apache HTTP Server
@@ -263,7 +294,8 @@ src/
- **разово, в самой задаче** — назвать полный путь к `ibcmd.exe`, например - **разово, в самой задаче** — назвать полный путь к `ibcmd.exe`, например
`C:\\Program Files\\1cv8\\8.3.24.1691\\bin\\ibcmd.exe`; `C:\\Program Files\\1cv8\\8.3.24.1691\\bin\\ibcmd.exe`;
- **в файле настроек** — прописать в `v8path` не каталог `bin`, а сам файл `...\\bin\\ibcmd.exe` (тогда через - **в файле настроек** — прописать в `v8path` не каталог `bin`, а сам файл `...\\bin\\ibcmd.exe` (тогда через
`ibcmd` пойдут все операции). `ibcmd` пойдут все операции). То же работает и в `v8path` записи базы — тогда через `ibcmd`
пойдут операции только с ней.
Через `ibcmd` навыки работают только с файловыми базами — для клиент-серверных `ibcmd` требует Через `ibcmd` навыки работают только с файловыми базами — для клиент-серверных `ibcmd` требует
прямых реквизитов СУБД, которые навыки не запрашивают. Список навыков, работающих через `ibcmd`, — прямых реквизитов СУБД, которые навыки не запрашивают. Список навыков, работающих через `ibcmd`, —
@@ -0,0 +1,24 @@
{
"name": "Платформа берётся из v8path записи базы, а не из корневого",
"fakePlatform": { "log": "" },
"preRun": [
{
"writeFile": {
"path": ".v8-project.json",
"content": {
"v8path": "{workDir}/nowhere/1cv8.exe",
"databases": [
{ "id": "dev", "name": "Dev", "type": "file", "path": "{workDir}/ib", "v8path": "{fakePlatform}" }
]
}
}
}
],
"args_extra": ["-InfoBasePath", "{workDir}/ib"],
"cwd": "workDir",
"expect": {
"stdoutContains": "Information base created successfully",
"stdoutNotContains": "nowhere"
},
"noSnapshot": "проверяется выбор платформы по stdout, файлов на выходе нет"
}
@@ -0,0 +1,22 @@
{
"name": "Соединение не совпало ни с одной записью — берётся корневой v8path",
"fakePlatform": { "log": "" },
"preRun": [
{
"writeFile": {
"path": ".v8-project.json",
"content": {
"v8path": "{workDir}/nowhere/1cv8.exe",
"databases": [
{ "id": "other", "name": "Other", "type": "file", "path": "{workDir}/other", "v8path": "{fakePlatform}" }
]
}
}
}
],
"args_extra": ["-InfoBasePath", "{workDir}/ib"],
"cwd": "workDir",
"expectError": true,
"expect": { "stdoutContains": "1C executable not found at" },
"noSnapshot": "проверяется выбор платформы по stdout, файлов на выходе нет"
}
@@ -0,0 +1,21 @@
{
"name": "У записи базы нет v8path — берётся корневой",
"fakePlatform": { "log": "" },
"preRun": [
{
"writeFile": {
"path": ".v8-project.json",
"content": {
"v8path": "{fakePlatform}",
"databases": [
{ "id": "dev", "name": "Dev", "type": "file", "path": "{workDir}/ib" }
]
}
}
}
],
"args_extra": ["-InfoBasePath", "{workDir}/ib"],
"cwd": "workDir",
"expect": { "stdoutContains": "Information base created successfully" },
"noSnapshot": "проверяется выбор платформы по stdout, файлов на выходе нет"
}
+28 -10
View File
@@ -88,10 +88,12 @@ const FAMILIES = [
variants: [ variants: [
// Имя с префиксом _sg_ историческое: функция просто ищет .v8-project.json обходом // Имя с префиксом _sg_ историческое: функция просто ищет .v8-project.json обходом
// вверх. Группа db-* использует её же, чтобы найти запись базы и взять реквизиты // вверх. Группа db-* использует её же, чтобы найти запись базы и взять реквизиты
// хранилища — задача одна, поэтому семья общая, а не вторая с тем же телом. // хранилища и путь к платформе — задача одна, поэтому семья общая, а не вторая с тем же телом.
{ id: 'full', authority: 'cf-edit', { id: 'full', authority: 'cf-edit',
consumers: ['cfe-borrow', 'db-cfe-admin', 'db-dump-xml', 'db-load-cf', 'db-load-git', 'db-load-xml', 'db-repo', 'db-update', consumers: ['cfe-borrow', 'db-cfe-admin', 'db-create', 'db-dump-cf', 'db-dump-dt', 'db-dump-xml',
'epf-build', 'form-add', 'form-compile', 'form-edit', 'help-add', 'interface-edit', 'meta-compile', 'db-load-cf', 'db-load-dt', 'db-load-git', 'db-load-xml', 'db-repo', 'db-run', 'db-update',
'epf-build', 'epf-dump', 'web-publish',
'form-add', 'form-compile', 'form-edit', 'help-add', 'interface-edit', 'meta-compile',
'meta-edit', 'meta-remove', 'mxl-compile', 'role-compile', 'role-edit', 'skd-compile', 'skd-edit', 'meta-edit', 'meta-remove', 'mxl-compile', 'role-compile', 'role-edit', 'skd-compile', 'skd-edit',
'subsystem-compile', 'subsystem-edit', 'template-add', 'xdto-compile', 'xdto-edit'] }, 'subsystem-compile', 'subsystem-edit', 'template-add', 'xdto-compile', 'xdto-edit'] },
], ],
@@ -386,6 +388,16 @@ const FAMILIES = [
'db-load-xml', 'db-repo', 'db-run', 'db-update', 'epf-build', 'epf-dump', 'web-publish', 'db-cfe-admin'] }, 'db-load-xml', 'db-repo', 'db-run', 'db-update', 'epf-build', 'epf-dump', 'web-publish', 'db-cfe-admin'] },
], ],
}, },
{
// Обёртка выбора платформы: запись базы → корневой v8path → автопоиск. В PS1 её роль
// играет не функция, а блок кода после объявления Find-ProjectV8Path, поэтому ps1: null.
name: 'platform: resolve_v8path', py: 'resolve_v8path', ps1: null,
variants: [
{ id: 'base', authority: 'db-create',
consumers: ['db-dump-cf', 'db-dump-dt', 'db-dump-xml', 'db-load-cf', 'db-load-dt', 'db-load-git',
'db-load-xml', 'db-repo', 'db-run', 'db-update', 'epf-build', 'epf-dump', 'db-cfe-admin'] },
],
},
{ {
name: 'platform: find_project_v8path', py: '_find_project_v8path', ps1: 'Find-ProjectV8Path', name: 'platform: find_project_v8path', py: '_find_project_v8path', ps1: 'Find-ProjectV8Path',
variants: [ variants: [
@@ -399,18 +411,24 @@ const FAMILIES = [
name: 'repository: load hints', py: 'write_repository_hints', ps1: 'Write-RepositoryHints', name: 'repository: load hints', py: 'write_repository_hints', ps1: 'Write-RepositoryHints',
variants: [{ id: 'base', authority: 'db-load-xml', consumers: ['db-load-git'] }], variants: [{ id: 'base', authority: 'db-load-xml', consumers: ['db-load-git'] }],
}, },
// ─── Реквизиты хранилища конфигурации ──────────────────────────────────── // ─── Запись базы в .v8-project.json ──────────────────────────────────────
// База под хранилищем не принимает ни одной операции конфигуратора без реквизитов // Модель не передаёт ни реквизиты хранилища (без них база под хранилищем не принимает
// доступа, и модель их не передаёт: скрипт сам сопоставляет параметры соединения с // ни одной операции конфигуратора), ни путь к платформе конкретной базы: скрипт сам
// записью в databases[]. Блок копируется во все навыки группы, работающие с // сопоставляет параметры соединения с записью в databases[]. Матч один на обе задачи,
// конфигурацией базы. // поэтому блок копируется во все навыки, запускающие платформу.
{ {
name: 'repository: same_path', py: 'same_path', ps1: 'Test-SamePath', name: 'repository: same_path', py: 'same_path', ps1: 'Test-SamePath',
variants: [{ id: 'base', authority: 'db-repo', consumers: ['db-dump-xml', 'db-load-git', 'db-load-xml', 'db-update', 'db-cfe-admin'] }], variants: [{ id: 'base', authority: 'db-repo',
consumers: ['db-cfe-admin', 'db-create', 'db-dump-cf', 'db-dump-dt', 'db-dump-xml', 'db-load-cf',
'db-load-dt', 'db-load-git', 'db-load-xml', 'db-run', 'db-update', 'epf-build', 'epf-dump',
'web-publish'] }],
}, },
{ {
name: 'repository: find_project_database', py: 'find_project_database', ps1: 'Find-ProjectDatabase', name: 'repository: find_project_database', py: 'find_project_database', ps1: 'Find-ProjectDatabase',
variants: [{ id: 'base', authority: 'db-repo', consumers: ['db-dump-xml', 'db-load-git', 'db-load-xml', 'db-update', 'db-cfe-admin'] }], variants: [{ id: 'base', authority: 'db-repo',
consumers: ['db-cfe-admin', 'db-create', 'db-dump-cf', 'db-dump-dt', 'db-dump-xml', 'db-load-cf',
'db-load-dt', 'db-load-git', 'db-load-xml', 'db-run', 'db-update', 'epf-build', 'epf-dump',
'web-publish'] }],
}, },
{ {
name: 'repository: resolve_settings', py: 'resolve_repository_settings', ps1: 'Resolve-RepositorySettings', name: 'repository: resolve_settings', py: 'resolve_repository_settings', ps1: 'Resolve-RepositorySettings',
+24 -8
View File
@@ -274,6 +274,25 @@ function cleanupWorkspace(ws) {
// ─── Arg building ─────────────────────────────────────────────────────────── // ─── Arg building ───────────────────────────────────────────────────────────
// Плейсхолдеры кейса: {workDir} — абсолютный путь рабочего каталога, {fakePlatform} — путь к
// фейковой платформе, которую раскладывает writeFakePlatform (имя зависит от ОС, поэтому кейс
// адресует её плейсхолдером и остаётся кроссплатформенным). Подстановка нужна не только в
// аргументах: путь к фейку кладут и ВНУТРЬ подложенного .v8-project.json — иначе кейс про
// выбор платформы пришлось бы писать двумя копиями под osOnly.
function substPlaceholders(s, workDir) {
const fakePath = join(workDir, process.platform === 'win32' ? 'fake.cmd' : 'fake.sh');
return s.replaceAll('{workDir}', workDir).replaceAll('{fakePlatform}', fakePath);
}
function substDeep(value, workDir) {
if (typeof value === 'string') return substPlaceholders(value, workDir);
if (Array.isArray(value)) return value.map(v => substDeep(v, workDir));
if (value && typeof value === 'object') {
return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, substDeep(v, workDir)]));
}
return value;
}
// Байты входного файла в заданной кодировке. Нужно для кейсов про кодировку: writeFileSync // Байты входного файла в заданной кодировке. Нужно для кейсов про кодировку: writeFileSync
// пишет только UTF-8, а навык обязан одинаково вести себя на UTF-16 с BOM (принять) и на // пишет только UTF-8, а навык обязан одинаково вести себя на UTF-16 с BOM (принять) и на
// cp1251 (отвергнуть, а не молча подменить кириллицу на U+FFFD). cp1251 в Node нет — кодируем // cp1251 (отвергнуть, а не молча подменить кириллицу на U+FFFD). cp1251 в Node нет — кодируем
@@ -355,13 +374,8 @@ function buildArgs(skillConfig, caseData, workDir, inputFilePath, runtime) {
} }
// Append extra args from case (for optional params like -Vendor, -Version). // Append extra args from case (for optional params like -Vendor, -Version).
// Supports {workDir} substitution for tests that need absolute paths inside the workspace,
// and {fakePlatform} — путь к фейковой платформе, которую раскладывает writeFakePlatform.
if (caseData.args_extra) { if (caseData.args_extra) {
const fakePath = join(workDir, process.platform === 'win32' ? 'fake.cmd' : 'fake.sh'); args.push(...caseData.args_extra.map(a => typeof a === 'string' ? substPlaceholders(a, workDir) : a));
args.push(...caseData.args_extra.map(a => typeof a === 'string'
? a.replace('{workDir}', workDir).replace('{fakePlatform}', fakePath)
: a));
} }
return { scriptPath, args }; return { scriptPath, args };
@@ -837,9 +851,11 @@ async function runCaseAsync(testCase, opts) {
// writeFile step — записать произвольный файл в workDir перед запуском скрипта // writeFile step — записать произвольный файл в workDir перед запуском скрипта
if (step.writeFile) { if (step.writeFile) {
const wfPath = join(workDir, step.writeFile.path); const wfPath = join(workDir, step.writeFile.path);
// Плейсхолдеры подставляются и здесь. В объектной форме — ДО JSON.stringify: иначе
// обратные слэши windows-пути попали бы в готовый JSON неэкранированными.
const wfContent = typeof step.writeFile.content === 'string' const wfContent = typeof step.writeFile.content === 'string'
? step.writeFile.content ? substPlaceholders(step.writeFile.content, workDir)
: JSON.stringify(step.writeFile.content, null, 2); : JSON.stringify(substDeep(step.writeFile.content, workDir), null, 2);
mkdirSync(dirname(wfPath), { recursive: true }); mkdirSync(dirname(wfPath), { recursive: true });
writeFileSync(wfPath, wfContent, 'utf8'); writeFileSync(wfPath, wfContent, 'utf8');
// Бит исполнения: на *nix навык запускает платформу через exec, и фейк без +x // Бит исполнения: на *nix навык запускает платформу через exec, и фейк без +x