╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ────╮ │src/event.zig│ ╰─────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1239 const record_maybe: ?Grant.Record = if (event_maybe) |event| .{ .event = event, .created_order = event_order, .updated_order = event_order } else null; │ │1240 try Grant.consume(DB, repo_opts.hash, haxy_moment, &current_event_id, record_maybe, &arena, &repo_event_oid); │ │1241 }, │ │1242 + .notify => |event_maybe| { │ │1243 + const record_maybe: ?Notify.Record = if (event_maybe) |event| .{ .event = event, .created_order = event_order, .updated_order = event_order } else null;│ │1244 + try Notify.consume(DB, repo_opts.hash, haxy_moment, &current_event_id, record_maybe, &arena, &repo_event_oid); │ │1245 + }, │ │1246 .discuss => |event_maybe| { │ │1247 const record_maybe: ?Discussion.Record = if (event_maybe) |event| .{ │ │1248 .event = event, │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────╮ │1949 .assign => Assignment.record_map_key, │ │1950 .patchrev => PatchRev.record_map_key, │ │1951 .patch => Patch.record_map_key, │ │1930 - .user, .repo, .fork, .grant => return null, │ │1952 + .user, .repo, .fork, .grant, .notify => return null,│ │1953 }; │ │1954 │ │1955 const DB = EventDB(repo_opts.hash); │ ╰──────────────────────────────────────────────────────────────────╯ ╭ changed ─────────╮ │src/event/User.zig│ ╰──────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │191 arena: *std.heap.ArenaAllocator, │ │192 email: []const u8, │ │193 ) !?Public { │ │194 + const user_id = (try readIdByEmail(DB, hash_kind, haxy_moment, email)) orelse return null; │ │195 + const user_map = try userMap(DB, hash_kind, haxy_moment, &user_id) orelse return null; │ │196 + const record = try evt.read(struct { event: Public }, DB, hash_kind, arena, user_map); │ │197 + return record.event; │ │198 +} │ │199 + │ │200 +// a user's id via the email->user-id index │ │201 +pub fn readIdByEmail( │ │202 + comptime DB: type, │ │203 + comptime hash_kind: hash.HashKind, │ │204 + haxy_moment: DB.HashMap(.read_only), │ │205 + email: []const u8, │ │206 +) !?[evt.event_id_size]u8 { │ │207 const email_to_user_id_cursor = (try haxy_moment.getCursor(hash.hashInt(hash_kind, email_to_user_id_key))) orelse return null;│ │208 const email_to_user_id = try DB.HashMap(.read_only).init(email_to_user_id_cursor); │ │209 const user_id_cursor = (try email_to_user_id.getCursor(hash.hashInt(hash_kind, email))) orelse return null; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────╮ │210 var user_id: [evt.event_id_size]u8 = undefined; │ │211 _ = try user_id_cursor.readBytes(&user_id); │ │199 - const user_map = try userMap(DB, hash_kind, haxy_moment, &user_id) orelse return null;│ │200 - const record = try evt.read(struct { event: Public }, DB, hash_kind, arena, user_map);│ │201 - return record.event; │ │212 + return user_id; │ │213 } │ │214 │ │215 // a user's id via the name->user-id index │ ╰───────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ added ─────────────╮ │src/event/Notify.zig│ ╰────────────────────╯ ╭ changed ──╮ │src/lib.zig│ ╰───────────╯ ╭────────────────────────────────────────────────╮ │2 pub const command = @import("./command.zig");│ │3 pub const main = @import("./main.zig"); │ │4 pub const event = @import("./event.zig"); │ │5 +pub const notify = @import("./notify.zig"); │ │6 pub const push = @import("./push.zig"); │ │7 pub const find = @import("./find.zig"); │ │8 pub const search = @import("./search.zig"); │ ╰────────────────────────────────────────────────╯ ╭ changed ────╮ │src/patch.zig│ ╰─────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 94 const history = try DB.ArrayList(.read_write).init(repo.core.db.rootCursor()); │ │ 95 try history.appendContext(.{ .slot = try history.getSlot(-1) }, Ctx{ .repo = repo, .io = io, .arena = &arena, .id = id, .patch = patch, .expected_patch = expected_patch, .author = author, .checks = &checks, .first_parent = first_parent });│ │ 96 } │ │ 97 - if (host == .server) evt.bumpRepoActivityAt(io, allocator, host.server.users_dir, repo.core.work_path); │ │ 97 + if (host == .server) evt.bumpRepoActivityAt(io, allocator, host.server, repo.core.work_path); │ │ 98 } │ │ 99 } │ │100 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────╮ │885 comptime repo_opts: rp.RepoOpts(.xit), │ │886 io: std.Io, │ │887 allocator: std.mem.Allocator, │ │888 - users_dir: []const u8, │ │888 + server: evt.Host.Server, │ │889 admin_repo: *rp.Repo(.xit, evt.admin_repo_opts),│ │890 target_repo: *rp.Repo(.xit, repo_opts), │ │891 input: PublishInput, │ ╰─────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │895 defer arena.deinit(); │ │896 │ │897 // validate the fork ownership and publishing identity │ │898 - var user_repo = (try evt.openUserRepo(io, allocator, users_dir, &input.user_id)) orelse return error.InvalidPatchDraft; │ │898 + var user_repo = (try evt.openUserRepo(io, allocator, server.users_dir, &input.user_id)) orelse return error.InvalidPatchDraft;│ │899 defer user_repo.deinit(io, allocator); │ │900 const admin_moment = try evt.currentMoment(evt.admin_repo_opts, admin_repo); │ │901 const user_moment = (try evt.userMoment(&user_repo)) orelse return error.InvalidPatchDraft; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │907 !std.mem.eql(u8, user.event.email, input.author.email)) return error.InvalidPatchDraft; │ │908 │ │909 // read the patch staged in the fork │ │910 - const fork_path = try fork.forkPath(arena.allocator(), users_dir, &input.user_id, &patch_id); │ │910 + const fork_path = try fork.forkPath(arena.allocator(), server.users_dir, &input.user_id, &patch_id); │ │911 var fork_repo = rp.Repo(.xit, repo_opts).open(io, allocator, .{ .path = fork_path }) catch return error.PatchDataUnavailable;│ │912 defer fork_repo.deinit(io, allocator); │ │913 const fork_moment = evt.currentMoment(repo_opts, &fork_repo) catch return error.PatchDataUnavailable; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯