╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ──╮ │src/try.zig│ ╰───────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1070 contents: []const []const u8, │ │1071 ) !void { │ │1072 const patch_hex = std.fmt.bytesToHex(patch_id.*, .lower); │ │1073 - const fork_path = try fork.forkPath(allocator, repos_path, &patch_hex); │ │1073 + const fork_path = try fork.forkPath(allocator, users_dir, forker_id, patch_id); │ │1074 defer allocator.free(fork_path); │ │1075 var fork_repo = try rp.Repo(.xit, .{}).open(io, allocator, .{ .path = fork_path, .require_repo_root = true });│ │1076 defer fork_repo.deinit(io, allocator); │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1199 }, │ │1200 }; │ │1201 │ │1202 - const repos_path = try std.fs.path.join(allocator, &.{ server_path, "repos" }); │ │1203 - defer allocator.free(repos_path); │ │1202 + const users_dir = try std.fs.path.join(allocator, &.{ server_path, "users" }); │ │1203 + defer allocator.free(users_dir); │ │1204 const patch_author = evt.CommitAuthor{ .name = "admin", .email = "admin@example.test" }; │ │1205 - var user_repo = (try evt.openUserRepo(io, allocator, repos_path, user_id)) orelse return error.NotFound;│ │1206 - defer user_repo.deinit(io, allocator); │ │1205 var patch_ids: [patch_data.len][evt.event_id_size]u8 = undefined; │ │1206 for (patch_data, 0..) |patch, i| { │ │1207 const timestamp: u64 = @intCast(500 + i * 10); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────╮ │1208 patch_ids[i] = evt.EventWithId.randomId(random); │ │1209 const patch_hex = std.fmt.bytesToHex(patch_ids[i], .lower); │ │1212 - const path = try fork.create(.{}, io, allocator, repos_path, &user_repo, .{│ │1210 + const path = try fork.create(.{}, io, allocator, users_dir, .{ │ │1211 .id = patch_hex, │ │1212 .user_id = user_id.*, │ │1213 .repo_id = repo_id.*, │ ╰─────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1253 } │ │1254 break :blk .{ "patch.txt", contents.len }; │ │1255 }; │ │1258 - try seedPatchRevision(io, allocator, repos_path, &patch_ids[i], patch.title, patch_author, timestamp + 1, random, base_oid, file_path, contents[0..count]); │ │1256 + try seedPatchRevision(io, allocator, users_dir, user_id, &patch_ids[i], patch.title, patch_author, timestamp + 1, random, base_oid, file_path, contents[0..count]);│ │1257 } │ │1258 const status = patch.status orelse continue; │ │1261 - const fork_path = try fork.forkPath(allocator, repos_path, &patch_hex); │ │1262 - defer allocator.free(fork_path); │ │1263 - try pch.publish(.{}, io, allocator, admin_repo, &user_repo, target_repo, fork_path, .{ │ │1259 + try pch.publish(.{}, io, allocator, users_dir, admin_repo, target_repo, .{ │ │1260 .id = patch_hex, │ │1261 .user_id = user_id.*, │ │1262 .repo_id = repo_id.*, │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────╮ │1265 }); │ │1266 │ │1267 if (status == .merged) { │ │1272 - try pch.mergeAndRemoveFork(.{}, io, allocator, repos_path, target_repo, .{│ │1268 + try pch.mergeAndRemoveFork(.{}, io, allocator, users_dir, target_repo, .{ │ │1269 .id = patch_hex, │ │1270 .revision = .source, │ │1271 .author = patch_author, │ ╰────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭──────────────────────────────────────────────────╮ │2019 io: std.Io, │ │2020 moment: evt.AdminDB.HashMap(.read_only),│ │2021 arena: *std.heap.ArenaAllocator, │ │2022 - repos_dir: []const u8, │ │2022 + users_dir: []const u8, │ │2023 user_id: [evt.event_id_size]u8, │ │2024 identity: []const u8, │ │2025 min_role: evt.Repo.Role, │ ╰──────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │2027 const user = (try activeUser(moment, arena, user_id)) orelse return .login_required; │ │2028 │ │2029 const owner_repo = evt.parseOwnerRepoPath(identity) orelse return .repo_not_found; │ │2030 - const repo = (try evt.readRepoByOwnerAndName(io, arena.child_allocator, arena, moment, repos_dir, owner_repo.owner, owner_repo.name)) orelse return .repo_not_found;│ │2030 + const repo = (try evt.readRepoByOwnerAndName(io, arena.child_allocator, arena, moment, users_dir, owner_repo.owner, owner_repo.name)) orelse return .repo_not_found;│ │2031 const role = evt.Repo.roleOf(repo.repo, user_id); │ │2032 // a repo the user can't read doesn't exist to them │ │2033 if (role == .none) return .repo_not_found; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────╮ │2091 // rebuilds pages from the serialized snapshot rather than from disk. │ │2092 io: ?std.Io = null, │ │2093 admin_repo: ?*rp.Repo(.xit, evt.admin_repo_opts) = null, │ │2094 - repos_dir: ?[]const u8 = null, │ │2094 + users_dir: ?[]const u8 = null, │ │2095 // the single on-disk repo this session views, when running in local mode │ │2096 // (haxy invoked with no arguments inside a repo). null on the server paths,│ │2097 // which resolve repos from the admin db instead. │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │2283 // the session's moment predates this input, so read the roles afresh │ │2284 const admin_repo = self.admin_repo orelse return null; │ │2285 const io = self.io orelse return null; │ │2286 - const repos_dir = self.repos_dir orelse return null; │ │2286 + const users_dir = self.users_dir orelse return null; │ │2287 const moment = try evt.currentMoment(evt.admin_repo_opts, admin_repo); │ │2288 - return switch (try authorizeUser(io, moment, self.page_arena, repos_dir, user_id, identity, min_role)) {│ │2288 + return switch (try authorizeUser(io, moment, self.page_arena, users_dir, user_id, identity, min_role)) {│ │2289 .actor => |actor| actor, │ │2290 .login_required, .repo_not_found, .forbidden => null, │ │2291 }; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────╮ │src/ui/Fork.zig│ ╰───────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────╮ │34 │ │35 pub fn init(arena: *std.heap.ArenaAllocator, session: *ui.Session, route: ui.RoutablePage) !Self {│ │36 const io = session.io orelse return error.NotFound; │ │37 - const repos_dir = session.repos_dir orelse return error.NotFound; │ │37 + const users_dir = session.users_dir orelse return error.NotFound; │ │38 const haxy_moment = session.haxy_moment orelse return error.NoMoment; │ │39 const route_fork = route.forkRoute() orelse return error.UnexpectedRoute; │ │40 // the route's identity names the forker and the target repo │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯