Справочник CLI
В merql входит CLI для создания снимков, вычисления различий и выполнения слияний прямо из терминала. Composer устанавливает его как vendor/bin/merql; в клоне репозитория merql это bin/merql.
vendor/bin/merql работает и при установке как зависимости, поскольку merql 0.4.1. В предыдущих выпусках автозагрузчик Composer искался только в каталоге vendor/ самого пакета, из-за чего merql не работал при установке как зависимость.
Быстрый старт
# Capture a baseline from your database.
export MERQL_DB_DSN="sqlite:/path/to/db.sqlite"
vendor/bin/merql snapshot base
# Make some changes, then capture again.
vendor/bin/merql snapshot current
# See what changed.
vendor/bin/merql diff base current
Для слияния трёх ветвей нужны снимки ours и theirs из двух баз данных, разошедшихся относительно base. Укажите для каждого снимка соответствующую базу данных в MERQL_DB_DSN:
# Base: live before the sandbox was copied from it.
MERQL_DB_DSN="sqlite:/data/live.sqlite" vendor/bin/merql snapshot base
# ... copy live.sqlite to sandbox.sqlite, then both databases change ...
MERQL_DB_DSN="sqlite:/data/sandbox.sqlite" vendor/bin/merql snapshot ours
MERQL_DB_DSN="sqlite:/data/live.sqlite" vendor/bin/merql snapshot theirs
# Three-way merge with dry-run preview.
vendor/bin/merql merge base ours theirs --dry-run
Последовательное создание всех трёх снимков из одной базы данных не подходит для слияния: снимок theirs уже будет содержать изменения ours, поэтому каждая добавленная ours строка будет отмечена как конфликт insert_insert.
Переменные среды
CLI читает сведения о подключении к базе данных из переменных среды. Подключиться можно с помощью строки DSN PDO или отдельных параметров MySQL.
Подключение через DSN
Используйте MERQL_DB_DSN для подключений через PDO. Это рекомендуемый способ для SQLite и нестандартных конфигураций. DSN должен указывать на базу данных MySQL или SQLite: CLI не умеет регистрировать драйверы для других движков.
| Переменная | Описание | Пример |
|---|---|---|
MERQL_DB_DSN |
Полная строка DSN PDO | sqlite:/path/to/db.sqlite |
MERQL_DB_USER |
Имя пользователя (необязательно при использовании DSN) | root |
MERQL_DB_PASS |
Пароль (необязательно при использовании DSN) | secret |
# SQLite file.
export MERQL_DB_DSN="sqlite:/var/data/myapp.sqlite"
# MySQL via DSN.
export MERQL_DB_DSN="mysql:host=127.0.0.1;dbname=mydb;charset=utf8mb4"
export MERQL_DB_USER="root"
export MERQL_DB_PASS="secret"
Используйте базу данных SQLite, хранящуюся в файле. Каждая команда CLI запускается в отдельном процессе, поэтому sqlite::memory: всегда открывает новую пустую базу данных, и её снимок не содержит таблиц.
Сокращённая запись MySQL
Если MERQL_DB_DSN не задана, CLI использует переменные, специфичные для MySQL.
| Переменная | Значение по умолчанию | Описание |
|---|---|---|
MERQL_DB_NAME |
(обязательно) | Имя базы данных |
MERQL_DB_HOST |
127.0.0.1 |
Хост MySQL |
MERQL_DB_PORT |
3306 |
Порт MySQL |
MERQL_DB_USER |
root |
Имя пользователя MySQL |
MERQL_DB_PASS |
(пусто) | Пароль MySQL |
MERQL_DB_ADAPTER |
pdo |
Установите значение mysqli, чтобы использовать адаптер mysqli |
export MERQL_DB_NAME="wordpress"
export MERQL_DB_HOST="127.0.0.1"
export MERQL_DB_PORT="3306"
export MERQL_DB_USER="root"
export MERQL_DB_PASS="password"
Команды
merql snapshot <name>
Сохраните текущее состояние базы данных, имя которой задано переменными среды, в виде именованного снимка. Это единственная команда, которая подключается к базе данных.
vendor/bin/merql snapshot baseline
Вывод:
Snapshot 'baseline' saved
Tables: posts, comments, users, settings
Снимки по умолчанию сохраняются в виде файлов JSON в каталоге .merql/snapshots/ внутри рабочей директории (см. раздел Хранение снимков). Имя может содержать только буквенно-цифровые символы, дефисы и подчёркивания.
Обычный рабочий процесс: создайте снимок до внесения изменений, а затем ещё один после. Эти два снимка служат основой для сравнения или слияния.
merql diff <base> <current>
Сравните два именованных снимка и выведите сводку различий.
vendor/bin/merql diff baseline current
Вывод:
Changeset: baseline -> current
Inserts: 3
Updates: 7
Deletes: 1
Оба снимка должны уже существовать (быть созданы с помощью merql snapshot). Для сравнения не требуется подключение к базе данных, поскольку оно работает с сохранёнными файлами снимков.
merql merge <base> <ours> <theirs>
Выполните слияние трёх именованных снимков.
vendor/bin/merql merge base ours theirs
Вывод:
Merge: base + ours + theirs
Operations: 12
Conflicts: 0
Clean: yes
Все три снимка должны уже существовать. Для слияния не требуется подключение к базе данных, поскольку оно работает с сохранёнными файлами снимков и никогда не записывает данные в базу: у CLI нет команды применения. Используйте PHP API, чтобы применить результат слияния.
CLI выполняет слияние на уровне столбцов. Он не объединяет отдельные ячейки в столбцах TEXT или JSON, поэтому два разных изменения одного столбца всегда считаются конфликтом (#7). Для слияния на уровне ячеек используйте ThreeWayMerge с CellMergeConfig в PHP.
--dry-run
Добавьте флаг --dry-run, чтобы просмотреть инструкции SQL, которые сгенерировало бы слияние, не выполняя их. Инструкции описывают преобразование базового состояния в итоговое и включают изменения обеих сторон.
vendor/bin/merql merge base ours theirs --dry-run
Вывод:
Merge: base + ours + theirs
Operations: 3
Conflicts: 0
Clean: yes
Dry run SQL:
INSERT INTO `posts` (`id`, `title`, `status`) VALUES ('10', 'New Post', 'draft');
UPDATE `posts` SET `title` = 'Updated Title' WHERE `id` = '5';
DELETE FROM `comments` WHERE `id` = '3';
Команды разработки
В клоне репозитория merql есть дополнительные скрипты в bin/ для набора тестов с оракулом. Они не входят в пакет Composer, поэтому при установке как зависимости доступны только vendor/bin/merql. Запускайте их из корня репозитория после composer install.
| Команда | Описание |
|---|---|
./bin/oracle <name> |
Вычислить ожидаемый результат слияния для сценария |
./bin/actual <name> |
Запустить merql для сценария и сохранить вывод |
./bin/compare <name> |
Сравнить вывод оракула с фактическим |
./bin/test-scenario <name> |
Полный конвейер: настройка, оракул, фактический результат, сравнение |
./bin/test-regression |
Запустить все сценарии |
./bin/test-regression --category clean |
Запустить одну категорию: clean, conflict, identity, types, scale или edge |
./bin/test-regression --fast |
Только результат: пройдено или нет, без отчётов |
./bin/verify-compliance |
Полный отчёт о соответствии |
./bin/verify-all |
PHPStan + стиль кода + PHPUnit + регрессионные тесты оракула |
bin/test-regression также принимает --jobs, но пока игнорирует его значение и запускает сценарии по очереди (#5). Если указать неизвестное значение --category, выводится No scenarios found, а выполнение завершается успешно.
См. Стратегия тестирования, чтобы узнать структуру сценариев.
Код завершения
Команды merql snapshot, diff и merge завершаются с кодом 1, если отсутствует аргумент; для команды snapshot это также происходит, если подключение не настроено. При отсутствии снимка команда завершается из-за необработанного исключения SnapshotException с ненулевым кодом. Неизвестная команда выводит Unknown command, но пока завершается с кодом 0 (#3).
Хранение снимков
Снимки хранятся в .merql/snapshots/ относительно рабочей директории. Каждый снимок представляет собой отдельный файл JSON с именем <name>.json. Запускайте все команды из одной директории, чтобы они находили снимки друг друга.
У CLI нет параметра или переменной среды для указания другого расположения (#8). Чтобы использовать другую директорию, перейдите в неё перед запуском. В PHP укажите директорию перед созданием или загрузкой снимков:
use Merql\Snapshot\SnapshotStore;
SnapshotStore::setDirectory('/var/data/merql-snapshots');
Файлы снимков переносимы. Их можно копировать между компьютерами, добавлять в систему контроля версий или передавать для совместной отладки. Снимок, созданный с помощью CLI, можно загрузить в PHP с помощью SnapshotStore::load() и наоборот, если обе программы используют одну директорию.