MCPcopy Create free account
hub / github.com/atomicdotdev/atomic / three_way_merge

Function three_way_merge

atomic-core/src/merge/three_way.rs:99–157  ·  view source on GitHub ↗

Perform a three-way merge of token sequences. `base` — the common ancestor's tokens `left` — one side's tokens `right` — the other side's tokens Returns [`ThreeWayResult::Merged`] when all edits are to different positions, or [`ThreeWayResult::Conflict`] when at least one token position was changed by both sides to different values.

(
    base: &[MergeToken],
    left: &[MergeToken],
    right: &[MergeToken],
)

Source from the content-addressed store, hash-verified

97/// positions, or [`ThreeWayResult::Conflict`] when at least one token
98/// position was changed by both sides to different values.
99pub fn three_way_merge(
100 base: &[MergeToken],
101 left: &[MergeToken],
102 right: &[MergeToken],
103) -> ThreeWayResult {
104 // Fast path: if left and right are identical, no conflict possible.
105 if left == right {
106 let content = reassemble_tokens(left);
107 return ThreeWayResult::Merged(content);
108 }
109
110 // Fast path: if left is unchanged, take right.
111 if left == base {
112 let content = reassemble_tokens(right);
113 return ThreeWayResult::Merged(content);
114 }
115
116 // Fast path: if right is unchanged, take left.
117 if right == base {
118 let content = reassemble_tokens(left);
119 return ThreeWayResult::Merged(content);
120 }
121
122 // --- General case: LCS-based alignment ---
123
124 let left_ops = diff_tokens(base, left);
125 let right_ops = diff_tokens(base, right);
126
127 // Collect base indices modified by each side.
128 let left_modified = modified_indices(&left_ops);
129 let right_modified = modified_indices(&right_ops);
130
131 // Check for overlapping modifications.
132 for idx in left_modified.intersection(&right_modified) {
133 // Both sides touched the same base index. This is only OK
134 // if they produced the *same* replacement.
135 let left_replacement = replacement_for(&left_ops, *idx);
136 let right_replacement = replacement_for(&right_ops, *idx);
137 if left_replacement != right_replacement {
138 return ThreeWayResult::Conflict;
139 }
140 }
141
142 // Check for conflicting insertions at the same position.
143 let left_inserts = insert_positions(&left_ops);
144 let right_inserts = insert_positions(&right_ops);
145 for pos in left_inserts.keys() {
146 if let Some(right_content) = right_inserts.get(pos) {
147 let left_content = &left_inserts[pos];
148 if left_content != right_content {
149 return ThreeWayResult::Conflict;
150 }
151 }
152 }
153
154 // No conflicts — merge.
155 let merged = merge_ops(base, &left_ops, &right_ops);
156 ThreeWayResult::Merged(merged)

Calls 7

reassemble_tokensFunction · 0.85
diff_tokensFunction · 0.85
modified_indicesFunction · 0.85
replacement_forFunction · 0.85
insert_positionsFunction · 0.85
merge_opsFunction · 0.85
getMethod · 0.65