╭ changed ───────────╮ │src/ui/Repo/Undo.zig│ ╰────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 97 if (std.mem.eql(u8, record.action, evt.merge_undo_action)) return .{ .action = "merge events", .description = "merged the events ref from a remote" };│ │ 98 if (!std.mem.eql(u8, record.action, evt.undo_action)) return null; │ │ 99 │ │100 - const description = "updated the event database"; │ │101 - const count = try momentEventCount(opts, moment) orelse return .{ .action = "events", .description = description }; │ │100 + const count = try momentEventCount(opts, moment) orelse return .{ .action = "events", .description = "updated the event database" }; │ │101 + // a transaction that consumed only merge commits indexed no events of its own │ │102 + if (count == 0) return .{ .action = "events", .description = "merged the event history" }; │ │103 │ │104 // the page reads the transaction's own moment, so the url names the │ │105 // transaction rather than the state it produced │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │107 const route = ui.RoutablePage.repoEventsRoute(identity, .active, null, "", history_index) orelse return error.RouteTooLong;│ │108 return .{ │ │109 .action = try std.fmt.allocPrint(aa, "events ({d})", .{count}), │ │109 - .description = description, │ │110 + .description = "updated the event database", │ │111 .events = .{ │ │112 .label = try std.fmt.allocPrint(aa, "view events ({d})", .{count}), │ │113 .link = try std.fmt.allocPrint(aa, "a:{s}", .{try route.toUrl(arena)}), │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │115 }; │ │116 } │ │117 │ │117 -// how many events the transaction's moment wrote, or null when it wrote none │ │118 +// how many events the transaction's moment wrote: zero when it named a moment │ │119 +// but indexed nothing, null when its state cannot be read at all │ │120 fn momentEventCount(comptime opts: rp.RepoOpts(.xit), moment: rp.Repo(.xit, opts).DB.HashMap(.read_only)) !?u64 {│ │121 const DB = rp.Repo(.xit, opts).DB; │ │122 const haxy_moment = evt.currentMomentFromRepoMoment(opts.hash, moment) catch return null; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │123 const index_cursor = try haxy_moment.getCursor(hash.hashInt(opts.hash, evt.moment_index_key)) orelse return null;│ │122 - const ids = try evt.momentEventIds(DB, opts.hash, haxy_moment, try index_cursor.readUint()) orelse return null; │ │124 + const ids = try evt.momentEventIds(DB, opts.hash, haxy_moment, try index_cursor.readUint()) orelse return 0; │ │125 return try ids.count(); │ │126 } │ │127 │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯