textmerge

package
v0.18.10 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 11, 2026 License: AGPL-3.0 Imports: 6 Imported by: 0

Documentation

Overview

Package textmerge is the line-based three-way merge shared by the sync engine (two devices' concurrent puts) and the hub (an outside write landing under a live co-editing room).

Hand-written, no dependency: the code that decides what a merged file contains should be readable in one sitting. Each side is diffed against the base with a Myers O(ND) line diff, so a side that touched several places in a file produces several small hunks rather than one span from its first change to its last. Hunks that do not touch the same base lines apply independently (diff3). Where both sides changed the same lines, three narrow cases still resolve without inventing text: an identical edit, two insertions at one point of a non-empty file (one already holding the other, or both kept in a content-defined order), and a single line both sides edited in different words. Everything else is a real conflict and stays one.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsText

func IsText(b []byte) bool

IsText reports whether b is something a line merge may touch: valid UTF-8 with no NUL. Merging bytes that are not lines produces a file that is neither side's, and for a binary format that means a corrupt one.

func Merge

func Merge(base, a, b []byte) ([]byte, bool)

Merge merges two edits of the same base. ok is false when the two sides changed the same region in different ways, which is a real conflict and stays one, or when any input is not text.

Determinism matters more than cleverness here: two devices can each observe the same concurrency and merge independently, so merge(base, a, b) and merge(base, b, a) must agree or the fleet diverges. Every rule below is symmetric in a and b; where an order has to be picked (two insertions at one point) it is picked by content, never by argument position.

func RetainsChanges added in v0.18.10

func RetainsChanges(base, candidate, head []byte) bool

RetainsChanges reports whether head still carries every line edit that took base to candidate, untouched: no later edit (candidate -> head) overlaps a span candidate inserted or rewrote, inserts inside such a span, or inserts where candidate deleted lines, and a final newline candidate changed is still the way candidate left it. It is deliberately strict — false means "cannot prove it is retained", never "it was reverted".

Types

type CharHunk added in v0.18.10

type CharHunk struct {
	Start, End int
	Insert     string
}

CharHunk is one edit turning old text into new: replace old[Start:End] with Insert. Offsets are UTF-16 code units into the OLD text, which is what Yjs counts in.

func DiffHunks added in v0.18.10

func DiffHunks(oldText, newText string) []CharHunk

DiffHunks is the minimal set of disjoint edits turning oldText into newText, ascending: a Myers line diff, each changed span then trimmed to the characters that actually differ. Applied from last to first, each edit's offsets stay valid. A splice made this way keeps every unchanged line as the same CRDT items instead of re-inserting the whole middle.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL