Исходники и база
Одна и та же конфигурация живёт в двух видах: в базе, где с ней работают, и в файлах, которые лежат под контролем версий. Эта страница о том, какие бывают исходники, что им соответствует в базе, в каких состояниях они бывают и какие команды переводят из одного состояния в другое.
- Какие бывают исходники
- Что лежит в базе
- Что чему соответствует
- Состояния и переходы
- Три памяти о прошлом разе
- Что делает раннер
Какие бывают исходники
Единица работы раннера — набор исходников: один каталог с одним предметом. Предметов три, форматов два, и любой предмет бывает в любом формате.
| предмет | XML платформы | проект EDT | пакет |
|---|---|---|---|
| конфигурация | каталог с Configuration.xml (15) | проект конфигурации (109) | .cf |
| расширение | тот же формат, объявлено расширением (32) | проект расширения, связан с проектом конфигурации (110) | .cfe |
| внешние обработки и отчёты | каталог с несколькими обработками | проект внешних отчётов и обработок (110) | .epf, .erf |
Пакет — четвёртый вид того же предмета: один файл, который платформа умеет применить к базе или разобрать обратно в файлы (30). Снимок всей базы в .dt к исходникам не относится: в нём данные.
Наборы объявлены в v8project.yaml. Тип набора раннер определяет по содержимому маркерных файлов: каталог можно назвать как угодно, тип задаёт Configuration.xml внутри. Структура объявления и примеры находятся на странице v8project.yaml.
У формата EDT две ступени. Проект правят в EDT, а с базой платформа обменивается только XML-выгрузкой (108). Экспорт проекта в XML раннер держит у себя как кеш: он не лежит под контролем версий и пересчитывается по изменившемуся.
Что лежит в базе
Информационная база держит несколько конфигураций сразу (1). Для каждого набора исходников в ней есть своя пара: то, что правят, и то, с чем работают пользователи (8).
| в базе | что это | кто пишет |
|---|---|---|
| основная конфигурация | то, что правят в Конфигураторе и куда загружают исходники | отправка, Конфигуратор |
| конфигурация базы данных | то, по чему построены таблицы и с чем работают сеансы; только для чтения (2) | только применение |
| конфигурации поставщика | эталоны типовых решений, есть у базы на поддержке (9); их может быть несколько, каждая с именем (8) | обновление поставщика |
| расширение и его база данных | та же пара на каждое установленное расширение (41) | отправка и применение с именем расширения |
Что чему соответствует
Команды ходят по этим стрелкам и ни по каким другим. Отправка и выгрузка работают с основной конфигурацией. До пользователей изменение доходит только после применения.
Шесть направлений между тремя видами одного предмета, и у каждого своя команда:
| откуда → куда | команда | нужна ли база |
|---|---|---|
| исходники → база | push | да |
| база → исходники | pull | да |
| пакет → база | upload | да |
| база → пакет | download | да |
| исходники → пакет | make | нет для конфигурации и внешних (30) |
| пакет → исходники | convert | нет (30) |
Расширение ходит по тем же стрелкам с указанием ссылки. Отдельных команд обмена для расширений нет: те же push и pull с именем. Свойства установленного экземпляра правит extensions.
Состояния и переходы
Исходники и основная конфигурация меняются независимо: файлы правят в редакторе, конфигурацию — в Конфигураторе. Отсюда четыре состояния снаружи базы и два способа вернуться к согласию.
Состояния выгрузки и основной конфигурации: каталог исходников против основной конфигурации базы.
Петля у «разошлись» — отказ по несовпадению предка. Раннер не выбирает, чья правка важнее: он возвращает к pull, а сводит расхождение система контроля версий.
До первого обмена состояния нет: раннер ещё не знает, как относятся друг к другу каталог и база. status так и говорит. Из этого положения pull идёт всегда, push — только в пустую базу; в непустую без памяти он отказывает и предлагает pull или push --force.
Внутри базы у каждой пары свои состояния. Сохранить изменение в основную конфигурацию и применить его к базе данных — два разных события (3, 6).
Состояния основной конфигурации и конфигурации базы данных: внутри самой базы.
«Есть непринятое» — штатное состояние: ради него разведены push --no-apply и apply, чтобы реструктуризацию можно было отложить до окна обслуживания. Обратный ход — reset: основная конфигурация возвращается к конфигурации базы данных, непринятое пропадает (7). «Обновлено динамически» означает, что новые сеансы получат новую конфигурацию, а работающие останутся на прежней до перезапуска.
Кроме содержимого у ссылки есть собственное состояние: существует ли она с обеих сторон.
| состояние ссылки | что это значит | чем переходят |
|---|---|---|
| есть с обеих сторон | обычная работа | push, pull |
| есть в проекте, нет в базе | расширение ещё не заведено | push my-ext заводит его сам (39) |
| есть в базе, нет в проекте | поставил кто-то другой или пришло с обновлением | pull my-ext после объявления набора исходников |
| выключено | установлено, но не действует | extensions set my-ext --active no |
| больше не нужно | уводит данные, которые добавляло (42) | push --delete my-ext |
Все три состояния называет одна команда. Без ключа она отвечает по памяти и платформу не запускает; с --deep спрашивает поколение и состав расширений, и тогда видно, что база ушла вперёд и что в ней есть непринятое:
$ v8-runner status --deep
origin: File="/srv/ib/demo"
main → ЖивоеИмяКонфигурации 3 файла изменено · есть непринятое
my-ext → РасширениеВБазе совпадает
patch-01 → Patch_01 база ушла вперёд — сперва pull
— → Patch_007 есть в базе, нет в проекте
Три памяти о прошлом разе
Целиком выгружать и загружать всегда верно и всегда долго. По изменившемуся — быстро, и для этого нужно знать, что изменилось. Знание складывается из трёх памятей: две ведёт раннер, одну платформа.
| память | отвечает на вопрос | кто ведёт | где лежит |
|---|---|---|---|
| хеши исходников | какие файлы я тронул | раннер считает сам | localPath, по файлу на набор |
| поколение базы | менялась ли база | платформа отвечает, раннер записывает (13) | localPath, с именем инструмента и операции |
файл версий ConfigDumpInfo.xml | что платформе выгружать заново | платформа (16) | localPath; в каталог исходников не попадает |
Хеши сравнивают каталог с прошлым разом и дают список файлов для частичной загрузки. Поколение сравнивается только на равенство: совпало — база с прошлого раза не менялась, и выгрузка отвечает «нечего делать» за секунду. Файл версий читает только платформа: по нему она решает, какие объекты перекладывать.
Все три описывают отношение между одним каталогом и одной базой. Поэтому под localPath они лежат по базе: у каждой объявленной базы своя память, и отправка в тестовую не сбивает память о рабочей. Без базы эту память не пересчитать, поэтому она лежит не в workPath: удаление workPath её не задевает. Место для этого в конфигурации уже есть: местный слой v8project.local.yaml задаёт localPath и базы по именам, из которых origin берётся без ключа, а наборы исходников и формат в нём запрещены.
.local/ # localPath
infobases/
origin/ # база по умолчанию
generation.json # поколение, чем получено, после какой операции
hashes/ # хеши исходников по наборам
dump-info/
main/
ConfigDumpInfo.xml # файл версий набора: у конфигурации и у каждого расширения свой
my-ext/
…
test/
…
Что делает раннер
Раннер берёт на себя ровно то, чего платформе знать неоткуда: какая база с каким каталогом связана и что в каталоге ваше.
Свой файл версий на пару
Файл версий ConfigDumpInfo.xml хранится только у раннера, в каталог исходников он не попадает. Выгрузка по изменившемуся идёт в пустой промежуточный каталог по копии раннера: платформа пишет туда изменённое и новую опись, раннер переносит в каталог всё, кроме описи, удаления — по двум описям, а новая опись становится его копией. Рядом с копией раннер помнит, какой каталог она описывает: каталог, созданный заново (новый клон), её не подтверждает. Загрузка опись не обновляет: копия отстаёт ровно на загруженное, и следующая выгрузка выгрузит это заново.
| файл версий | каталог | что делает раннер |
|---|---|---|
| копия своей пары | тот же | работает по изменившемуся |
| копии нет или она чужая | любой | выгрузка полная |
| копия своей пары | создан заново | выгрузка полная |
Выгрузить один файл версий, не трогая остального, платформа умеет (21), и раннер этого не делает: новый файл опишет базу такой, какая она сейчас, и заявит, что все её объекты уже лежат в каталоге. Следующая работа по изменившемуся пропустит настоящие изменения.
Проверка до выбора режима
Наличие копии и версия формата в ней читаются до запуска платформы. Копии нет — выгрузка полная, она же её создаст. Версия чужая — тоже полная. Для загрузки та же проверка работает в обратную сторону: формат новее платформы — отказ до запуска с обеими версиями (22).
Ответ описывает случившееся
Платформа может перейти на полную выгрузку сама, и узнать об этом заранее нельзя (18). Поэтому раннер не обещает быстро: ответ называет запрошенный режим и рядом — что вышло на самом деле, с причиной.
Токен хранится с именем инструмента
Рядом с поколением лежит то, чем оно получено. Сравниваются только значения от одного инструмента, чужое считается отсутствием ответа. Токен пустой базы, включая сорок нулей, сохраняется и сравнивается как любой другой токен этого инструмента.
Слить или заменить
Выгрузка из базы, где правили мимо исходников, должна встретиться с тем, что вы успели наработать. Выбор явный:
слить · pull | заменить · pull --force | |
|---|---|---|
| что происходит | выгрузка ложится поверх; чего в базе нет, остаётся на месте | каталог приводится ровно к базе, лишнее исчезает |
| когда нужно | базу правили мимо исходников, расхождение надо увидеть в системе контроля версий | каталог считается производным от базы и должен ей соответствовать |
| формат EDT | слияния нет ни в одном режиме: EDT сводит изменения интерактивно (109), поэтому выгрузка либо заменяет проект, либо отказывается | |
Слияние раннер выполняет чужими руками, и это выбор: выгрузка ложится в рабочий каталог обычным изменением, а сводит его система контроля версий, у которой есть история, трёхстороннее слияние и разметка конфликтов. Раннер отвечает за то, чтобы расхождение стало для неё видимым и безопасным.
Подтверждение разрушения
Разрушение — то, чего нельзя вернуть: правки без фиксации в системе контроля версий, файлы вне её учёта, весь каталог, если он под контролем не находится. Изменение зафиксированного файла сюда не относится: оно видно в разнице и откатывается одной командой.
| каталог чистый | терять нечего, команда идёт |
| есть незафиксированное | команда отказывается и называет, что именно потеряется |
| каталог не под контролем версий | потеряться может всё, отказ на тех же правах |
| попросили явно | идёт и перечисляет уничтоженное в ответе |
--dry-run показывает это заранее: перечисляет поимённо, что будет перезаписано и что удалено, ничего при этом не трогая.
Поколение до и после
Перед операцией с базой раннер спрашивает поколение и спрашивает его снова после. Если между ними базу правили, ответ называет это, а память о прошлом разе не обновляется: следующая команда снова увидит расхождение.