╭ changed ──────────────╮ │src/ui/Repo/Patches.zig│ ╰───────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────╮ │← previous│ ╰──────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │406 pub fn mergePatch(data: *const Self, session: *ui.Session, allocator: std.mem.Allocator, author: evt.CommitAuthor, id: []const u8, revision: evt.Patch.MergeRevision) !void {│ │407 const io = session.io orelse return error.NotFound; │ │408 const repos_dir = session.repos_dir orelse return error.NotFound; │ │392 - const admin_repo = session.admin_repo orelse return error.NotFound; │ │409 const repo_source = data.repo_source orelse return error.NotFound; │ │410 if (repo_source.repo_kind != .xit) return error.NotFound; │ │411 const patch_id = evt.parseEventId(id) catch return error.NotFound; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────╮ │413 const id_hex = std.fmt.bytesToHex(patch_id, .lower); │ │414 var target_repo = try rp.Repo(.xit, .{}).open(io, allocator, repo_source.localInitOpts());│ │415 defer target_repo.deinit(io, allocator); │ │400 - try pch.mergeAndRemoveFork(.{}, io, allocator, repos_dir, admin_repo, &target_repo, .{ │ │416 + try pch.mergeAndRemoveFork(.{}, io, allocator, repos_dir, &target_repo, .{ │ │417 .id = id_hex, │ │418 .revision = revision, │ │419 .author = author, │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │444 const id_hex = std.fmt.bytesToHex(patch_id, .lower); │ │445 const fork_path = try fork.forkPath(allocator, repos_dir, &id_hex); │ │446 defer allocator.free(fork_path); │ │431 - if (!try pch.editDraft(.{}, io, allocator, admin_repo, fork_path, .{ │ │447 + var user_repo = (try evt.openUserRepo(io, allocator, repos_dir, &user_id)) orelse return error.NotFound;│ │448 + defer user_repo.deinit(io, allocator); │ │449 + if (!try pch.editDraft(.{}, io, allocator, admin_repo, &user_repo, fork_path, .{ │ │450 .id = id_hex, │ │451 .user_id = user_id, │ │452 .repo_id = repo_id, │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │462 pub fn removeDraft(session: *ui.Session, allocator: std.mem.Allocator, author: evt.CommitAuthor, id: *const [evt.event_id_size]u8) !void {│ │463 const io = session.io orelse return error.NotFound; │ │464 const repos_dir = session.repos_dir orelse return error.NotFound; │ │447 - const admin_repo = session.admin_repo orelse return error.NotFound; │ │465 const user_id = session.userId() orelse return error.NotFound; │ │466 │ │467 const id_hex = std.fmt.bytesToHex(id.*, .lower); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │451 - try fork.remove(io, allocator, repos_dir, admin_repo, &id_hex, &user_id, author); │ │468 + var user_repo = (try evt.openUserRepo(io, allocator, repos_dir, &user_id)) orelse return error.NotFound;│ │469 + defer user_repo.deinit(io, allocator); │ │470 + try fork.remove(io, allocator, repos_dir, &user_repo, &id_hex, author); │ │471 } │ │472 │ │473 // `status`'s windowed listing. │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │720 var closed_window = try thread.loadWindow(Self, .patch, repo_opts.hash, arena, admin_moment, haxy_moment, event_id_to_patch, closed_set, closed_root, conflict_set, empty.selected_id, thread_comments_start, empty.search);│ │721 var merged_window = try thread.loadWindow(Self, .patch, repo_opts.hash, arena, admin_moment, haxy_moment, event_id_to_patch, merged_set, merged_root, conflict_set, empty.selected_id, thread_comments_start, empty.search);│ │722 var conflicts_window = try thread.loadWindow(Self, .patch, repo_opts.hash, arena, admin_moment, haxy_moment, event_id_to_patch, conflict_set, conflicts_root, conflict_set, empty.selected_id, thread_comments_start, null);│ │704 - try setPatchDetails(repo_kind, repo_opts, io, arena, admin_moment, haxy_moment, repo, &open_window); │ │705 - try setPatchDetails(repo_kind, repo_opts, io, arena, admin_moment, haxy_moment, repo, &closed_window); │ │706 - try setPatchDetails(repo_kind, repo_opts, io, arena, admin_moment, haxy_moment, repo, &merged_window); │ │707 - try setPatchDetails(repo_kind, repo_opts, io, arena, admin_moment, haxy_moment, repo, &conflicts_window); │ │723 + try setPatchDetails(repo_kind, repo_opts, io, arena, admin_moment, session.repos_dir, haxy_moment, repo, &open_window); │ │724 + try setPatchDetails(repo_kind, repo_opts, io, arena, admin_moment, session.repos_dir, haxy_moment, repo, &closed_window); │ │725 + try setPatchDetails(repo_kind, repo_opts, io, arena, admin_moment, session.repos_dir, haxy_moment, repo, &merged_window); │ │726 + try setPatchDetails(repo_kind, repo_opts, io, arena, admin_moment, session.repos_dir, haxy_moment, repo, &conflicts_window); │ │727 if (view == .conflicts and conflicts_window.count > 0) resolved_view = .conflicts; │ │728 │ │729 const comment_page = if (empty.comment_id.len == 0) │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────╮ │761 io: std.Io, │ │762 arena: *std.heap.ArenaAllocator, │ │763 admin_moment: ?evt.AdminDB.HashMap(.read_only), │ │764 + repos_dir: ?[]const u8, │ │765 haxy_moment: evt.EventDB(repo_opts.hash).HashMap(.read_only),│ │766 repo: *rp.Repo(repo_kind, repo_opts), │ │767 target: *Window, │ ╰──────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │771 for (items) |*item| { │ │772 const id = try evt.parseEventId(item.id); │ │773 const status = item.record.event.status.kind(); │ │754 - if (admin_moment) |moment| { │ │755 - const record = try evt.readRecordSubset(evt.Fork, struct { removed: bool }, evt.AdminDB, evt.admin_repo_opts.hash, moment, arena, &id);│ │756 - item.fork_exists = if (record) |value| !value.removed else false; │ │757 - } │ │774 + // a fork-backed patch's fork lives in its forker's user repo │ │775 + if (admin_moment) |moment| if (repos_dir) |dir| if (item.record.event.source_branch == null) { │ │776 + if (try evt.readForker(arena, moment, item.record.author_email)) |forker| { │ │777 + item.forker = forker.name; │ │778 + const record = try evt.readForkById(io, arena.child_allocator, arena, dir, &forker.id, &id); │ │779 + item.fork_exists = if (record) |value| !value.removed else false; │ │780 + } │ │781 + }; │ │782 const target_branch = item.record.event.target_branch; │ │783 const revision = item.record.event.revision orelse continue; │ │784 item.commit_count = revision.commit_count; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │821 selected_id: []const u8, │ │822 target_repo: *rp.Repo(repo_kind, repo_opts), │ │823 ) !Window { │ │800 - const user_id = session.data.user_id orelse return .empty; │ │801 - if (user_id.len != evt.event_id_size) return .empty; │ │824 + const user_id = session.userId() orelse return .empty; │ │825 + const user_name = session.data.user_name orelse return .empty; │ │826 const repos_dir = session.repos_dir orelse return .empty; │ │827 const io = session.io orelse return .empty; │ │804 - const key = evt.Fork.draftKey(repo_id, user_id); │ │805 - const drafts_cursor = try admin_moment.getCursor(hash.hashInt(evt.admin_repo_opts.hash, evt.Fork.repo_user_to_draft_id_set_key)) orelse return .empty;│ │806 - const drafts = try evt.AdminDB.HashMap(.read_only).init(drafts_cursor); │ │807 - const set_cursor = try drafts.getCursor(hash.hashInt(evt.admin_repo_opts.hash, &key)) orelse return .empty; │ │808 - const set = try evt.AdminDB.SortedSet(.read_only).init(set_cursor); │ │828 + │ │829 + // the viewer's drafts live in their user repo │ │830 + var user_repo = (try evt.openUserRepo(io, arena.child_allocator, repos_dir, &user_id)) orelse return .empty; │ │831 + defer user_repo.deinit(io, arena.child_allocator); │ │832 + const user_moment = (try evt.userMoment(&user_repo)) orelse return .empty; │ │833 + const drafts_cursor = try user_moment.getCursor(hash.hashInt(evt.user_repo_opts.hash, evt.Fork.repo_to_draft_id_set_key)) orelse return .empty; │ │834 + const drafts = try evt.UserDB.HashMap(.read_only).init(drafts_cursor); │ │835 + const set_cursor = try drafts.getCursor(hash.hashInt(evt.user_repo_opts.hash, repo_id)) orelse return .empty; │ │836 + const set = try evt.UserDB.SortedSet(.read_only).init(set_cursor); │ │837 const aa = arena.allocator(); │ │838 │ │839 var root_key: ?[]const u8 = null; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │840 if (selected_id.len != 0) { │ │841 const id = evt.parseEventId(selected_id) catch return error.NotFound; │ │814 - if (try evt.Fork.readById(evt.AdminDB, evt.admin_repo_opts.hash, admin_moment, arena, &id)) |record| {│ │842 + if (try evt.Fork.readById(evt.UserDB, evt.user_repo_opts.hash, user_moment, arena, &id)) |record| { │ │843 if (!record.removed and record.event.stage == .draft) { │ │844 const order_key = try aa.dupe(u8, &evt.orderKeyDesc(record.created_order, &id)); │ │845 if (!try set.contains(order_key)) return error.NotFound; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯