Cellaszintű egyesítés
Az oszlopszintű egyesítés észleli, ha mindkét oldal ugyanazt az oszlopot módosította. A cellaszintű egyesítés mélyebbre hatol, és az oszlopon belüli tartalmat egyesíti. Két ember különböző sorokat szerkeszthet egy TEXT mezőben, vagy különböző kulcsokat egy JSON objektumban, és a módosítások ütközésmentesen egyesíthetők.
use Merql\CellMerge\CellMergeConfig;
use Merql\Merge\ThreeWayMerge;
$config = CellMergeConfig::auto();
$merge = new ThreeWayMerge($config);
$result = $merge->merge($base, $ours, $theirs);
Cellaszintű egyesítés engedélyezése
A cellaszintű egyesítés választható. Csak olyan ThreeWayMerge esetén fut, amelyet CellMergeConfig értékkel hoztak létre. Enélkül minden olyan oszlop, amelyet mindkét oldal eltérő értékre módosított, update_update ütközésnek számít.
A Merql homlokzat nem fogad el konfigurációt: a Merql::merge(), Merql::patch() és Merql::plan() konfiguráció nélkül hozza létre a new ThreeWayMerge() példányát, a CLI merge parancsa pedig a Merql::merge() útján fut. Ezek mindig oszlopszinten egyesítenek (#7).
Ha a homlokzat vagy a CLI által mentett pillanatképeket cellaszintű egyesítéssel szeretné egyesíteni, töltse be őket, majd hívja meg saját maga a ThreeWayMerge műveletet. Az eredmény egy szokványos MergeResult, ezért a homlokzat továbbra is alkalmazhatja, a MergePlanBuilder pedig egyesítési tervvé alakítja:
use Merql\CellMerge\CellMergeConfig;
use Merql\Merge\ThreeWayMerge;
use Merql\Merql;
use Merql\Plan\MergePlanBuilder;
use Merql\Snapshot\SnapshotStore;
$base = SnapshotStore::load('base');
$ours = SnapshotStore::load('ours');
$theirs = SnapshotStore::load('theirs');
$result = (new ThreeWayMerge(CellMergeConfig::auto()))->merge($base, $ours, $theirs);
$plan = (new MergePlanBuilder())->build('plan-1', $base, $ours, $theirs, $result);
A cellaegyesítők csak azoknál az oszlopoknál futnak le, amelyeket mindkét oldal módosított. Ha csak az egyik oldal módosított egy oszlopot, az értéke változatlanul kerül át.
CellMergeConfig
A CellMergeConfig oszlopokat vagy oszloptípusokat rendel cellaegyesítő-megvalósításokhoz. A auto() gyár alapértelmezésként ésszerű beállításokat ad:
use Merql\CellMerge\CellMergeConfig;
use Merql\CellMerge\JsonCellMerger;
use Merql\CellMerge\TextCellMerger;
// Auto: column types containing "text" (TEXT, MEDIUMTEXT, LONGTEXT, ...) use
// TextCellMerger, column types containing "json" use JsonCellMerger.
$config = CellMergeConfig::auto();
// Custom: assign mergers to specific columns.
$config = (new CellMergeConfig())
->forColumn('posts.content', new TextCellMerger())
->forColumn('settings', new JsonCellMerger())
->forType('json', new JsonCellMerger());
Az egyesítő feloldásának prioritása:
- Minősített oszlopnév (
table.column). - Nem minősített oszlopnév (
column). - Oszloptípus szerinti illesztés (kis- és nagybetűket figyelmen kívül hagyó
str_contains). - Alapértelmezés:
OpaqueCellMerger(eltérő értékek esetén mindig ütközést jelez).
TextCellMerger
Többsoros szöveget egyesít a Myers-féle különbségvizsgálattal, ugyanazzal az algoritmussal, amelyet a git használ a fájltartalomhoz. Minden sor önálló egységnek számít, így a különböző sorok módosításai ütközésmentesen egyesíthetők.
use Merql\CellMerge\TextCellMerger;
$merger = new TextCellMerger();
Példa: ütközésmentes szövegegyesítés
Base: "line one\nline two\nline three"
Ours: "LINE ONE\nline two\nline three" // changed line 1
Theirs: "line one\nline two\nLINE THREE" // changed line 3
Különböző sorokat szerkesztettek. Az egyesítés eredménye "LINE ONE\nline two\nLINE THREE", ütközés nélkül.
Példa: szövegütközés
Base: "line one\nline two"
Ours: "changed by us\nline two" // changed line 1
Theirs: "changed by them\nline two" // also changed line 1
Mindkét oldal ugyanazt a sort módosította eltérő értékre. Az egyesítő ütközési eredményt ad vissza. Az egyesített tartalom a gitben használthoz hasonló ütközésjelölőket tartalmaz.
Működés
A TextCellMerger a pitmaster ThreeWayMerge::merge() megoldására bízza a feladatot, amely Myers-féle különbségvizsgálattal összehasonlítja a base állapotot mindkét oldallal, majd egyesíti a két módosítási listát. Ha a módosítások ugyanazon a sorszakaszon fedik egymást, ütközést jelez.
JsonCellMerger
JSON objektumokat egyesít úgy, hogy a legfelső szintű kulcsokat külön-külön hasonlítja össze. Minden kulcs egyesítése a szokásos háromutas szabályok szerint történik.
use Merql\CellMerge\JsonCellMerger;
$merger = new JsonCellMerger();
Példa: ütközésmentes JSON egyesítés
// Base
{"name": "Alice", "role": "editor", "active": true}
// Ours: changed "role"
{"name": "Alice", "role": "admin", "active": true}
// Theirs: changed "name"
{"name": "Bob", "role": "editor", "active": true}
A különböző kulcsok módosultak. Az egyesítés eredménye:
{"name": "Bob", "role": "admin", "active": true}
Példa: JSON ütközés
// Base
{"color": "red"}
// Ours
{"color": "blue"}
// Theirs
{"color": "green"}
Mindkét oldal ugyanazt az color kulcsot módosította, eltérő értékre. Ez ütközés. Az egyesítő alapértelmezés szerint az ours értékét választja, és egy ütközést jelez.
Kulcsszintű szabályok
| Base | Ours | Theirs | Eredmény |
|---|---|---|---|
| Kulcs változatlan | Kulcs változatlan | Az alap elfogadása | |
| Kulcs változatlan | Kulcs módosult | A theirs elfogadása | |
| Kulcs módosult | Kulcs változatlan | Az ours elfogadása | |
| Kulcs módosult (azonos) | Kulcs módosult (azonos) | Elfogadás (egyezés) | |
| Kulcs módosult (eltérő) | Kulcs módosult (eltérő) | Ütközés (alapértelmezés: ours) | |
| Kulcs létezik | Kulcs létezik | Kulcs eltávolítva | Az eltávolítás elfogadása |
| Kulcs létezik | Kulcs eltávolítva | Kulcs létezik | Az eltávolítás elfogadása |
| Kulcs hiányzik | Kulcs hozzáadva | Kulcs hiányzik | A hozzáadás elfogadása |
| Kulcs hiányzik | Kulcs hiányzik | Kulcs hozzáadva | A hozzáadás elfogadása |
A beágyazott objektumokat átlátszatlan JSON karakterláncként hasonlítja össze, rekurzió nélkül. Ha egy beágyazott objektum eltér, a teljes kulcsértéket hasonlítja össze, nem annak alkulcsait.
Követelmények
Mindhárom értéknek érvényes JSON objektumnak vagy tömbnek kell lennie. Ha bármelyik érték nem érvényes JSON, vagy JSON skalár (karakterlánc, szám, logikai érték), az egyesítő ütközésre vált.
OpaqueCellMerger
Az alapértelmezett egyesítő, ha nincs beállítva cellaszintű stratégia. Az oszlopértéket átlátszatlan adatként kezeli, és mindig ütközést jelez, ha a két oldal eltér.
use Merql\CellMerge\OpaqueCellMerger;
$merger = new OpaqueCellMerger();
$result = $merger->merge($base, $ours, $theirs);
// $result->clean is always false when $ours !== $theirs
CellMergeResult
Minden cellaegyesítő egy CellMergeResult értéket ad vissza:
$result = $merger->merge($base, $ours, $theirs);
$result->clean; // bool: true if merge resolved cleanly
$result->value; // mixed: the merged value (or ours on conflict)
$result->conflicts; // int: number of conflicts within the cell
Gyári metódusok:
CellMergeResult::resolved($value); // clean merge
CellMergeResult::conflict($oursValue, $n); // n conflicts, defaults to ours
Egyéni cellaegyesítők
Saját egyesítési stratégia hozzáadásához valósítsa meg a CellMerger interfészt:
use Merql\CellMerge\CellMerger;
use Merql\CellMerge\CellMergeResult;
class YamlCellMerger implements CellMerger
{
public function merge(mixed $base, mixed $ours, mixed $theirs): CellMergeResult
{
// Parse YAML, merge keys, return result.
$merged = $this->mergeYaml($base, $ours, $theirs);
if ($merged['clean']) {
return CellMergeResult::resolved($merged['value']);
}
return CellMergeResult::conflict($ours);
}
}
$config = (new CellMergeConfig())
->forColumn('config_data', new YamlCellMerger());