CLI リファレンス
merqlには、スナップショットの取得、差分の計算、マージの実行をターミナルから直接行うためのCLIが付属しています。Composerでインストールするとvendor/bin/merqlとして使え、merqlリポジトリのチェックアウトではbin/merqlです。
vendor/bin/merqlは、merql 0.4.1以降では依存パッケージとしてのインストールからも実行できます。それ以前のリリースでは、パッケージ自身のvendor/ディレクトリ内でしかComposerオートローダーを探さなかったため、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
3方向マージでは、baseから分岐した2つのデータベースからoursとtheirsを取得する必要があります。各スナップショットで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
3つのスナップショットをすべて同じデータベースから順番に取得しても、マージには使えません。theirsにはすでにoursの変更が含まれるため、oursが挿入した行はすべてinsert_insert競合として報告されます。
環境変数
CLIは環境変数からデータベース接続情報を読み取ります。PDO DSN文字列または個別のMySQLパラメーターを使って接続できます。
DSNによる接続
PDOを使った接続にはMERQL_DB_DSNを使用します。SQLiteや標準外の構成ではこの方法が推奨されます。DSNではMySQLまたはSQLiteデータベースを指定する必要があります。CLIには他のエンジン用ドライバーを登録する方法がないためです。
| 変数 | 説明 | 例 |
|---|---|---|
MERQL_DB_DSN |
完全なPDO DSN文字列 | 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
スナップショットは、作業ディレクトリ配下の.merql/snapshots/にJSONファイルとして保存されます(スナップショットの保存を参照)。名前に使用できるのは英数字、ハイフン、アンダースコアのみです。
一般的な手順は、変更前にスナップショットを取得し、変更後にもう一度取得することです。この2つのスナップショットを差分計算やマージの基礎として使います。
merql diff <base> <current>
名前を指定した2つのスナップショットを比較し、差分の概要を表示します。
vendor/bin/merql diff baseline current
出力:
Changeset: baseline -> current
Inserts: 3
Updates: 7
Deletes: 1
両方のスナップショットがすでに存在している必要があります(merql snapshotで事前に取得)。差分計算は保存済みのスナップショットファイルを使うため、データベース接続は不要です。
merql merge <base> <ours> <theirs>
名前を指定した3つのスナップショットを3方向マージします。
vendor/bin/merql merge base ours theirs
出力:
Merge: base + ours + theirs
Operations: 12
Conflicts: 0
Clean: yes
3つのスナップショットがすべてすでに存在している必要があります。マージでは保存済みのスナップショットファイルを使うため、データベース接続は不要です。また、データベースへの書き込みは行いません。CLIには適用コマンドがありません。マージ結果を適用するにはPHPAPIを使ってください。
CLIは列単位でマージします。TEXT列やJSON列にはセル単位のマージを適用しないため、同じ列に対する異なる編集は常に競合になります(#7)。セル単位でマージするには、PHP内のCellMergeConfigを使ってThreeWayMergeを実行してください。
--dry-run
--dry-runフラグを追加すると、何も実行せずに、マージで生成されるSQL文をプレビューできます。各文はbaseの状態をマージ結果にする方法を示すため、両側の変更が含まれます。
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 を出力して正常終了します。
シナリオの構成については、Testing Strategyを参照してください。
終了ステータス
引数が不足している場合、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() を使って読み込めます。その逆も可能です。