╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ───────────────╮ │src/test/event/patch.zig│ ╰────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │449 }})); │ │450 │ │451 const invalid_merged_id = evt.EventWithId.randomId(prng.random()); │ │452 - try std.testing.expectError(error.InvalidPatch, evt.consume(.repo, .xit, repo_opts, io, allocator, &target, evt.events_ref, &.{.{ │ │452 + try std.testing.expectError(error.InvalidPatch, evt.consume(.local, .repo, .xit, repo_opts, io, allocator, &target, evt.events_ref, &.{.{│ │453 .id = std.fmt.bytesToHex(invalid_merged_id, .lower), │ │454 .timestamp = 16, │ │455 .author = author, │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │511 │ │512 var admin = try rp.Repo(.xit, evt.admin_repo_opts).init(io, allocator, .{ .path = admin_path }); │ │513 defer admin.deinit(io, allocator); │ │514 - try evt.consume(.admin, .xit, evt.admin_repo_opts, io, allocator, &admin, evt.events_ref, &.{ │ │514 + try evt.consume(.server, .admin, .xit, evt.admin_repo_opts, io, allocator, &admin, evt.events_ref, &.{│ │515 .{ │ │516 .id = std.fmt.bytesToHex(user_id, .lower), │ │517 .timestamp = 1, │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │748 // merge the selected revision into the target │ │749 // │ │750 │ │751 - try evt.Patch.update(.xit, repo_opts, io, allocator, &target, &patch_id, .{ .status = .closed }, author); │ │751 + try evt.Patch.update(.local, .xit, repo_opts, io, allocator, &target, &patch_id, .{ .status = .closed }, author);│ │752 try std.testing.expectError(error.PatchClosed, pch.merge(repo_opts, io, allocator, repos_dir, &target, .{ │ │753 .id = patch_id_hex, │ │754 .revision = merge_revision, │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │755 .author = author, │ │756 .timestamp = 5, │ │757 })); │ │758 - try evt.Patch.update(.xit, repo_opts, io, allocator, &target, &patch_id, .{ .status = .open }, author); │ │758 + try evt.Patch.update(.local, .xit, repo_opts, io, allocator, &target, &patch_id, .{ .status = .open }, author);│ │759 │ │760 // run the cache scenario once; both lifecycle runs still perform a merge │ │761 if (merge_revision == .source) { │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │864 const state = Repo.State(.read_only){ .core = &target.core, .extra = .{ .moment = &moment } }; │ │865 try std.testing.expectError(error.ObjectNotFound, obj.Object(.xit, repo_opts).initCommit(state, io, allocator, source));│ │866 } │ │867 - const events_before = try target.readRef(io, evt.events_ref); │ │867 │ │868 // a target update invalidates the old result before refresh │ │869 { │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │879 try std.testing.expectEqualDeep(pch.Mergeability{}, try readMergeability(target, io, allocator, id, patch)); │ │880 try std.testing.expectError(error.MergeCheckUnavailable, pch.merge(repo_opts, io, allocator, repos_dir, target, input)); │ │881 try std.testing.expectError(error.MergeCheckUnavailable, pch.merge(repo_opts, io, allocator, repos_dir, target, squash_input)); │ │883 - pch.refreshMergeability(repo_opts, io, allocator, target, null); │ │882 + │ │883 + // local edits and server comments leave checks alone │ │884 + var edit = evt.Patch.Update{ .fields = .{ │ │885 + .title = "edit the answer", │ │886 + .tags = patch.tags, │ │887 + .description = patch.description, │ │888 + .target_branch = patch.target_branch, │ │889 + } }; │ │890 + try evt.Patch.update(.local, .xit, repo_opts, io, allocator, target, id, edit, author); │ │891 + try std.testing.expectEqualDeep(pch.Mergeability{}, try readMergeability(target, io, allocator, id, patch)); │ │892 + _ = try evt.Comment.create(.server, .xit, repo_opts, io, allocator, target, &input.id, &input.id, "reviewing the answer", author); │ │893 + try std.testing.expectEqualDeep(pch.Mergeability{}, try readMergeability(target, io, allocator, id, patch)); │ │894 + │ │895 + // a server patch edit refreshes its mergeability │ │896 + edit.fields.title = patch.title; │ │897 + try evt.Patch.update(.server, .xit, repo_opts, io, allocator, target, id, edit, author); │ │898 + const events_before = try target.readRef(io, evt.events_ref); │ │899 try std.testing.expectEqualDeep(pch.Mergeability{ .source = .conflict, .squash = .conflict }, try readMergeability(target, io, allocator, id, patch));│ │900 try expectMergeabilityShortBytes(try target.core.latestMoment(), id); │ │901 try std.testing.expectError(error.MergeConflict, pch.merge(repo_opts, io, allocator, repos_dir, target, input)); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │929 { │ │930 try std.Io.Dir.renameAbsolute(draft_path, away_path, io); │ │931 defer std.Io.Dir.renameAbsolute(away_path, draft_path, io) catch {}; │ │917 - pch.refreshMergeability(repo_opts, io, allocator, target, id.*); │ │932 + try std.testing.expectError(error.PatchDataUnavailable, pch.merge(repo_opts, io, allocator, repos_dir, target, input));│ │933 try std.testing.expectEqualDeep(pch.Mergeability{}, try readMergeability(target, io, allocator, id, patch)); │ │934 try std.testing.expectEqual(events_before, try target.readRef(io, evt.events_ref)); │ │935 } │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───────╮ │src/test/net.zig│ ╰────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │628 defer arena.deinit(); │ │629 const moment = try evt.currentMoment(repo_opts, &target); │ │630 const patch = (try evt.Patch.readById(evt.EventDB(hash_kind), hash_kind, moment, &arena, &fork_id)) orelse return error.NotFound;│ │631 - try evt.Patch.update(.xit, repo_opts, io, allocator, &target, &fork_id, .{ .fields = .{ │ │631 + try evt.Patch.update(.server, .xit, repo_opts, io, allocator, &target, &fork_id, .{ .fields = .{ │ │632 .title = "edited feature", │ │633 .description = patch.event.description, │ │634 .tags = patch.event.tags, │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │715 { │ │716 var target = try rp.Repo(.xit, repo_opts).open(io, allocator, .{ .path = target_path }); │ │717 defer target.deinit(io, allocator); │ │718 - try evt.remove(.repo, .xit, repo_opts, io, allocator, &target, &fork_id, .patch, .{ .name = "admin", .email = "admin@example.test" }); │ │718 + try evt.remove(.server, .repo, .xit, repo_opts, io, allocator, &target, &fork_id, .patch, .{ .name = "admin", .email = "admin@example.test" });│ │719 } │ │720 try client.push(io, allocator, "patch-to-feature", "master:patch", false, .{ .wire = .{ .ssh = .{ .command = ssh_cmd } } }); │ │721 { │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │739 defer arena.deinit(); │ │740 const moment = try evt.currentMoment(repo_opts, &target); │ │741 const removed = (try evt.Patch.readById(evt.EventDB(hash_kind), hash_kind, moment, &arena, &fork_id)) orelse return error.NotFound;│ │742 - try evt.consume(.repo, .xit, repo_opts, io, allocator, &target, evt.events_ref, &.{.{ │ │742 + try evt.consume(.server, .repo, .xit, repo_opts, io, allocator, &target, evt.events_ref, &.{.{ │ │743 .id = fork_id_hex, │ │744 .timestamp = 4, │ │745 .author = .{ .name = "admin", .email = "admin@example.test" }, │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯