applyPatch function
Applies an edit script ops to baseText (line-based).
Reconstructs text by taking lines from baseText for equal/delete and
from ops for insert. Validates that equal segments match baseText;
returns ApplyPatchConflict if they do not.
Implementation
ApplyPatchUtils applyPatch(String baseText, List<DiffOp> ops) {
final List<String> lines = _splitLines(baseText);
int lineIndex = 0;
final StringBuffer out = StringBuffer();
for (final DiffOp op in ops) {
final List<String> opLines = _opToLines(op.text);
switch (op.kind) {
case DiffOpKind.equal:
for (final String ln in opLines) {
if (lineIndex >= lines.length) {
return ApplyPatchConflict(
'Expected line "${ln.trimRight()}" but base has no more lines',
);
}
final String baseLine = lines[lineIndex];
if (baseLine != ln) {
return ApplyPatchConflict(
'Conflict at line ${lineIndex + 1}: expected "${ln.trimRight()}", got "${baseLine.trimRight()}"',
);
}
out.write(baseLine);
lineIndex++;
}
break;
case DiffOpKind.delete:
for (final String ln in opLines) {
if (lineIndex >= lines.length) {
return ApplyPatchConflict(
'Delete expected "${ln.trimRight()}" but base has no more lines',
);
}
final String baseLine = lines[lineIndex];
if (baseLine != ln) {
return ApplyPatchConflict(
'Conflict at line ${lineIndex + 1}: delete expected "${ln.trimRight()}", got "${baseLine.trimRight()}"',
);
}
lineIndex++;
}
break;
case DiffOpKind.insert:
for (final String ln in opLines) {
out.write(ln);
}
break;
}
}
if (lineIndex < lines.length) {
return ApplyPatchConflict('Base has ${lines.length - lineIndex} extra lines after patch');
}
return ApplyPatchSuccess(out.toString());
}