╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ─────────╮ │src/event/User.zig│ ╰──────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────╮ │119 if (!std.mem.eql(u8, existing_event.name, event.name)) { │ │120 _ = try name_to_user_id.remove(hash.hashInt(hash_kind, existing_event.name)); │ │121 } │ │122 + if (!std.mem.eql(u8, existing_event.email, event.email)) { │ │123 + _ = try email_to_user_id.remove(hash.hashInt(hash_kind, existing_event.email));│ │124 + } │ │125 │ │126 // any event settles the conflict, since resolving in the ui may │ │127 // keep our own values and so change nothing to detect │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────╮ │140 try evt.upsert(@This(), DB, hash_kind, user, event_to_write); │ │141 │ │142 try name_to_user_id.put(hash.hashInt(hash_kind, event.name), .{ .bytes = event_id }); │ │143 + try email_to_user_id.put(hash.hashInt(hash_kind, event.email), .{ .bytes = event_id });│ │144 │ │145 // first time we've seen this user: add it to the ordered set the users │ │146 // view paginates through. the key embeds the event id, so the set needs │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────╮ │152 try user_id_set.put(&order_key); │ │153 } │ │154 } else { │ │145 - // read the user's name so we can drop its name->id index entry │ │155 + // read the user so we can drop its name and email index entries │ │156 if (try event_id_to_user.getCursor(user_key)) |existing_cursor| { │ │157 const existing_user = try DB.HashMap(.read_only).init(existing_cursor); │ │158 const existing_event = try evt.read(@This(), DB, hash_kind, arena, existing_user);│ ╰───────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │159 _ = try name_to_user_id.remove(hash.hashInt(hash_kind, existing_event.name)); │ │160 + _ = try email_to_user_id.remove(hash.hashInt(hash_kind, existing_event.email)); │ │161 │ │162 // drop it from the ordered set using its recorded creation timestamp │ │163 const user_id_set_cursor = try haxy_moment.putCursor(hash.hashInt(hash_kind, "user-id-set"));│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────╮ │292 try evt.consume(.xit, repo_opts, io, allocator, repo, evt.events_ref, &[_]evt.EventWithId{.{│ │293 .id = std.fmt.bytesToHex(user_id[0..evt.event_id_size].*, .lower), │ │294 .timestamp = @intCast(std.Io.Timestamp.now(io, .real).toSeconds()), │ │295 + .author_email = user.email, │ │296 .event = .{ .user = updated }, │ │297 }}); │ │298 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─────────╮ │src/test/event.zig│ ╰──────────────────╯ ╭─────────────────────────────────────╮ │ 4 const rp = xit.repo; │ │ 5 const rf = xit.ref; │ │ 6 const hash = xit.hash; │ │ 7 + │ │ 8 +const author_email = "user@haxy";│ │ 9 │ │10 test "rebase" { │ │11 const io = std.testing.io; │ ╰─────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │48 const events_to_consume = [_]evt.EventWithId{ │ │49 .{ │ │50 .id = std.fmt.bytesToHex(first_event_id, .lower), │ │51 + .author_email = author_email, │ │52 .event = .{ │ │53 .issue = .{ │ │54 .title = "Login form clears password on validation error",│ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │60 // this event edits the previous one because it has the same id │ │61 .{ │ │62 .id = std.fmt.bytesToHex(first_event_id, .lower), │ │63 + .author_email = author_email, │ │64 .event = .{ │ │65 .issue = .{ │ │66 .title = "Login form clears password on validation error",│ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────╮ │71 }, │ │72 .{ │ │73 .id = std.fmt.bytesToHex(evt.EventWithId.randomId(prng.random()), .lower),│ │74 + .author_email = author_email, │ │75 .event = .{ │ │76 .issue = .{ │ │77 .title = "Search results ignore archived project filter", │ ╰──────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────╮ │82 }, │ │83 .{ │ │84 .id = std.fmt.bytesToHex(evt.EventWithId.randomId(prng.random()), .lower),│ │85 + .author_email = author_email, │ │86 .event = .{ │ │87 .issue = .{ │ │88 .title = "Issue list does not persist selected sort order", │ ╰──────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯