╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ───────────────╮ │src/test/event/patch.zig│ ╰────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │250 - try std.testing.expectEqualStrings(if (selection == .source) revision.source_oid else revision.squash_oid, oid); │ │260 + const result_oid = (try repo.readRef(io, .{ .kind = .head, .name = "master" })) orelse return error.NotFound; │ │261 + try std.testing.expectEqual(selection, range.revision); │ │262 + try std.testing.expectEqualStrings(&target_oid, range.before_oid); │ │263 + try std.testing.expectEqualStrings(&result_oid, range.after_oid); │ │264 + { │ │265 + var commits = try repo.log(io, allocator, .{ .start_oids = &.{result_oid} }); │ │266 + defer commits.deinit(); │ │267 + const commit = (try commits.next(allocator)) orelse return error.NotFound; │ │268 + defer commit.deinit(); │ │269 + const parents = commit.content.commit.metadata.parent_oids orelse return error.ParentOidsNotFound; │ │270 + try std.testing.expectEqual(2, parents.len); │ │271 + try std.testing.expectEqualStrings(&target_oid, &parents[0]); │ │272 + try std.testing.expectEqualStrings(if (selection == .source) revision.source_oid else revision.squash_oid, &parents[1]);│ │273 + } │ │274 │ │275 // the source survives, and merged patches no longer follow it │ │276 _ = try repo.commitAtRef(io, allocator, .{ .message = "later" }, null, .{ .kind = .head, .name = "feature" }); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │591 .{ .tree = .{ .name = "head", .oid = &source_b_tree } }, │ │592 }; │ │593 var parent_patch = updated_patch; │ │571 - parent_patch.status = .{ .merged = &source_b_oid }; │ │594 + parent_patch.status = .{ .merged = .{ .revision = .source, .before_oid = &base_oid, .after_oid = &source_b_oid } };│ │595 { │ │596 try consumePatchWithRevision(.repo, io, allocator, &target, side_events_ref, patchrev_b_id, .{ │ │597 .base_oid = &base_oid, │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │705 .event = .{ .patch = closed_child }, │ │706 }}); │ │707 var merged_child = child.event; │ │685 - merged_child.status = .{ .merged = (child.event.revision orelse return error.NotFound).source_oid }; │ │708 + merged_child.status = .{ .merged = .{ .revision = .source, .before_oid = &base_oid, .after_oid = (child.event.revision orelse return error.NotFound).source_oid } };│ │709 try evt.consume(.local, .repo, .xit, repo_opts, io, allocator, &target, status_side_ref, &.{.{ │ │710 .id = std.fmt.bytesToHex(child_id, .lower), │ │711 .timestamp = 15, │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │747 .description = "has no revision", │ │748 .tags = "enhancement", │ │749 .target_branch = "master", │ │727 - .status = .{ .merged = &base_oid }, │ │750 + .status = .{ .merged = .{ .revision = .source, .before_oid = &base_oid, .after_oid = &base_oid } },│ │751 } }, │ │752 }})); │ │753 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────╮ │773 try patchLifecycle(.source); │ │774 } │ │775 │ │753 -fn patchLifecycle(merge_revision: pch.MergeRevision) !void { │ │776 +fn patchLifecycle(merge_revision: evt.Patch.MergeRevision) !void {│ │777 const io = std.testing.io; │ │778 const allocator = std.testing.allocator; │ │779 │ ╰───────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1068 const merged_moment = try evt.currentMoment(repo_opts, &target); │ │1069 const merged = (try evt.Patch.readById(Repo.DB, repo_opts.hash, merged_moment, &arena, &patch_id)) orelse return error.NotFound;│ │1070 try std.testing.expectEqual(.merged, merged.event.status.kind()); │ │1048 - const merged_oid = switch (merged.event.status) { │ │1049 - .merged => |oid| oid, │ │1071 + const merged_range = switch (merged.event.status) { │ │1072 + .merged => |range| range, │ │1073 else => return error.InvalidPatch, │ │1074 }; │ │1052 - try std.testing.expectEqualStrings(&selected_oid, merged_oid); │ │1075 + try std.testing.expectEqual(merge_revision, merged_range.revision); │ │1076 + try std.testing.expectEqualStrings(&base_oid, merged_range.before_oid); │ │1077 + try std.testing.expectEqualStrings(&selected_oid, merged_range.after_oid); │ │1078 try std.testing.expect(null != try evt.PatchRev.readById(Repo.DB, repo_opts.hash, merged_moment, &arena, &first_patchrev_id)); │ │1079 │ │1080 _ = arena.reset(.retain_capacity); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───────╮ │src/test/net.zig│ ╰────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │518 │ │519 const target_path = (try repoOnDiskPath(io, allocator, temp_path, "target", true)).?; │ │520 defer allocator.free(target_path); │ │521 - { │ │521 + const base_oid = blk: { │ │522 var target_repo = try rp.Repo(.xit, repo_opts).init(io, allocator, .{ .bare = true, .path = target_path }); │ │523 defer target_repo.deinit(io, allocator); │ │524 - _ = try commitServer(&target_repo, io, allocator, .{ .files = &.{.{ .path = "main.txt", .content = "base contents\n" }} }, .{ .author = "admin <admin@example.test>", .message = "initial code" }); │ │525 - } │ │524 + break :blk try commitServer(&target_repo, io, allocator, .{ .files = &.{.{ .path = "main.txt", .content = "base contents\n" }} }, .{ .author = "admin <admin@example.test>", .message = "initial code" });│ │525 + }; │ │526 │ │527 const other_path = (try repoOnDiskPath(io, allocator, temp_path, "other", true)).?; │ │528 defer allocator.free(other_path); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────╮ │731 } │ │732 │ │733 // │ │734 - // restore the patch, merge its source oid, and push the merge │ │734 + // restore the patch, merge a descendant of its source oid, and push the merge│ │735 // │ │736 │ │737 { │ ╰───────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │748 .event = .{ .patch = removed.event }, │ │749 }}); │ │750 } │ │751 - const merge_parents = [_][hash.hexLen(hash_kind)]u8{ third_source_oid, second_source_oid }; │ │752 - _ = try client.commit(io, allocator, .{ .message = "merge patch", .parent_oids = &merge_parents }); │ │751 + const merge_parents = [_][hash.hexLen(hash_kind)]u8{ base_oid, third_source_oid }; │ │752 + const merge_oid = try client.commit(io, allocator, .{ .message = "merge patch", .parent_oids = &merge_parents }); │ │753 + // later commits in the push must not be mistaken for the merge itself │ │754 + _ = try client.commit(io, allocator, .{ .message = "after merge", .allow_empty = true }); │ │755 try client.push(io, allocator, "origin", "master:feature", false, .{ .wire = .{ .ssh = .{ .command = ssh_cmd } } });│ │756 { │ │757 var target = try rp.Repo(.xit, repo_opts).open(io, allocator, .{ .path = target_path }); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │761 const moment = try evt.currentMoment(repo_opts, &target); │ │762 const patch = (try evt.Patch.readById(evt.EventDB(hash_kind), hash_kind, moment, &arena, &fork_id)) orelse return error.NotFound; │ │763 try std.testing.expectEqual(.merged, patch.event.status.kind()); │ │762 - const merged_oid = switch (patch.event.status) { │ │763 - .merged => |oid| oid, │ │764 + const merged_range = switch (patch.event.status) { │ │765 + .merged => |range| range, │ │766 else => return error.InvalidPatch, │ │767 }; │ │766 - try std.testing.expectEqualStrings(&second_source_oid, merged_oid); │ │768 + try std.testing.expectEqual(.source, merged_range.revision); │ │769 + try std.testing.expectEqualStrings(&base_oid, merged_range.before_oid); │ │770 + try std.testing.expectEqualStrings(&merge_oid, merged_range.after_oid); │ │771 const imported = (try evt.PatchRev.readById(evt.EventDB(hash_kind), hash_kind, moment, &arena, &second_revision_id)) orelse return error.NotFound;│ │772 try std.testing.expectEqualStrings(&second_patch_oid, imported.patch_oid); │ │773 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯