╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ────╮ │src/patch.zig│ ╰─────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1035 │ │1036 // validate the draft ownership and editing identity │ │1037 { │ │1038 + var user_repo = (try evt.openUserRepo(io, allocator, users_dir, &input.user_id)) orelse return false; │ │1039 + defer user_repo.deinit(io, allocator); │ │1040 const admin_moment = try evt.currentMoment(evt.admin_repo_opts, admin_repo); │ │ 972 - const user_moment = (try evt.userMoment(user_repo)) orelse return false; │ │1041 + const user_moment = (try evt.userMoment(&user_repo)) orelse return false; │ │1042 const fork_record = (try evt.Fork.readById(evt.UserDB, evt.user_repo_opts.hash, user_moment, &arena, &patch_id)) orelse return false;│ │1043 if (fork_record.event.stage != .draft) return false; │ │1044 if (fork_record.removed or !std.mem.eql(u8, fork_record.event.repo_id, &input.repo_id)) return error.InvalidPatchDraft; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1049 } │ │1050 │ │1051 // read the draft patch from its fork │ │1052 + const fork_path = try fork.forkPath(arena.allocator(), users_dir, &input.user_id, &patch_id); │ │1053 var fork_repo = rp.Repo(.xit, repo_opts).open(io, allocator, .{ .path = fork_path, .require_repo_root = true }) catch return error.PatchDataUnavailable;│ │1054 defer fork_repo.deinit(io, allocator); │ │1055 const fork_moment = evt.currentMoment(repo_opts, &fork_repo) catch return error.PatchDataUnavailable; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────╮ │1079 comptime repo_opts: rp.RepoOpts(.xit), │ │1080 io: std.Io, │ │1081 allocator: std.mem.Allocator, │ │1012 - repo_root_path: []const u8, │ │1082 + users_dir: []const u8, │ │1083 target_repo: *rp.Repo(.xit, repo_opts),│ │1084 input: MergeInput, │ │1085 ) !void { │ ╰─────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1105 const target_ref = rf.Ref{ .kind = .head, .name = patch_record.event.target_branch }; │ │1106 │ │1107 // open the fork │ │1038 - const fork_path = try fork.forkPath(arena.allocator(), repo_root_path, &input.id); │ │1039 - var fork_repo_maybe: ?rp.Repo(.xit, repo_opts) = if (patch_record.event.source_branch != null) null else rp.Repo(.xit, repo_opts).open(io, allocator, .{ .path = fork_path, .require_repo_root = true }) catch return error.PatchDataUnavailable;│ │1108 + var fork_repo_maybe: ?rp.Repo(.xit, repo_opts) = if (patch_record.event.source_branch != null) null else blk: { │ │1109 + var config = try target_repo.listConfig(io, allocator); │ │1110 + defer config.deinit(); │ │1111 + const forker_id = (try fork.readForkerId(&config.sections, &patch_id)) orelse return error.PatchDataUnavailable; │ │1112 + const fork_path = try fork.forkPath(arena.allocator(), users_dir, &forker_id, &patch_id); │ │1113 + break :blk rp.Repo(.xit, repo_opts).open(io, allocator, .{ .path = fork_path, .require_repo_root = true }) catch return error.PatchDataUnavailable; │ │1114 + }; │ │1115 defer if (fork_repo_maybe) |*repo| repo.deinit(io, allocator); │ │1116 │ │1117 // select the commit and merge identity │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────╮ │1242 comptime repo_opts: rp.RepoOpts(.xit), │ │1243 io: std.Io, │ │1244 allocator: std.mem.Allocator, │ │1170 - repo_root_path: []const u8, │ │1245 + users_dir: []const u8, │ │1246 target_repo: *rp.Repo(.xit, repo_opts),│ │1247 input: MergeInput, │ │1248 ) !void { │ ╰─────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │1174 - try merge(repo_opts, io, allocator, repo_root_path, target_repo, input);│ │1249 + try merge(repo_opts, io, allocator, users_dir, target_repo, input); │ │1250 var arena = std.heap.ArenaAllocator.init(allocator); │ │1251 defer arena.deinit(); │ │1252 │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1253 // remove fork data only for patches backed by a fork │ │1179 - const record = (try evt.readFromRepo(evt.Patch, .xit, repo_opts, io, allocator, &arena, target_repo, &try evt.parseEventId(&input.id))) orelse return error.InvalidPatch;│ │1254 + const patch_id = try evt.parseEventId(&input.id); │ │1255 + const record = (try evt.readFromRepo(evt.Patch, .xit, repo_opts, io, allocator, &arena, target_repo, &patch_id)) orelse return error.InvalidPatch; │ │1256 if (record.event.source_branch != null) return; │ │1181 - // a fork already cleaned up has no repo left │ │1182 - const fork_path = try fork.forkPath(arena.allocator(), repo_root_path, &input.id); │ │1183 - const forker_id = (try fork.readForkerId(io, allocator, fork_path)) orelse return; │ │1184 - var user_repo = (try evt.openUserRepo(io, allocator, repo_root_path, &forker_id)) orelse return error.InvalidPatchDraft; │ │1185 - defer user_repo.deinit(io, allocator); │ │1186 - try fork.remove(io, allocator, repo_root_path, &user_repo, &input.id, input.author); │ │1257 + // a patch from another instance has no fork here │ │1258 + const forker_id = blk: { │ │1259 + var config = try target_repo.listConfig(io, allocator); │ │1260 + defer config.deinit(); │ │1261 + break :blk (try fork.readForkerId(&config.sections, &patch_id)) orelse return; │ │1262 + }; │ │1263 + try fork.remove(io, allocator, users_dir, &forker_id, &input.id, input.author); │ │1264 } │ │1265 │ │1266 fn commitAuthor(line: []const u8) !evt.CommitAuthor { │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────╮ │1279 moment: *evt.EventDB(repo_opts.hash).HashMap(.read_write),│ │1280 io: std.Io, │ │1281 allocator: std.mem.Allocator, │ │1205 - repo_root_path: []const u8, │ │1282 + users_dir: []const u8, │ │1283 patch_id: *const [evt.event_id_size]u8, │ │1284 matched_oid: *const [hash.hexLen(repo_opts.hash)]u8, │ │1285 before_oid: *const [hash.hexLen(repo_opts.hash)]u8, │ ╰────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1289 defer arena.deinit(); │ │1290 │ │1291 // identify which selected revision was merged by the client. │ │1215 - const patch_hex = std.fmt.bytesToHex(patch_id.*, .lower); │ │1216 - const fork_path = try fork.forkPath(arena.allocator(), repo_root_path, &patch_hex); │ │1292 const events = try evt.currentMomentFromRepoMoment(repo_opts.hash, moment.readOnly()); │ │1293 const record = (try evt.Patch.readById(evt.EventDB(repo_opts.hash), repo_opts.hash, events, &arena, patch_id)) orelse return;│ │1294 const selected = record.event.revision orelse return; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1295 const revision: evt.Patch.MergeRevision = if (std.mem.eql(u8, matched_oid, selected.source_oid)) .source else if (std.mem.eql(u8, matched_oid, selected.squash_oid)) .squash else return; │ │1296 │ │1297 // open the fork when the revision is not stored in the target repository. │ │1223 - 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 });│ │1298 + var fork_repo_maybe: ?rp.Repo(.xit, repo_opts) = if (record.event.source_branch != null) null else blk: { │ │1299 + var config = try xit.config.Config(.xit, repo_opts).init(state.readOnly(), io, allocator); │ │1300 + defer config.deinit(); │ │1301 + const forker_id = (try fork.readForkerId(&config.sections, patch_id)) orelse return error.PatchDataUnavailable; │ │1302 + const fork_path = try fork.forkPath(arena.allocator(), users_dir, &forker_id, patch_id); │ │1303 + break :blk try rp.Repo(.xit, repo_opts).open(io, allocator, .{ .path = fork_path, .require_repo_root = true }); │ │1304 + }; │ │1305 defer if (fork_repo_maybe) |*repo| repo.deinit(io, allocator); │ │1306 │ │1307 // import the revision and record the client-side merge. │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯