╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ───╮ │src/fork.zig│ ╰────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │230 if (fork_patch.removed and target_patch == null) return error.PatchDataUnavailable; │ │231 if (target_patch) |patch| { │ │232 if (!std.mem.eql(u8, patch.author_email orelse "", author.email)) return error.PatchDataUnavailable;│ │233 + if (patch.event.status == .merged) return error.PatchAlreadyMerged; │ │234 } │ │235 const published = target_patch != null; │ │236 const title = if (target_patch) |patch| patch.event.title else fork_patch.event.title; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────╮ │319 ctx.revision_id_maybe.* = revision_id;│ │320 │ │321 if (!ctx.published) { │ │322 + var patch = ctx.patch.event; │ │323 + patch.patchrev_id = revision_hex; │ │324 events[event_count] = .{ │ │325 .id = ctx.patch_id, │ │326 .timestamp = ctx.timestamp, │ ╰───────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────╮ │327 .author = ctx.author, │ │325 - .event = .{ .patch = .{ │ │326 - .title = ctx.patch.event.title, │ │327 - .description = ctx.patch.event.description, │ │328 - .tags = ctx.patch.event.tags, │ │329 - .target_patch_id = ctx.patch.event.target_patch_id,│ │330 - .patchrev_id = revision_hex, │ │331 - } }, │ │328 + .event = .{ .patch = patch }, │ │329 }; │ │330 event_count += 1; │ │331 } │ ╰────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────╮ │386 if (published_patch.event.patchrev_id) |*published_revision| { │ │387 if (std.mem.eql(u8, published_revision, &revision_hex)) return; │ │388 } │ │389 + var patch = published_patch.event; │ │390 + patch.patchrev_id = revision_hex; │ │391 evt.consume(.repo, .xit, repo_opts, io, allocator, target_repo, evt.events_ref, &.{.{│ │392 .id = id.*, │ │393 .timestamp = timestamp, │ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────╮ │394 .author = author, │ │396 - .event = .{ .patch = .{ │ │397 - .title = published_patch.event.title, │ │398 - .description = published_patch.event.description, │ │399 - .tags = published_patch.event.tags, │ │400 - .target_patch_id = published_patch.event.target_patch_id,│ │401 - .patchrev_id = revision_hex, │ │402 - } }, │ │395 + .event = .{ .patch = patch }, │ │396 }}) catch {}; │ │397 } │ │398 │ ╰──────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │445 } │ │446 if (local_patch.removed) { │ │447 if (existing == null) return error.PatchDataUnavailable; │ │455 - return; │ │456 - } │ │448 + } else { │ │449 + const revision_hex = local_patch.event.patchrev_id orelse return error.PatchNotPushed; │ │450 + const revision_id = try evt.parseEventId(&revision_hex); │ │451 + const revision = (try evt.PatchRev.readById(evt.EventDB(repo_opts.hash), repo_opts.hash, fork_moment, &arena, &revision_id)) orelse return error.PatchNotPushed;│ │452 + if (revision.removed) return error.PatchNotPushed; │ │453 + var patch = (existing orelse local_patch).event; │ │454 + patch.patchrev_id = revision_hex; │ │455 + if (existing == null) patch.status = .open; │ │456 │ │458 - const revision_hex = local_patch.event.patchrev_id orelse return error.PatchNotPushed; │ │459 - const revision_id = try evt.parseEventId(&revision_hex); │ │460 - const revision = (try evt.PatchRev.readById(evt.EventDB(repo_opts.hash), repo_opts.hash, fork_moment, &arena, &revision_id)) orelse return error.PatchNotPushed; │ │461 - if (revision.removed) return error.PatchNotPushed; │ │462 - const metadata = existing orelse local_patch; │ │457 + try evt.consume(.repo, .xit, repo_opts, io, allocator, target_repo, evt.events_ref, &.{.{ │ │458 + .id = input.id, │ │459 + .timestamp = input.timestamp, │ │460 + .author = input.author, │ │461 + .event = .{ .patch = patch }, │ │462 + }}); │ │463 │ │464 - try evt.consume(.repo, .xit, repo_opts, io, allocator, target_repo, evt.events_ref, &.{.{ │ │465 - .id = input.id, │ │466 - .timestamp = input.timestamp, │ │467 - .author = input.author, │ │468 - .event = .{ .patch = .{ │ │469 - .title = metadata.event.title, │ │470 - .description = metadata.event.description, │ │471 - .tags = metadata.event.tags, │ │472 - .target_patch_id = metadata.event.target_patch_id, │ │473 - .patchrev_id = revision_hex, │ │474 - } }, │ │475 - }}); │ │464 + try evt.consume(.fork, .xit, repo_opts, io, allocator, &fork_repo, evt.events_ref, &.{.{ │ │465 + .id = input.id, │ │466 + .timestamp = input.timestamp, │ │467 + .author = input.author, │ │468 + .event = .{ .patch = null }, │ │469 + }}); │ │470 + } │ │471 │ │477 - try evt.consume(.fork, .xit, repo_opts, io, allocator, &fork_repo, evt.events_ref, &.{.{ │ │478 - .id = input.id, │ │479 - .timestamp = input.timestamp, │ │480 - .author = input.author, │ │481 - .event = .{ .patch = null }, │ │482 - }}); │ │472 + if (fork_record.event.stage == .draft) { │ │473 + var posted = fork_record.event; │ │474 + posted.stage = .posted; │ │475 + try evt.consume(.admin, .xit, evt.admin_repo_opts, io, allocator, admin_repo, evt.events_ref, &.{.{ │ │476 + .id = input.id, │ │477 + .timestamp = input.timestamp, │ │478 + .author = input.author, │ │479 + .event = .{ .fork = posted }, │ │480 + }}); │ │481 + } │ │482 } │ │483 │ │484 // delete first so a failed tombstone can be retried safely │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───────────────╮ │src/test/event/admin.zig│ ╰────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │415 var record = (try evt.Fork.readById(evt.AdminDB, evt.admin_repo_opts.hash, moment, &arena, &fork_id)) orelse return error.NotFound;│ │416 try std.testing.expectEqualSlices(u8, &user_id, record.event.user_id); │ │417 try std.testing.expectEqualSlices(u8, &repo_id, record.event.repo_id); │ │418 + try std.testing.expectEqual(.draft, record.event.stage); │ │419 try std.testing.expectEqual(1, try indexedForkCount(moment, evt.Fork.user_id_to_fork_id_set_key, &user_id)); │ │419 - try std.testing.expectEqual(1, try indexedForkCount(moment, evt.Fork.repo_id_to_fork_id_set_key, &repo_id)); │ │420 + const draft_key = evt.Fork.draftKey(&repo_id, &user_id); │ │421 + try std.testing.expectEqual(1, try indexedForkCount(moment, evt.Fork.repo_user_to_draft_id_set_key, &draft_key)); │ │422 │ │423 var draft_repo = try rp.Repo(.xit, fork_repo_opts).open(io, allocator, .{ .path = draft_path }); │ │424 defer draft_repo.deinit(io, allocator); │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │439 record = (try evt.Fork.readById(evt.AdminDB, evt.admin_repo_opts.hash, moment, &arena, &fork_id)) orelse return error.NotFound;│ │440 try std.testing.expect(record.removed); │ │441 try std.testing.expectEqual(0, try indexedForkCount(moment, evt.Fork.user_id_to_fork_id_set_key, &user_id)); │ │440 - try std.testing.expectEqual(0, try indexedForkCount(moment, evt.Fork.repo_id_to_fork_id_set_key, &repo_id)); │ │442 + try std.testing.expectEqual(0, try indexedForkCount(moment, evt.Fork.repo_user_to_draft_id_set_key, &draft_key)); │ │443 │ │444 try fork.remove(io, allocator, repos_dir, &admin, &fork_id_hex, &user_id, author); │ │445 } │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───────────────╮ │src/test/event/patch.zig│ ╰────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────╮ │241 }; │ │242 var target_patch = updated_patch; │ │243 target_patch.patchrev_id = std.fmt.bytesToHex(patchrev_a_id, .lower); │ │244 + target_patch.status = .closed; │ │245 { │ │246 try evt.consume(.repo, .xit, repo_opts, io, allocator, &target, evt.events_ref, &.{│ │247 .{ │ ╰────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────╮ │271 }; │ │272 var parent_patch = updated_patch; │ │273 parent_patch.patchrev_id = std.fmt.bytesToHex(patchrev_b_id, .lower); │ │274 + parent_patch.status = .merged; │ │275 { │ │276 try evt.consume(.repo, .xit, repo_opts, io, allocator, &target, side_events_ref, &.{│ │277 .{ │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯