╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ────╮ │src/patch.zig│ ╰─────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │660 } │ │661 │ │662 // copy the selected commit and its dependencies │ │482 - { │ │483 - var fork_repo_moment = try ctx.fork_repo.core.latestMoment(); │ │484 - const fork_state = State(.read_only){ .core = &ctx.fork_repo.core, .extra = .{ .moment = &fork_repo_moment } }; │ │663 + if (ctx.fork_repo) |repo| { │ │664 + var fork_repo_moment = try repo.core.latestMoment(); │ │665 + const fork_state = State(.read_only){ .core = &repo.core, .extra = .{ .moment = &fork_repo_moment } }; │ │666 var objects = try obj.ObjectIterator(.xit, repo_opts).init(fork_state, ctx.io, ctx.allocator, .{ .kind = .all });│ │667 defer objects.deinit(); │ │668 try objects.include(&ctx.merge_oid); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │670 } │ │671 │ │672 // import the revision and mark the patch merged │ │492 - if (!try importMergedFromFork(repo_opts, state, &ctx.core.db, &moment, ctx.io, ctx.allocator, ctx.fork_repo, &ctx.patch_id, &ctx.merge_oid, ctx.expected_patch, ctx.author, ctx.timestamp)) return error.PatchOutOfDate;│ │673 + if (!try importMergedRevision(repo_opts, state, &ctx.core.db, &moment, ctx.io, ctx.allocator, ctx.fork_repo, &ctx.patch_id, &ctx.merge_oid, ctx.expected_patch, ctx.author, ctx.timestamp)) return error.PatchOutOfDate;│ │674 │ │675 // merge the selected commit │ │676 { │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │696 } │ │697 }; │ │698 │ │518 - try fork_repo.core.db_file.lock(io, .shared); │ │519 - defer fork_repo.core.db_file.unlock(io); │ │699 + if (fork_repo_maybe) |*repo| try repo.core.db_file.lock(io, .shared);│ │700 + defer if (fork_repo_maybe) |*repo| repo.core.db_file.unlock(io); │ │701 try target_repo.core.db_file.lock(io, .exclusive); │ │702 defer target_repo.core.db_file.unlock(io); │ │703 │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ │704 const history = try DB.ArrayList(.read_write).init(target_repo.core.db.rootCursor());│ │705 try history.appendContext(.{ .slot = try history.getSlot(-1) }, Ctx{ │ │706 .core = &target_repo.core, │ │526 - .fork_repo = &fork_repo, │ │707 + .fork_repo = if (fork_repo_maybe) |*repo| repo else null, │ │708 .io = io, │ │709 .allocator = allocator, │ │710 .patch_id = patch_id, │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │731 input: MergeInput, │ │732 ) !void { │ │733 try merge(repo_opts, io, allocator, repo_root_path, target_repo, input); │ │553 - try fork.remove(io, allocator, repo_root_path, admin_repo, &input.id, null, input.author); │ │734 + var arena = std.heap.ArenaAllocator.init(allocator); │ │735 + defer arena.deinit(); │ │736 + const record = (try evt.Patch.readFromRepo(.xit, repo_opts, io, allocator, &arena, target_repo, &try evt.parseEventId(&input.id))) orelse return error.InvalidPatch;│ │737 + if (record.event.source_branch == null) try fork.remove(io, allocator, repo_root_path, admin_repo, &input.id, null, input.author); │ │738 } │ │739 │ │740 fn commitAuthor(line: []const u8) !evt.CommitAuthor { │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │762 │ │763 const patch_hex = std.fmt.bytesToHex(patch_id.*, .lower); │ │764 const fork_path = try fork.forkPath(arena.allocator(), repo_root_path, &patch_hex); │ │581 - var fork_repo = try rp.Repo(.xit, repo_opts).open(io, allocator, .{ .path = fork_path, .require_repo_root = true }); │ │582 - defer fork_repo.deinit(io, allocator); │ │765 + const events = try evt.currentMomentFromRepoMoment(repo_opts.hash, moment.readOnly()); │ │766 + const record = (try evt.Patch.readById(evt.EventDB(repo_opts.hash), repo_opts.hash, events, &arena, patch_id)) orelse return; │ │767 + var fork_repo_maybe: ?rp.Repo(.xit, repo_opts) = if (record.event.source_branch != null) null else try rp.Repo(.xit, repo_opts).open(io, allocator, .{ .path = fork_path, .require_repo_root = true });│ │768 + defer if (fork_repo_maybe) |*repo| repo.deinit(io, allocator); │ │769 │ │584 - _ = try importMergedFromFork(repo_opts, state, db, moment, io, allocator, &fork_repo, patch_id, merged_oid, null, null, 0); │ │770 + _ = try importMergedRevision(repo_opts, state, db, moment, io, allocator, if (fork_repo_maybe) |*repo| repo else null, patch_id, merged_oid, null, null, 0); │ │771 } │ │772 │ │773 // import the revision and mark its patch merged in the current transaction │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────╮ │588 -fn importMergedFromFork( │ │774 +fn importMergedRevision( │ │775 comptime repo_opts: rp.RepoOpts(.xit), │ │776 state: rp.Repo(.xit, repo_opts).State(.read_write),│ │777 db: *evt.EventDB(repo_opts.hash), │ ╰────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────╮ │778 moment: *evt.EventDB(repo_opts.hash).HashMap(.read_write),│ │779 io: std.Io, │ │780 allocator: std.mem.Allocator, │ │595 - fork_repo: *rp.Repo(.xit, repo_opts), │ │781 + fork_repo: ?*rp.Repo(.xit, repo_opts), │ │782 patch_id: *const [evt.event_id_size]u8, │ │783 merged_oid: *const [hash.hexLen(repo_opts.hash)]u8, │ │784 expected_patch: ?evt.Patch, │ ╰───────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │795 if (patch_record.removed or patch_record.event.status.kind() == .merged) return false; │ │796 if (expected_patch) |expected| { │ │797 if (!evt.fieldEqual(evt.Patch, expected, patch_record.event)) return false; │ │798 + if (try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, evt.Patch.conflicts_key))) |cursor| { │ │799 + const conflicts = try DB.SortedMap(.read_only).init(cursor); │ │800 + if (try conflicts.getCursor(&evt.orderKeyDesc(patch_record.created_order, patch_id)) != null) return false;│ │801 + } │ │802 } │ │803 const revision_id = try evt.parseEventId(&selected.id); │ │804 if (!selected.includesOid(merged_oid)) return false; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │805 │ │616 - const fork_moment = try evt.currentMoment(repo_opts, fork_repo); │ │617 - const revision = (try evt.PatchRev.readById(DB, repo_opts.hash, fork_moment, &arena, &revision_id)) orelse return false; │ │806 + const current_revision = try evt.PatchRev.readById(DB, repo_opts.hash, haxy_moment, &arena, &revision_id); │ │807 + const revision = (if (fork_repo) |repo| │ │808 + try evt.PatchRev.readById(DB, repo_opts.hash, try evt.currentMoment(repo_opts, repo), &arena, &revision_id) │ │809 + else │ │810 + current_revision) orelse return false; │ │811 if (!selected.matches(revision)) return false; │ │812 │ │620 - var fork_repo_moment = try fork_repo.core.latestMoment(); │ │621 - const fork_state = rp.Repo(.xit, repo_opts).State(.read_only){ .core = &fork_repo.core, .extra = .{ .moment = &fork_repo_moment } }; │ │813 + var fork_repo_moment = if (fork_repo) |repo| try repo.core.latestMoment() else moment.readOnly(); │ │814 + const fork_state = rp.Repo(.xit, repo_opts).State(.read_only){ .core = if (fork_repo) |repo| &repo.core else state.core, .extra = .{ .moment = &fork_repo_moment } };│ │815 var event_oid: [hash.hexLen(repo_opts.hash)]u8 = undefined; │ │816 if (revision.event_oid.len != event_oid.len) return false; │ │817 @memcpy(&event_oid, revision.event_oid); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯