mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-09-20 00:45:54 +03:00
feat(epf-build): исходники проверяются платформой до сборки
Сборка .epf/.erf не компилирует модули, поэтому сломанный BSL уезжал пользователю и падал при открытии обработки. Прямой команды «проверь внешнюю обработку» у платформы нет, но объект конфигурации она проверяет: обработка кладётся в конфигурацию временной базы (stub-db-create -EmbedSourceFile) и спрашивается /CheckConfig. При находках сборка отменяется, в выводе — сообщение платформы и путь к файлу исходника. Ключи -Checks и -Context; выключение -Checks off или externalCheck: false в .v8-project.json. С выключенной проверкой поведение прежнее. У копии объекта перевыпускаются все GUID: с идентификаторами исходника платформа путает копию в базе с загружаемой внешней обработкой и через раз отвечает «Исключение XDTO при чтении файла» на исправном исходнике. Ручная матрица (база есть/нет × ps1/py × исправный/битый × с модулями/без) вскрыла ещё три вещи: отказ платформы принять исходники при подготовке проверки выдавался за сбой базы; py-порт стаба терял причину отказа LoadConfigFromFiles (не было /Out, в PS он есть); копии общих утилит в stub-db-create.py разошлись с эталоном db-create — у run_v8 не было POSIX-ветки, из-за чего на darwin/Linux временная база с пробелом в пути молча не находилась бы. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013MQkqXxErBepYmoUycfkbn
This commit is contained in:
co-authored by
Claude Opus 5
parent
a3ea0b7be6
commit
448f05ed11
@@ -1,4 +1,4 @@
|
||||
# stub-db-create v1.8 — Create temp 1C infobase with metadata stubs for EPF/ERF build
|
||||
# stub-db-create v1.9 — Create temp 1C infobase with metadata stubs for EPF/ERF build
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
@@ -9,6 +9,10 @@ param(
|
||||
|
||||
[string]$TempBasePath,
|
||||
|
||||
# XML проверяемой обработки/отчёта: объект кладётся в конфигурацию-заглушку, чтобы платформа
|
||||
# смогла проверить его штатными проверками. Без параметра стаб работает как раньше.
|
||||
[string]$EmbedSourceFile,
|
||||
|
||||
[string[]]$AdditionalV8Arguments = @(),
|
||||
|
||||
[string[]]$AdditionalIbcmdArguments = @()
|
||||
@@ -350,6 +354,9 @@ foreach ($f in $xmlFiles) {
|
||||
}
|
||||
|
||||
$hasRefTypes = $typeMap.Count -gt 0
|
||||
# Конфигурация нужна и тогда, когда ссылочных типов нет: в неё кладётся сам объект.
|
||||
$embedRequested = -not [string]::IsNullOrWhiteSpace($EmbedSourceFile)
|
||||
$needCfg = $hasRefTypes -or $embedRequested
|
||||
|
||||
# --- 2. Determine TempBasePath ---
|
||||
if (-not $TempBasePath) {
|
||||
@@ -370,13 +377,106 @@ if ($needsRegistrator) {
|
||||
$typeMap["Document"]["ЗаглушкаРегистратора"] = $true
|
||||
}
|
||||
|
||||
# --- Внедрение проверяемого объекта в конфигурацию-заглушку ---
|
||||
# Платформа не умеет проверять внешнюю обработку: /LoadExternalDataProcessorOrReportFromFiles
|
||||
# только упаковывает XML и модули не компилирует. Зато она проверяет объект КОНФИГУРАЦИИ, а
|
||||
# внешняя обработка отличается от него немногим (замер 8.3.24): корневым тегом, именем
|
||||
# порождаемого объектного типа и отсутствием типа менеджера. Правим ровно эти точки и переносим
|
||||
# остальное как есть — под проверку попадает всё, что написал автор, включая реквизиты, формы и
|
||||
# макеты, а формат может расти без правок здесь.
|
||||
#
|
||||
# Подстановка типа делается ТОЛЬКО в .xml (это DefaultForm и основной реквизит формы); в .bsl
|
||||
# такой же текст был бы кодом, и трогать его нельзя.
|
||||
function Add-SourceObjectToConfig {
|
||||
param([string]$SourceXml, [string]$CfgDir)
|
||||
|
||||
# Копия объекта живёт в конфигурации базы, а следом в ту же базу грузится исходник как ВНЕШНЯЯ
|
||||
# обработка. С одинаковыми идентификаторами платформа путает их и через раз отвечает «Исключение
|
||||
# XDTO при чтении файла» на исправном исходнике — поэтому у копии все GUID свои, но согласованные
|
||||
# между её файлами (ссылки внутри объекта идут по идентификатору).
|
||||
$guidMap = @{}
|
||||
$reGuid = [regex]'[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}'
|
||||
$reissue = {
|
||||
param($m)
|
||||
$k = $m.Value.ToLower()
|
||||
if (-not $guidMap.ContainsKey($k)) { $guidMap[$k] = [guid]::NewGuid().ToString() }
|
||||
$guidMap[$k]
|
||||
}
|
||||
|
||||
$text = [IO.File]::ReadAllText($SourceXml, [Text.Encoding]::UTF8)
|
||||
if ($text -match '<ExternalDataProcessor[\s>]') {
|
||||
$extTag = 'ExternalDataProcessor'; $cfgTag = 'DataProcessor'; $folder = 'DataProcessors'
|
||||
} elseif ($text -match '<ExternalReport[\s>]') {
|
||||
$extTag = 'ExternalReport'; $cfgTag = 'Report'; $folder = 'Reports'
|
||||
} else {
|
||||
return $null
|
||||
}
|
||||
|
||||
$name = if ($text -match '<Name>([^<]+)</Name>') { $Matches[1] } else { [IO.Path]::GetFileNameWithoutExtension($SourceXml) }
|
||||
|
||||
$conv = $reGuid.Replace($text, $reissue)
|
||||
$conv = $conv.Replace("<$extTag ", "<$cfgTag ").Replace("<$extTag>", "<$cfgTag>").Replace("</$extTag>", "</$cfgTag>")
|
||||
$conv = $conv.Replace("${extTag}Object.", "${cfgTag}Object.").Replace("$extTag.", "$cfgTag.")
|
||||
|
||||
# Тип менеджера у внешней обработки не объявлен, а объекту конфигурации он обязателен:
|
||||
# без него платформа отвечает «отсутствует один или более типов объекта».
|
||||
$mgr = "`t`t`t<xr:GeneratedType name=`"${cfgTag}Manager.$name`" category=`"Manager`">`r`n" +
|
||||
"`t`t`t`t<xr:TypeId>$([guid]::NewGuid().ToString())</xr:TypeId>`r`n" +
|
||||
"`t`t`t`t<xr:ValueId>$([guid]::NewGuid().ToString())</xr:ValueId>`r`n" +
|
||||
"`t`t`t</xr:GeneratedType>`r`n"
|
||||
if ($conv -match '</InternalInfo>') {
|
||||
$conv = [regex]::Replace($conv, '(\s*)</InternalInfo>', ("`r`n" + $mgr + "`t`t</InternalInfo>"), 1)
|
||||
} else {
|
||||
$objType = "`t`t`t<xr:GeneratedType name=`"${cfgTag}Object.$name`" category=`"Object`">`r`n" +
|
||||
"`t`t`t`t<xr:TypeId>$([guid]::NewGuid().ToString())</xr:TypeId>`r`n" +
|
||||
"`t`t`t`t<xr:ValueId>$([guid]::NewGuid().ToString())</xr:ValueId>`r`n" +
|
||||
"`t`t`t</xr:GeneratedType>`r`n"
|
||||
$conv = [regex]::Replace($conv, "(<$cfgTag[^>]*>)", ("`$1`r`n`t`t<InternalInfo>`r`n" + $objType + $mgr + "`t`t</InternalInfo>"), 1)
|
||||
}
|
||||
|
||||
$objDir = Join-Path $CfgDir $folder
|
||||
New-Item -ItemType Directory -Path $objDir -Force | Out-Null
|
||||
$encBom = New-Object System.Text.UTF8Encoding($true)
|
||||
[IO.File]::WriteAllText((Join-Path $objDir "$name.xml"), $conv, $encBom)
|
||||
|
||||
# Содержимое объекта — как есть; в XML та же подстановка типа, .bsl копируются байт в байт.
|
||||
$srcContent = Join-Path (Split-Path $SourceXml -Parent) $name
|
||||
if (Test-Path $srcContent) {
|
||||
$dstContent = Join-Path $objDir $name
|
||||
foreach ($f in (Get-ChildItem -Path $srcContent -Recurse -File)) {
|
||||
$rel = $f.FullName.Substring($srcContent.Length).TrimStart('\', '/')
|
||||
$dst = Join-Path $dstContent $rel
|
||||
New-Item -ItemType Directory -Path (Split-Path $dst -Parent) -Force | Out-Null
|
||||
if ($f.Extension -ieq '.xml') {
|
||||
$t = [IO.File]::ReadAllText($f.FullName, [Text.Encoding]::UTF8)
|
||||
$t = $reGuid.Replace($t, $reissue)
|
||||
$t = $t.Replace("${extTag}Object.", "${cfgTag}Object.").Replace("$extTag.", "$cfgTag.")
|
||||
[IO.File]::WriteAllText($dst, $t, $encBom)
|
||||
} else {
|
||||
Copy-Item -Path $f.FullName -Destination $dst -Force
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return @{ Tag = $cfgTag; Name = $name }
|
||||
}
|
||||
|
||||
# --- 4. Generate configuration XML ---
|
||||
|
||||
if ($hasRefTypes) {
|
||||
if ($needCfg) {
|
||||
$enc = New-Object System.Text.UTF8Encoding($true)
|
||||
$cfgDir = Join-Path $TempBasePath "cfg"
|
||||
New-Item -ItemType Directory -Path $cfgDir -Force | Out-Null
|
||||
|
||||
$embedded = $null
|
||||
if ($embedRequested) {
|
||||
$embedded = Add-SourceObjectToConfig $EmbedSourceFile $cfgDir
|
||||
if (-not $embedded) {
|
||||
Write-Host "Error: $EmbedSourceFile is neither ExternalDataProcessor nor ExternalReport" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
# Заглушке нужна САМАЯ НИЗКАЯ работающая версия, а не версия исходников: ограничение платформы
|
||||
# одностороннее — она читает формат не новее себя. Отсюда min(версия исходников, 2.17): на 2.17+
|
||||
# заглушка остаётся 2.17 (как было), а под исходники 2.13-2.16 опускается до их версии, иначе
|
||||
@@ -566,6 +666,7 @@ if ($hasRefTypes) {
|
||||
$childXml += "`r`n`t`t`t<$tag>$name</$tag>"
|
||||
}
|
||||
}
|
||||
if ($embedded) { $childXml += "`r`n`t`t`t<$($embedded.Tag)>$($embedded.Name)</$($embedded.Tag)>" }
|
||||
|
||||
$cfgXml = @"
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
@@ -1548,7 +1649,7 @@ if ($stubEngine -eq "ibcmd") {
|
||||
$ibData = Join-Path $env:TEMP "stub_data_$(Get-Random)"
|
||||
New-Item -ItemType Directory -Path $ibData -Force | Out-Null
|
||||
$ibArgs = @("infobase", "create", "--db-path=$TempBasePath", "--create-database")
|
||||
if ($hasRefTypes) { $ibArgs += "--import=$(Join-Path $TempBasePath 'cfg')", "--apply", "--force" }
|
||||
if ($needCfg) { $ibArgs += "--import=$(Join-Path $TempBasePath 'cfg')", "--apply", "--force" }
|
||||
$ibArgs += "--data=$ibData"
|
||||
$ibArgs += $extraArgs
|
||||
$__ib = Invoke-PlatformProcess $V8Path $ibArgs
|
||||
@@ -1560,7 +1661,7 @@ if ($stubEngine -eq "ibcmd") {
|
||||
Write-Error "Failed to create stub infobase (code: $ibRc)"
|
||||
exit 1
|
||||
}
|
||||
if ($hasRefTypes) { Remove-Item -Path (Join-Path $TempBasePath "cfg") -Recurse -Force -ErrorAction SilentlyContinue }
|
||||
if ($needCfg) { Remove-Item -Path (Join-Path $TempBasePath "cfg") -Recurse -Force -ErrorAction SilentlyContinue }
|
||||
Write-Host "[OK] Stub database created: $TempBasePath"
|
||||
Write-Host $TempBasePath
|
||||
exit 0
|
||||
@@ -1576,8 +1677,8 @@ if ($proc.ExitCode -ne 0) {
|
||||
exit 1
|
||||
}
|
||||
|
||||
# --- 6. Load config and update DB if ref types exist ---
|
||||
if ($hasRefTypes) {
|
||||
# --- 6. Load config and update DB if there is one ---
|
||||
if ($needCfg) {
|
||||
$cfgDir = Join-Path $TempBasePath "cfg"
|
||||
# LoadConfigFromFiles
|
||||
Write-Host "Loading configuration from files..."
|
||||
|
||||
Reference in New Issue
Block a user