fix(db-dump-xml): Changes без тихой полной перевыгрузки, инкремент в ibcmd

- -update без -force: при другой версии формата — отказ с подсказкой
  про -Mode Full, а не молчаливая перезапись всего дерева в новом формате.
- Первая выгрузка режимом по умолчанию: в каталог без выгрузки (пусто,
  только .git/README) — полностью; выгрузка без ConfigDumpInfo.xml — ошибка.
- ibcmd: Changes через --sync; Full в непустой каталог — через временный
  каталог и копирование поверх, как пишет конфигуратор; ошибка копирования
  даёт код 1. UpdateInfo с -AllExtensions отвергается, а не выгружает всё.
- py-порт печатает вывод ibcmd, как PS.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ANXwbMUhuRFSCsq2RgmTTm
This commit is contained in:
Nick Shirokov
2026-09-24 18:08:20 +03:00
co-authored by Claude Opus 5.5
parent ce7238792e
commit f98e7e9e81
12 changed files with 514 additions and 18 deletions
@@ -0,0 +1,23 @@
{
"name": "Changes в пустой каталог: первая выгрузка выполняется полностью",
"fakePlatform": {
"log": ""
},
"args_extra": [
"-V8Path",
"{fakePlatform}",
"-InfoBasePath",
"{workDir}/ib",
"-ConfigDir",
"{workDir}/out"
],
"expectError": true,
"expect": {
"stdoutContains": [
"[note] выгрузки в каталоге ещё нет — первая выгрузка выполняется полностью",
"Executing full configuration dump..."
],
"stdoutNotContains": "-update"
},
"noSnapshot": "проверяется, какие ключи ушли платформе; фейк файлов не выгружает, поэтому постусловие навыка справедливо даёт отказ"
}
@@ -0,0 +1,32 @@
{
"name": "Changes в каталог без выгрузки (только служебные файлы репозитория): первая выгрузка полная",
"fakePlatform": {
"log": ""
},
"preRun": [
{
"writeFile": {
"path": "out/.gitignore",
"content": "*.log\n"
}
}
],
"args_extra": [
"-V8Path",
"{fakePlatform}",
"-InfoBasePath",
"{workDir}/ib",
"-ConfigDir",
"{workDir}/out",
"-Mode",
"Changes"
],
"expect": {
"stdoutContains": [
"[note] выгрузки в каталоге ещё нет — первая выгрузка выполняется полностью",
"Executing full configuration dump..."
],
"stdoutNotContains": "-update"
},
"noSnapshot": "проверяется командная строка платформы; каталог выгрузки — фикстура кейса"
}
@@ -0,0 +1,32 @@
{
"name": "Changes по прошлой выгрузке: -update без -force",
"fakePlatform": {
"log": ""
},
"preRun": [
{
"writeFile": {
"path": "out/ConfigDumpInfo.xml",
"content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><ConfigDumpInfo format=\"Hierarchical\" version=\"2.17\"/>"
}
}
],
"args_extra": [
"-V8Path",
"{fakePlatform}",
"-InfoBasePath",
"{workDir}/ib",
"-ConfigDir",
"{workDir}/out",
"-Mode",
"Changes"
],
"expect": {
"stdoutContains": [
"Executing incremental configuration dump...",
"-update"
],
"stdoutNotContains": "-force"
},
"noSnapshot": "проверяется командная строка платформы; каталог выгрузки — фикстура кейса"
}
@@ -0,0 +1,32 @@
{
"name": "Ошибка: Changes в непустой каталог без ConfigDumpInfo.xml",
"fakePlatform": {
"log": ""
},
"preRun": [
{
"writeFile": {
"path": "out/Configuration.xml",
"content": "<?xml version=\"1.0\"?><MetaDataObject/>"
}
}
],
"args_extra": [
"-V8Path",
"{fakePlatform}",
"-InfoBasePath",
"{workDir}/ib",
"-ConfigDir",
"{workDir}/out",
"-Mode",
"Changes"
],
"expectError": true,
"expect": {
"stdoutContains": [
"no ConfigDumpInfo.xml",
"-Mode Full выгрузит конфигурацию целиком поверх каталога."
],
"stdoutNotContains": "Running:"
}
}
@@ -0,0 +1,42 @@
{
"name": "Ошибка: ibcmd не умеет UpdateInfo — и с -AllExtensions не подменяет его полной выгрузкой (fake platform)",
"preRun": [
{
"writeFile": {
"path": "ibcmd.cmd",
"content": "@echo off\r\necho ARGS: %*\r\nexit /b 0\r\n"
}
},
{
"writeFile": {
"path": "ib/1Cv8.1CD",
"content": "stub"
}
},
{
"writeFile": {
"path": "out/РасшА/ConfigDumpInfo.xml",
"content": "<ConfigDumpInfo/>"
}
}
],
"args_extra": [
"-V8Path",
"{workDir}\\ibcmd.cmd",
"-InfoBasePath",
"{workDir}\\ib",
"-UserName",
"Admin",
"-ConfigDir",
"{workDir}\\out",
"-Mode",
"UpdateInfo",
"-AllExtensions"
],
"expectError": true,
"expect": {
"stdoutContains": "ibcmd config export does not support Mode UpdateInfo",
"stdoutNotContains": "ARGS:"
},
"osOnly": "win32"
}
@@ -0,0 +1,32 @@
{
"name": "Отказ инкремента из-за версии формата: подсказка про полную перевыгрузку",
"fakePlatform": {
"log": "\ufeffОбновление XML выгрузки невозможно: версия формата платформы отличается от версии формата выгрузки.\r\nДля синхронизации необходимо выполнить полную выгрузку.\r\n",
"exit": 101
},
"preRun": [
{
"writeFile": {
"path": "out/ConfigDumpInfo.xml",
"content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><ConfigDumpInfo format=\"Hierarchical\" version=\"2.16\"/>"
}
}
],
"args_extra": [
"-V8Path",
"{fakePlatform}",
"-InfoBasePath",
"{workDir}/ib",
"-ConfigDir",
"{workDir}/out",
"-Mode",
"Changes"
],
"expectError": true,
"expect": {
"stdoutContains": [
"Error dumping configuration (code: 101)",
"[подсказка] Каталог выгружен в другой версии формата."
]
}
}
@@ -0,0 +1,44 @@
{
"name": "ibcmd: Changes — инкремент через --sync, без --force (fake platform)",
"preRun": [
{
"writeFile": {
"path": "ibcmd.cmd",
"content": "@echo off\r\necho ARGS: %*\r\nexit /b 0\r\n"
}
},
{
"writeFile": {
"path": "ib/1Cv8.1CD",
"content": "stub"
}
},
{
"writeFile": {
"path": "out/ConfigDumpInfo.xml",
"content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><ConfigDumpInfo format=\"Hierarchical\" version=\"2.17\"/>"
}
}
],
"args_extra": [
"-V8Path",
"{workDir}\\ibcmd.cmd",
"-InfoBasePath",
"{workDir}\\ib",
"-UserName",
"Admin",
"-ConfigDir",
"{workDir}\\out",
"-Mode",
"Changes"
],
"expect": {
"stdoutContains": [
"ARGS: infobase config export",
"--sync"
],
"stdoutNotContains": "--force"
},
"noSnapshot": "проверяется командная строка в stdout; каталог выгрузки — фикстура кейса",
"osOnly": "win32"
}
@@ -54,6 +54,17 @@ export const steps = [
script: 'db-dump-xml/scripts/db-dump-xml',
args: { '-V8Path': '{v8path}', '-InfoBasePath': '{workDir}/testdb', '-ConfigDir': '{workDir}/dumpA', '-Mode': 'Changes' },
},
// ── 3b. Changes into a FRESH dir → no ConfigDumpInfo yet, so the first dump must be full ──
{
name: 'db-dump-xml: Changes в пустой каталог (первая выгрузка)',
script: 'db-dump-xml/scripts/db-dump-xml',
args: { '-V8Path': '{v8path}', '-InfoBasePath': '{workDir}/testdb', '-ConfigDir': '{workDir}/dumpC', '-Mode': 'Changes' },
},
{
name: 'assert: первая выгрузка записала ConfigDumpInfo.xml',
assertContains: '{workDir}/dumpC/ConfigDumpInfo.xml',
expect: 'ConfigDumpInfo',
},
// ── 4. UpdateInfo into a FRESH dir → proves the mode alone yields non-empty output ──
{
name: 'db-dump-xml: UpdateInfo',
@@ -0,0 +1,101 @@
// platform-dump-sync.test.mjs — db-dump-xml Changes/Full поверх существующей выгрузки, оба движка.
// Changes должен быть инкрементом от ConfigDumpInfo.xml (1cv8 -update, ibcmd --sync), а Full в
// непустой каталог — писать поверх и не трогать лишнее, как конфигуратор (ibcmd сам в непустой
// каталог не выгружает). Изменение доставляется в базу загрузкой частями и проверяется маркером.
export const name = 'Выгрузка поверх существующей: Changes и Full (оба движка)';
export const setup = 'none';
export const requiresPlatform = true;
export const engines = ['1cv8', 'ibcmd'];
export const steps = [
// ── 1. Минимальная база ──
{
name: 'cf-init: пустая конфигурация',
script: 'cf-init/scripts/cf-init',
args: { '-Name': 'ВыгрузкаПоверх', '-OutputDir': '{workDir}/config' },
},
{
name: 'meta-compile: Справочник Товары',
script: 'meta-compile/scripts/meta-compile',
input: { type: 'Catalog', name: 'Товары', codeLength: 9, descriptionLength: 100 },
args: { '-JsonPath': '{inputFile}', '-OutputDir': '{workDir}/config' },
},
{
name: 'cf-edit: регистрация справочника',
script: 'cf-edit/scripts/cf-edit',
input: [{ operation: 'add-childObject', value: 'Catalog.Товары' }],
args: { '-ConfigPath': '{workDir}/config', '-DefinitionFile': '{inputFile}' },
},
{
name: 'db-create: файловая ИБ',
script: 'db-create/scripts/db-create',
args: { '-V8Path': '{v8path}', '-InfoBasePath': '{workDir}/testdb' },
},
{
name: 'db-load-xml: загрузка конфигурации (Full)',
script: 'db-load-xml/scripts/db-load-xml',
args: { '-V8Path': '{v8path}', '-InfoBasePath': '{workDir}/testdb', '-ConfigDir': '{workDir}/config' },
},
// ── 2. Первая выгрузка режимом по умолчанию (Changes) в несуществующий каталог → полная ──
{
name: 'db-dump-xml: первая выгрузка без -Mode',
script: 'db-dump-xml/scripts/db-dump-xml',
args: { '-V8Path': '{v8path}', '-InfoBasePath': '{workDir}/testdb', '-ConfigDir': '{workDir}/dump' },
},
{
name: 'assert: выгрузка содержит ConfigDumpInfo.xml',
assertContains: '{workDir}/dump/ConfigDumpInfo.xml',
expect: 'ConfigDumpInfo',
},
// ── 3. Изменение в базе → Changes поверх выгрузки ──
{
name: 'editFile: маркер в Comment справочника',
editFile: '{workDir}/config/Catalogs/Товары.xml',
replace: '<Comment/>',
with: '<Comment>syncMARK</Comment>',
},
{
name: 'db-load-xml: частичная загрузка Товары',
script: 'db-load-xml/scripts/db-load-xml',
args: {
'-V8Path': '{v8path}', '-InfoBasePath': '{workDir}/testdb',
'-ConfigDir': '{workDir}/config', '-Files': 'Catalogs/Товары.xml',
},
},
{
name: 'db-dump-xml: Changes поверх выгрузки',
script: 'db-dump-xml/scripts/db-dump-xml',
args: { '-V8Path': '{v8path}', '-InfoBasePath': '{workDir}/testdb', '-ConfigDir': '{workDir}/dump', '-Mode': 'Changes' },
},
{
name: 'assert: Changes выгрузил изменение',
assertContains: '{workDir}/dump/Catalogs/Товары.xml',
expect: 'syncMARK',
},
// ── 4. Full в непустой каталог: пишет поверх, лишнее остаётся ──
{
name: 'meta-compile: посторонний объект в каталоге выгрузки',
script: 'meta-compile/scripts/meta-compile',
input: { type: 'Catalog', name: 'Посторонний' },
args: { '-JsonPath': '{inputFile}', '-OutputDir': '{workDir}/dump' },
},
{
name: 'db-dump-xml: Full в непустой каталог',
script: 'db-dump-xml/scripts/db-dump-xml',
args: { '-V8Path': '{v8path}', '-InfoBasePath': '{workDir}/testdb', '-ConfigDir': '{workDir}/dump', '-Mode': 'Full' },
},
{
name: 'assert: Full выгрузил конфигурацию',
assertContains: '{workDir}/dump/Catalogs/Товары.xml',
expect: 'syncMARK',
},
{
name: 'assert: посторонний объект не удалён',
assertContains: '{workDir}/dump/Catalogs/Посторонний.xml',
expect: 'Посторонний',
},
];