Перейти к содержимому

Справочник 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 укажите директорию перед созданием или загрузкой снимков:

PHP
use Merql\Snapshot\SnapshotStore;

SnapshotStore::setDirectory('/var/data/merql-snapshots');

Файлы снимков переносимы. Их можно копировать между компьютерами, добавлять в систему контроля версий или передавать для совместной отладки. Снимок, созданный с помощью CLI, можно загрузить в PHP с помощью SnapshotStore::load() и наоборот, если обе программы используют одну директорию.