╭ changed ───────────────╮ │src/test/event/admin.zig│ ╰────────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────╮ │← previous│ ╰──────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │181 const repo_map = try Repo.DB.HashMap(.read_only).init(repo_cursor); │ │175 - const repo_event = try evt.read(evt.Repo.Record, Repo.DB, repo_opts.hash, &arena, repo_map); │ │176 - try std.testing.expect(!repo_event.removed); │ │182 + const repo_record = try evt.read(evt.Repo.Record, Repo.DB, repo_opts.hash, &arena, repo_map); │ │183 + try std.testing.expect(!repo_record.removed); │ │184 │ │178 - const user_id_to_repo_id_set_cursor = try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, "user-id->repo-id-set")) orelse return error.NotFound;│ │179 - const user_id_to_repo_id_set = try Repo.DB.HashMap(.read_only).init(user_id_to_repo_id_set_cursor); │ │180 - const user_repos_cursor = try user_id_to_repo_id_set.getCursor(hash.hashInt(repo_opts.hash, &user_event_id)) orelse return error.NotFound; │ │185 + const user_repos_cursor = try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, evt.Repo.active_id_set_key)) orelse return error.NotFound; │ │186 const user_repos = try Repo.DB.SortedSet(.read_only).init(user_repos_cursor); │ │187 try std.testing.expectEqual(1, try user_repos.count()); │ │188 } │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │213 const user_map = try Repo.DB.HashMap(.read_only).init(user_cursor); │ │214 const user_event = try evt.read(evt.User.Record, Repo.DB, repo_opts.hash, &arena, user_map); │ │215 try std.testing.expect(user_event.removed); │ │211 - │ │212 - // removing the user removes their active repos too │ │213 - const event_id_to_repo_cursor = try haxy_moment.getCursor(hash.hashInt(repo_opts.hash, "event-id->repo")) orelse return error.NotFound;│ │214 - const event_id_to_repo = try Repo.DB.HashMap(.read_only).init(event_id_to_repo_cursor); │ │215 - const repo_cursor = try event_id_to_repo.getCursor(hash.hashInt(repo_opts.hash, &repo_event_id)) orelse return error.NotFound; │ │216 - const repo_map = try Repo.DB.HashMap(.read_only).init(repo_cursor); │ │217 - const repo_event = try evt.read(evt.Repo.Record, Repo.DB, repo_opts.hash, &arena, repo_map); │ │218 - try std.testing.expect(repo_event.removed); │ │216 } │ │217 } │ │218 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────╮ │227 │ │228 const repo_opts: rp.RepoOpts(.xit) = .{ .is_test = true }; │ │229 const Repo = rp.Repo(.xit, repo_opts); │ │233 - var repo = try Repo.init(io, allocator, .{ .path = temp_path }); │ │230 + const admin_path = try std.fs.path.join(allocator, &.{ temp_path, "admin" });│ │231 + defer allocator.free(admin_path); │ │232 + var admin = try Repo.init(io, allocator, .{ .path = admin_path }); │ │233 + defer admin.deinit(io, allocator); │ │234 + const user_path = try std.fs.path.join(allocator, &.{ temp_path, "user" }); │ │235 + defer allocator.free(user_path); │ │236 + var repo = try Repo.init(io, allocator, .{ .path = user_path }); │ │237 defer repo.deinit(io, allocator); │ │238 │ │239 var arena = std.heap.ArenaAllocator.init(allocator); │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │268 } │ │269 }; │ │270 │ │268 - // one user, then four repos in creation order with deliberately skewed │ │269 - // timestamps │ │271 + // one user in the admin repo, then four repos in creation order with │ │272 + // deliberately skewed timestamps in the user's repo │ │273 + try evt.consume(.server, .admin, .xit, repo_opts, io, allocator, &admin, evt.events_ref, &.{ │ │274 + .{ .id = std.fmt.bytesToHex(user_id, .lower), .author = author, .timestamp = 100, .event = .{ .user = .{ .name = "alice", .email = "alice@example.test", .password_hash = pw } } },│ │275 + }); │ │276 const events = [_]evt.EventWithId{ │ │271 - .{ .id = std.fmt.bytesToHex(user_id, .lower), .author = author, .timestamp = 100, .event = .{ .user = .{ .name = "alice", .email = "alice@example.test", .password_hash = pw } } },│ │277 .{ .id = std.fmt.bytesToHex(repo_ids[0], .lower), .author = author, .timestamp = 10_000, .event = .{ .repo = .{ .user_id = &user_id, .name = "repo0", .description = "d0" } } }, │ │278 .{ .id = std.fmt.bytesToHex(repo_ids[1], .lower), .author = author, .timestamp = 10, .event = .{ .repo = .{ .user_id = &user_id, .name = "repo1", .description = "d1" } } }, │ │279 .{ .id = std.fmt.bytesToHex(repo_ids[2], .lower), .author = author, .timestamp = 5_000, .event = .{ .repo = .{ .user_id = &user_id, .name = "repo2", .description = "d2" } } }, │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │280 .{ .id = std.fmt.bytesToHex(repo_ids[3], .lower), .author = author, .timestamp = 20, .event = .{ .repo = .{ .user_id = &user_id, .name = "repo3", .description = "d3" } } },│ │281 }; │ │277 - try evt.consume(.server, .admin, .xit, repo_opts, io, allocator, &repo, evt.events_ref, &events); │ │282 + try evt.consume(.server, .user, .xit, repo_opts, io, allocator, &repo, evt.events_ref, &events); │ │283 │ │284 { │ │285 const moment = try evt.currentMoment(repo_opts, &repo); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │286 try Check.order(Repo.DB, repo_opts.hash, moment, &.{ &repo_ids[3], &repo_ids[2], &repo_ids[1], &repo_ids[0] }); │ │287 │ │288 // the single user shows up in its own ordered set │ │284 - const ucur = try moment.getCursor(hash.hashInt(repo_opts.hash, "user-id-set")) orelse return error.NotFound; │ │289 + const admin_moment = try evt.currentMoment(repo_opts, &admin); │ │290 + const ucur = try admin_moment.getCursor(hash.hashInt(repo_opts.hash, "user-id-set")) orelse return error.NotFound;│ │291 const uset = try Repo.DB.SortedSet(.read_only).init(ucur); │ │292 try std.testing.expectEqual(1, try uset.count()); │ │293 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │294 │ │295 // removing repo1 retains its place in the canonical order │ │290 - try evt.consume(.server, .admin, .xit, repo_opts, io, allocator, &repo, evt.events_ref, &[_]evt.EventWithId{ │ │296 + try evt.consume(.server, .user, .xit, repo_opts, io, allocator, &repo, evt.events_ref, &[_]evt.EventWithId{ │ │297 .{ .id = std.fmt.bytesToHex(repo_ids[1], .lower), .author = author, .timestamp = 200, .event = .{ .repo = null } },│ │298 }); │ │299 { │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │302 } │ │303 │ │304 // update repo0 at a later timestamp -> keeps its original place │ │299 - try evt.consume(.server, .admin, .xit, repo_opts, io, allocator, &repo, evt.events_ref, &[_]evt.EventWithId{ │ │305 + try evt.consume(.server, .user, .xit, repo_opts, io, allocator, &repo, evt.events_ref, &[_]evt.EventWithId{ │ │306 .{ .id = std.fmt.bytesToHex(repo_ids[0], .lower), .author = author, .timestamp = 300, .event = .{ .repo = .{ .user_id = &user_id, .name = "repo0", .description = "updated" } } },│ │307 }); │ │308 { │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │353 .password_hash = "", │ │354 } }, │ │355 }, │ │356 + }); │ │357 + const user_repo_path = try evt.userRepoPath(allocator, repos_dir, &user_id); │ │358 + defer allocator.free(user_repo_path); │ │359 + var user_repo = try evt.initUserRepo(io, allocator, user_repo_path); │ │360 + defer user_repo.deinit(io, allocator); │ │361 + try evt.consume(.server, .user, .xit, evt.user_repo_opts, io, allocator, &user_repo, evt.events_ref, &.{│ │362 .{ │ │363 .id = std.fmt.bytesToHex(repo_id, .lower), │ │364 .timestamp = 1, │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────╮ │383 try target.add(io, allocator, &.{"README"}); │ │384 _ = try target.commit(io, allocator, .{ .message = "initial" }); │ │385 │ │374 - const draft_path = try fork.create(fork_repo_opts, io, allocator, repos_dir, &admin, .{ │ │386 + const draft_path = try fork.create(fork_repo_opts, io, allocator, repos_dir, &user_repo, .{│ │387 .target_branch = "master", │ │388 .id = fork_id_hex, │ │389 .user_id = user_id, │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯