╭ changed ────╮ │src/event.zig│ ╰─────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │271 │ │272 const haxy_moment = try DB.HashMap(.read_write).init(haxy_moment_cursor); │ │273 │ │274 - // merge changes from every parent after the first parent. the first parent │ │275 - // is the baseline, so a later parent only contributes values it changed. │ │274 + // merge changes from every parent after the first parent. the common │ │275 + // ancestor is the baseline, so a later parent only contributes values │ │276 + // it changed relative to the merge base. │ │277 if (repo_event.parent_oids.len > 1) { │ │277 - var first_parent_oid: [hash.byteLen(repo_opts.hash)]u8 = undefined; │ │278 - _ = try std.fmt.hexToBytes(&first_parent_oid, &repo_event.parent_oids[0]); │ │279 - const first_parent_haxy_moment_cursor = try haxy_moments.getCursor(hash.bytesToInt(repo_opts.hash, &first_parent_oid)) orelse return error.CursorNotFound;│ │280 - const first_parent_haxy_moment = try DB.HashMap(.read_only).init(first_parent_haxy_moment_cursor); │ │281 - │ │278 for (repo_event.parent_oids[1..]) |*parent_oid| { │ │279 var oid: [hash.byteLen(repo_opts.hash)]u8 = undefined; │ │280 _ = try std.fmt.hexToBytes(&oid, parent_oid); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │282 const parent_haxy_moment_cursor = try haxy_moments.getCursor(hash.bytesToInt(repo_opts.hash, &oid)) orelse return error.CursorNotFound; │ │283 const parent_haxy_moment = try DB.HashMap(.read_only).init(parent_haxy_moment_cursor); │ │284 │ │289 - try mergeChangedMapEntries(DB, haxy_moment, parent_haxy_moment, first_parent_haxy_moment, true); │ │285 + const baseline_oid_hex = try mrg.commonAncestor(.xit, repo_opts, state.readOnly(), io, allocator, &repo_event.parent_oids[0], parent_oid); │ │286 + var baseline_oid: [hash.byteLen(repo_opts.hash)]u8 = undefined; │ │287 + _ = try std.fmt.hexToBytes(&baseline_oid, &baseline_oid_hex); │ │288 + const baseline_haxy_moment_cursor = try haxy_moments.getCursor(hash.bytesToInt(repo_opts.hash, &baseline_oid)) orelse return error.CursorNotFound;│ │289 + const baseline_haxy_moment = try DB.HashMap(.read_only).init(baseline_haxy_moment_cursor); │ │290 + │ │291 + try mergeChangedMapEntries(DB, haxy_moment, parent_haxy_moment, baseline_haxy_moment, true); │ │292 } │ │293 } │ │294 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────╮ │366 const kv_pair = try kv_pair_cursor.readKeyValuePair(); │ │367 │ │368 const baseline_value_cursor = try baseline.getCursor(kv_pair.hash) orelse {│ │369 + if ((try target.getCursor(kv_pair.hash)) != null) { │ │370 + return error.MergeConflict; │ │371 + } │ │372 + │ │373 try target.put(kv_pair.hash, .{ .slot = kv_pair.value_cursor.slot() });│ │374 continue; │ │375 }; │ ╰────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────╮ │376 │ │371 - if (baseline_value_cursor.slot().value == kv_pair.value_cursor.slot().value) {│ │372 - continue; │ │373 - } │ │377 + const tag = kv_pair.value_cursor.slot().tag; │ │378 │ │375 - if (kv_pair.value_cursor.slot().tag != baseline_value_cursor.slot().tag) { │ │379 + if (tag != baseline_value_cursor.slot().tag) { │ │380 return error.UnexpectedTag; │ │381 } │ │382 │ ╰───────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │379 - const tag = kv_pair.value_cursor.slot().tag; │ │383 + if (kv_pair.value_cursor.slot().value == baseline_value_cursor.slot().value) { │ │384 + continue; │ │385 + } │ │386 │ │387 if (tag == .hash_map) { │ │388 + const target_existing_cursor = try target.getCursor(kv_pair.hash) orelse return error.MergeConflict;│ │389 + if (target_existing_cursor.slot().tag != .hash_map) { │ │390 + return error.MergeConflict; │ │391 + } │ │392 + │ │393 const target_child_cursor = try target.putCursor(kv_pair.hash); │ │394 const target_child = try DB.HashMap(.read_write).init(target_child_cursor); │ │395 const parent_child = try DB.HashMap(.read_only).init(kv_pair.value_cursor); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │396 const baseline_child = try DB.HashMap(.read_only).init(baseline_value_cursor); │ │397 try mergeChangedMapEntries(DB, target_child, parent_child, baseline_child, false); │ │398 } else if (is_top_level) { │ │399 + // the moment-index is a top-level key in the haxy moment │ │400 + // and is not a map. we don't want to do any merge of this. │ │401 continue; │ │402 } else { │ │403 + const target_value_cursor = try target.getCursor(kv_pair.hash) orelse return error.MergeConflict;│ │404 + if (target_value_cursor.slot().value != baseline_value_cursor.slot().value) { │ │405 + return error.MergeConflict; │ │406 + } │ │407 + │ │408 try target.put(kv_pair.hash, .{ .slot = kv_pair.value_cursor.slot() }); │ │409 } │ │410 } │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯