╭ changed ────╮ │src/patch.zig│ ╰─────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────────────────────────────────────────────────╮ │17 timestamp: u64, │ │18 }; │ │19 │ │20 +pub const EditDraftInput = struct { │ │21 + id: [evt.event_id_size * 2]u8, │ │22 + user_id: [evt.event_id_size]u8, │ │23 + repo_id: [evt.event_id_size]u8, │ │24 + title: []const u8, │ │25 + tags: []const u8, │ │26 + description: []const u8, │ │27 + author: evt.CommitAuthor, │ │28 + timestamp: u64, │ │29 +}; │ │30 + │ │31 pub const MergeRevision = enum { squash, source };│ │32 │ │33 pub const MergeInput = struct { │ ╰──────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────╮ │43 allocator: std.mem.Allocator, │ │44 admin_repo: *rp.Repo(.xit, evt.admin_repo_opts), │ │45 target_repo: *rp.Repo(.xit, repo_opts), │ │35 - path: []const u8, │ │46 + fork_path: []const u8, │ │47 input: PublishInput, │ │48 ) !void { │ │49 const patch_id = try evt.parseEventId(&input.id);│ ╰─────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │60 !std.mem.eql(u8, user.event.name, input.author.name) or │ │61 !std.mem.eql(u8, user.event.email, input.author.email)) return error.InvalidPatchDraft; │ │62 │ │52 - var fork_repo = rp.Repo(.xit, repo_opts).open(io, allocator, .{ .path = path }) catch return error.PatchDataUnavailable; │ │63 + var fork_repo = rp.Repo(.xit, repo_opts).open(io, allocator, .{ .path = fork_path }) catch return error.PatchDataUnavailable; │ │64 defer fork_repo.deinit(io, allocator); │ │65 const fork_moment = evt.currentMoment(repo_opts, &fork_repo) catch return error.PatchDataUnavailable; │ │66 const local_patch = (try evt.Patch.readById(evt.EventDB(repo_opts.hash), repo_opts.hash, fork_moment, &arena, &patch_id)) orelse return error.PatchDataUnavailable;│ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │112 .event = .{ .fork = published }, │ │113 }}); │ │114 } │ │115 +} │ │116 + │ │117 +pub fn editDraft( │ │118 + comptime repo_opts: rp.RepoOpts(.xit), │ │119 + io: std.Io, │ │120 + allocator: std.mem.Allocator, │ │121 + admin_repo: *rp.Repo(.xit, evt.admin_repo_opts), │ │122 + fork_path: []const u8, │ │123 + input: EditDraftInput, │ │124 +) !bool { │ │125 + if (!evt.Patch.fieldsValid(input.title, input.tags)) return error.InvalidFields; │ │126 + const patch_id = try evt.parseEventId(&input.id); │ │127 + var arena = std.heap.ArenaAllocator.init(allocator); │ │128 + defer arena.deinit(); │ │129 + │ │130 + const admin_moment = try evt.currentMoment(evt.admin_repo_opts, admin_repo); │ │131 + const fork_record = (try evt.Fork.readById(evt.AdminDB, evt.admin_repo_opts.hash, admin_moment, &arena, &patch_id)) orelse return false; │ │132 + if (fork_record.event.stage != .draft) return false; │ │133 + if (fork_record.removed or │ │134 + !std.mem.eql(u8, fork_record.event.user_id, &input.user_id) or │ │135 + !std.mem.eql(u8, fork_record.event.repo_id, &input.repo_id)) return error.InvalidPatchDraft; │ │136 + const user = (try evt.User.readById(evt.AdminDB, evt.admin_repo_opts.hash, admin_moment, &arena, &input.user_id)) orelse return error.InvalidPatchDraft; │ │137 + if (user.removed or │ │138 + !std.mem.eql(u8, user.event.name, input.author.name) or │ │139 + !std.mem.eql(u8, user.event.email, input.author.email)) return error.InvalidPatchDraft; │ │140 + │ │141 + var fork_repo = rp.Repo(.xit, repo_opts).open(io, allocator, .{ .path = fork_path, .require_repo_root = true }) catch return error.PatchDataUnavailable; │ │142 + defer fork_repo.deinit(io, allocator); │ │143 + const fork_moment = evt.currentMoment(repo_opts, &fork_repo) catch return error.PatchDataUnavailable; │ │144 + const record = (try evt.Patch.readById(evt.EventDB(repo_opts.hash), repo_opts.hash, fork_moment, &arena, &patch_id)) orelse return error.PatchDataUnavailable;│ │145 + if (record.removed) return error.PatchDataUnavailable; │ │146 + │ │147 + var patch = record.event; │ │148 + patch.title = input.title; │ │149 + patch.tags = input.tags; │ │150 + patch.description = input.description; │ │151 + try evt.consume(.fork, .xit, repo_opts, io, allocator, &fork_repo, evt.events_ref, &.{.{ │ │152 + .id = input.id, │ │153 + .timestamp = input.timestamp, │ │154 + .author = input.author, │ │155 + .event = .{ .patch = patch }, │ │156 + }}); │ │157 + return true; │ │158 } │ │159 │ │160 // merge the selected patch revision into its target branch │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯