Выгрузка и загрузка приложений

Инструмент tools/tma_app_archive.py выгружает приложение TMA в детерминированный ZIP-архив с небольшими текстовыми файлами. Архив удобно хранить в Git, индексировать и передавать агентам для анализа и изменения.

Скачать tma_app_archive.py

Скрипт умеет выгружать целое приложение или выбранные модули. Обратная операция создаёт обычный XML-файл обновления. Сам скрипт ничего не записывает в рабочую базу: итоговый XML загружается штатной командой платформы.

Что потребуется

  • Python 3.9 или новее;
  • для работы непосредственно с БД — клиентская библиотека MariaDB/MySQL;
  • сетевой доступ к MySQL и учётная запись с правом чтения таблицы __easycontrol.

Сохраните скачанный файл в рабочий каталог и проверьте запуск:

python3 tma_app_archive.py --help

На Windows вместо python3 обычно используется команда py:

py .\tma_app_archive.py --help

Если библиотека MySQL не находится автоматически, укажите полный путь:

$env:TMA_MYSQL_CLIENT_LIB = "C:\Program Files\MariaDB\MariaDB Connector C 64-bit\lib\libmariadb.dll"

Быстрый сценарий: всё приложение

Задайте подключение, не помещая пароль в историю команд:

export TMA_DB_HOST=db.example.local
export TMA_DB_USER=tma_export
export TMA_DB_PASSWORD='change_me'

В PowerShell те же параметры задаются так:

$env:TMA_DB_HOST = "db.example.local"
$env:TMA_DB_USER = "tma_export"
$env:TMA_DB_PASSWORD = "change_me"

Выгрузите приложение из БД:

python3 tma_app_archive.py export-db \
  --database suvr_new \
  --output suvr_new.tma-source.zip

Распакуйте архив, измените XML, Pascal или SQL-файлы и соберите полный файл обновления:

python3 tma_app_archive.py unpack \
  --input suvr_new.tma-source.zip \
  --output suvr_new-source

python3 tma_app_archive.py verify --input suvr_new-source

python3 tma_app_archive.py pack \
  --input suvr_new-source \
  --output suvr_new-update.xml

Загрузите suvr_new-update.xml в TMA от пользователя root командой Меню -> Загрузить обновление из файла.

Быстрый сценарий: отдельные модули

Параметр --module можно повторять. Он принимает точное внутреннее имя или glob-маску:

python3 tma_app_archive.py export-db \
  --database suvr_new \
  --module task \
  --module taskForm \
  --module taskReference \
  --output suvr_new-task.tma-source.zip

После изменений выборочный архив необходимо объединить с текущей полной версией приложения из БД:

python3 tma_app_archive.py unpack \
  --input suvr_new-task.tma-source.zip \
  --output suvr_new-task-source

python3 tma_app_archive.py verify --input suvr_new-task-source

python3 tma_app_archive.py pack-db \
  --database suvr_new \
  --input suvr_new-task-source \
  --output suvr_new-task-update.xml

Загрузите suvr_new-task-update.xml той же командой платформы: Меню -> Загрузить обновление из файла. pack-db читает актуальное приложение из БД, заменяет в нём выбранные модули и сохраняет полный XML; остальные модули и общие изображения остаются без изменений.

Состав архива

manifest.json
application.xml
modules/
  form/
    taskForm--<hash>/
      module.xml
      form.xml
      program.pas
  table/
    task--<hash>/
      module.xml
      triggers/
        before_insert.pas
        before_insert.sql
resources/
  images.xml
  • manifest.json содержит версию формата, перечень модулей и контрольные суммы.
  • application.xml содержит свойства приложения и ссылки на файлы модулей.
  • module.xml содержит полное XML-представление одного модуля.
  • form.xml, report.xml и menu.xml содержат визуальную конфигурацию.
  • program.pas содержит прикладной код модуля.
  • triggers/*.pas содержит исходный код триггеров платформы.
  • triggers/*.sql и control.sql содержат SQL-представление, если оно было сохранено платформой.
  • resources/images.xml содержит изображения приложения.

Все файлы внутри архива записываются в UTF-8. Собранный файл приложения записывается в Windows-1251, которую использует текущая Win32-сборка.

При выборочной выгрузке архив содержит только выбранные модули. Общий блок Images в такой архив не включается: существующие ссылки на изображения сохраняются за счёт слияния с актуальным полным приложением.

Выгрузка из базы

Подключение задаётся теми же переменными окружения, что и для headless-сервера:

export TMA_DB_HOST=db.example.local
export TMA_DB_USER=tma_export
export TMA_DB_PASSWORD='change_me'
export TMA_MYSQL_CLIENT_LIB=/path/to/libmariadb

python3 tma_app_archive.py export-db \
  --host db.example.local \
  --user tma_export \
  --database suvr_new \
  --output suvr_new.tma-source.zip

Параметры командной строки имеют приоритет над переменными окружения. --port необязателен, по умолчанию используется порт 3306. Для регулярной работы пароль лучше передавать через TMA_DB_PASSWORD, чтобы он не оставался в истории команд.

Можно выгрузить уже сохранённый XML или закодированный файл приложения:

python3 tma_app_archive.py export \
  --input application.xml \
  --output application.tma-source.zip

Выгрузка отдельных модулей

Параметр --module выбирает модуль по внутреннему имени. Его можно указывать несколько раз:

python3 tma_app_archive.py export-db \
  --host db.example.local \
  --user tma_export \
  --database suvr_new \
  --module task \
  --module taskForm \
  --module taskReference \
  --output suvr_new-task.tma-source.zip

Поддерживаются регистронезависимые glob-маски. Маску нужно заключать в кавычки, чтобы её не разворачивал shell:

python3 tma_app_archive.py export-db \
  --database suvr_new \
  --module 'task*' \
  --type Form \
  --output suvr_new-task-forms.tma-source.zip

Несколько --module объединяются по правилу «или», как и несколько --type. Если заданы и имена, и типы, модуль должен пройти оба фильтра. Типы соответствуют XML-атрибуту Module.Type, например Form, Table или Reference.

Работа с файлами

Архив распаковывается в пустой каталог:

python3 tma_app_archive.py unpack \
  --input suvr_new.tma-source.zip \
  --output suvr_new-source

После изменения файлов нужно проверить сборку:

python3 tma_app_archive.py verify --input suvr_new-source

Если одновременно изменены module.xml и выделенный из него файл program.pas, form.xml или файл триггера, выделенный файл имеет приоритет. Неизменённые файлы не переформатируются: пустой цикл export/pack сохраняет исходный XML байт-в-байт.

Обратная сборка

Полный архив можно собрать как из каталога, так и из неизменённого ZIP:

python3 tma_app_archive.py pack \
  --input suvr_new-source \
  --output suvr_new-agent-update.xml

Выборочный архив нельзя загружать в платформу напрямую: в нём намеренно нет остальных модулей. Перед загрузкой его нужно объединить с актуальным приложением из базы:

python3 tma_app_archive.py pack-db \
  --host db.example.local \
  --user tma_export \
  --database suvr_new \
  --input suvr_new-task.tma-source.zip \
  --output suvr_new-task-update.xml

pack-db только читает __easycontrol и создаёт полный XML-файл. Команда ничего не записывает в базу. Не выбранные модули, общие изображения и свойства приложения берутся из текущей версии в БД.

Если полный XML уже сохранён локально, вместо подключения к БД можно передать его как основу:

python3 tma_app_archive.py pack \
  --input suvr_new-task-source \
  --base suvr_new-current.xml \
  --output suvr_new-task-update.xml

Выборочная сборка сейчас обновляет существующие модули. Добавление совершенно нового модуля и новых общих изображений следует выполнять через полный архив.

Перед загрузкой следует сохранить резервную копию базы и просмотреть diff изменённых файлов. В платформе собранный XML загружается пользователем root через Меню -> Загрузить обновление из файла.

Загрузка выполняется существующим механизмом обновления приложения. Строки прикладных таблиц в архив не экспортируются и напрямую инструментом не изменяются.