╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ────────────╮ │src/search_commit.zig│ ╰─────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │208 if (item.base == null) break true; │ │209 } else false; │ │210 if (unbased) for (existing.keys()) |oid| { │ │173 - var commit = obj.Object(.xit, repo_opts).initCommit(state, io, allocator, &oid) catch continue; │ │211 + var commit = obj.Object(.xit, repo_opts).initCommit(read_state, io, allocator, &oid) catch continue;│ │212 defer commit.deinit(); │ │213 try versions.append(aa, .{ .oid = oid, .timestamp = commit.content.commit.metadata.timestamp }); │ │214 }; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │225 if (!wanted.contains(oid)) try gone.append(aa, oid); │ │226 } │ │227 } │ │190 - │ │191 - if (work.items.len == 0 and gone.items.len == 0) return; │ │192 - │ │193 - const Save = struct { │ │194 - core: *Repo.Core, │ │195 - io: std.Io, │ │196 - allocator: std.mem.Allocator, │ │197 - work: []const Work, │ │198 - gone: []const Oid, │ │199 - aa: std.mem.Allocator, │ │200 - default_tip: ?Oid, │ │201 - versions: *std.ArrayList(Tip), │ │228 │ │203 - pub fn run(ctx: @This(), cursor: *DB.Cursor(.read_write)) !void { │ │204 - var moment = try DB.HashMap(.read_write).init(cursor.*); │ │205 - const state = Repo.State(.read_write){ .core = ctx.core, .extra = .{ .moment = &moment } }; │ │206 - const index_hash = hash.hashInt(repo_opts.hash, index_key); │ │229 + if (work.items.len == 0 and gone.items.len == 0) return false; │ │230 │ │208 - var message: std.ArrayList(u8) = .empty; │ │209 - defer message.deinit(ctx.allocator); │ │231 + { │ │232 + const index_hash = hash.hashInt(repo_opts.hash, index_key); │ │233 │ │211 - for (ctx.work) |item| { │ │212 - const index = try DB.HashMap(.read_write).init(try moment.putCursor(index_hash)); │ │213 - const base = item.base orelse nearestVersion(repo_opts.hash, ctx.versions.items, ctx.default_tip, item.timestamp); │ │234 + var message: std.ArrayList(u8) = .empty; │ │235 + defer message.deinit(allocator); │ │236 │ │215 - var oid_bytes: [hash.byteLen(repo_opts.hash)]u8 = undefined; │ │216 - _ = try std.fmt.hexToBytes(&oid_bytes, &item.oid); │ │217 - const oid_int = hash.bytesToInt(repo_opts.hash, &oid_bytes); │ │218 - try index.putKey(oid_int, .{ .bytes = &oid_bytes }); │ │219 - var version_cursor = try index.putCursor(oid_int); │ │220 - if (base) |base_oid| { │ │221 - const base_cursor = (try index.getCursor(try hash.hexToInt(repo_opts.hash, &base_oid))) orelse return error.InvalidCommitIndex; │ │222 - try version_cursor.write(.{ .slot = base_cursor.slot() }); │ │223 - } │ │224 - const version = try DB.SortedMap(.read_write).init(version_cursor); │ │237 + for (work.items) |item| { │ │238 + const index = try DB.HashMap(.read_write).init(try moment.putCursor(index_hash)); │ │239 + const base = item.base orelse nearestVersion(repo_opts.hash, versions.items, default_tip, item.timestamp); │ │240 │ │226 - var diff_arena = std.heap.ArenaAllocator.init(ctx.allocator); │ │227 - defer diff_arena.deinit(); │ │228 - const diff = try commitDiff(repo_opts, state.readOnly(), ctx.io, ctx.allocator, diff_arena.allocator(), if (base) |*base_oid| base_oid else null, &item.oid);│ │229 - for (diff.removed) |commit| { │ │230 - const key = try readPosting(repo_opts, state.readOnly(), ctx.io, ctx.allocator, &message, commit); │ │231 - try srch.remove(DB, version, ctx.allocator, &key, message.items); │ │232 - } │ │233 - for (diff.added) |commit| { │ │234 - const key = try readPosting(repo_opts, state.readOnly(), ctx.io, ctx.allocator, &message, commit); │ │235 - try srch.add(DB, version, ctx.allocator, &key, message.items); │ │236 - } │ │241 + var oid_bytes: [hash.byteLen(repo_opts.hash)]u8 = undefined; │ │242 + _ = try std.fmt.hexToBytes(&oid_bytes, &item.oid); │ │243 + const oid_int = hash.bytesToInt(repo_opts.hash, &oid_bytes); │ │244 + try index.putKey(oid_int, .{ .bytes = &oid_bytes }); │ │245 + var version_cursor = try index.putCursor(oid_int); │ │246 + if (base) |base_oid| { │ │247 + const base_cursor = (try index.getCursor(try hash.hexToInt(repo_opts.hash, &base_oid))) orelse return error.InvalidCommitIndex; │ │248 + try version_cursor.write(.{ .slot = base_cursor.slot() }); │ │249 + } │ │250 + const version = try DB.SortedMap(.read_write).init(version_cursor); │ │251 │ │238 - try ctx.versions.append(ctx.aa, .{ .oid = item.oid, .timestamp = item.timestamp }); │ │239 - // the next version copies this one's slot, so everything │ │240 - // written so far has to be shared rather than mutated │ │241 - try ctx.core.db.freeze(); │ │252 + var diff_arena = std.heap.ArenaAllocator.init(allocator); │ │253 + defer diff_arena.deinit(); │ │254 + const diff = try commitDiff(repo_opts, state.readOnly(), io, allocator, diff_arena.allocator(), if (base) |*base_oid| base_oid else null, &item.oid); │ │255 + for (diff.removed) |commit| { │ │256 + const key = try readPosting(repo_opts, state.readOnly(), io, allocator, &message, commit); │ │257 + try srch.remove(DB, version, allocator, &key, message.items); │ │258 } │ │259 + for (diff.added) |commit| { │ │260 + const key = try readPosting(repo_opts, state.readOnly(), io, allocator, &message, commit); │ │261 + try srch.add(DB, version, allocator, &key, message.items); │ │262 + } │ │263 │ │244 - // removing last keeps a tip that is going away available as a base │ │245 - const index = try DB.HashMap(.read_write).init(try moment.putCursor(index_hash)); │ │246 - for (ctx.gone) |oid| _ = try index.remove(try hash.hexToInt(repo_opts.hash, &oid)); │ │264 + try versions.append(aa, .{ .oid = item.oid, .timestamp = item.timestamp }); │ │265 + // the next version copies this one's slot, so everything │ │266 + // written so far has to be shared rather than mutated │ │267 + try state.core.db.freeze(); │ │268 } │ │248 - }; │ │269 │ │250 - const history = try DB.ArrayList(.read_write).init(repo.core.db.rootCursor()); │ │251 - try history.appendContext(.{ .slot = try history.getSlot(-1) }, Save{ │ │252 - .core = &repo.core, │ │253 - .io = io, │ │254 - .allocator = allocator, │ │255 - .work = work.items, │ │256 - .gone = gone.items, │ │257 - .aa = aa, │ │258 - .default_tip = default_tip, │ │259 - .versions = &versions, │ │260 - }); │ │270 + // removing last keeps a tip that is going away available as a base │ │271 + const index = try DB.HashMap(.read_write).init(try moment.putCursor(index_hash)); │ │272 + for (gone.items) |oid| _ = try index.remove(try hash.hexToInt(repo_opts.hash, &oid)); │ │273 + } │ │274 + return true; │ │275 } │ │276 │ │277 // the version a tip committed at `timestamp` derives from when no push names │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──╮ │src/try.zig│ ╰───────────╯ ╭───────────────────────────────────────╮ │13 const obj = xit.object; │ │14 const ui = hx.ui; │ │15 const find = hx.find; │ │16 -const cms = hx.search_commit; │ │16 +const srch_cmmt = hx.search_commit;│ │17 const fork = hx.fork; │ │18 const pch = hx.pch; │ │19 const push = hx.push; │ ╰───────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────╮ │811 try template_repo.addConfig(io, allocator, .{ .name = "core.bare", .value = "true" });│ │812 // fixtures commit directly, so index the ref tips by hand │ │813 try find.refresh(.{}, io, allocator, &template_repo); │ │814 - try cms.refresh(.{}, io, allocator, &template_repo, null); │ │814 + try srch_cmmt.refresh(.{}, io, allocator, &template_repo, null); │ │815 // clear history only after indexing has written its transactions. │ │816 { │ │817 const moment = try evt.currentMoment(.{}, &template_repo); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────────────╮ │src/ui/Repo/Commits.zig│ ╰───────────────────────╯ ╭─────────────────────────────────────────────────────────╮ │ 6 const rp = xit.repo; │ │ 7 const Diff = @import("Diff.zig"); │ │ 8 const obj = xit.object; │ │ 9 -const cms = @import("../../search_commit.zig"); │ │ 9 +const srch_cmmt = @import("../../search_commit.zig");│ │10 const srch = @import("../../search.zig"); │ │11 const xitui = xit.xitui; │ │12 const wgt = xitui.widget; │ ╰─────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │147 // bounded by a base, whose version also covers the commits before it. │ │148 if (comptime repo_kind == .xit) index: { │ │149 if (location != .repo or resolved.ref_or_oid == .object or base_oid.len != 0) break :index;│ │150 - const index = (try cms.lookup(repo_opts, moment, &resolved.oid)) orelse break :index; │ │150 + const index = (try srch_cmmt.lookup(repo_opts, moment, &resolved.oid)) orelse break :index;│ │151 search_available = true; │ │152 const text = query orelse break :index; │ │153 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │155 if (from.len != 0) { │ │156 var start = obj.Object(.xit, repo_opts).initCommit(state, io, gpa, from[0..hex_len]) catch return error.NotFound;│ │157 defer start.deinit(); │ │158 - const key = try cms.docKey(repo_opts.hash, start.content.commit.metadata.timestamp, &start.oid); │ │158 + const key = try srch_cmmt.docKey(repo_opts.hash, start.content.commit.metadata.timestamp, &start.oid); │ │159 results.seek(&key); │ │160 } │ │161 while (try results.next()) |key| { │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────╮ │162 - const oid = try cms.keyOid(repo_opts.hash, key); │ │162 + const oid = try srch_cmmt.keyOid(repo_opts.hash, key);│ │163 if (count == page_size) { │ │164 next_start = try aa.dupe(u8, &oid); │ │165 break; │ ╰───────────────────────────────────────────────────────────────────────╯ ╭ changed ───────────╮ │src/ui/Repo/Undo.zig│ ╰────────────────────╯ ╭─────────────────────────────────────────────────────────╮ │ 5 const pch = @import("../../patch.zig"); │ │ 6 const push = @import("../../push.zig"); │ │ 7 const fork = @import("../../fork.zig"); │ │ 8 +const find = @import("../../find.zig"); │ │ 9 +const srch_cmmt = @import("../../search_commit.zig");│ │10 const inp = @import("../input.zig"); │ │11 const xit = @import("xit"); │ │12 const rp = xit.repo; │ ╰─────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │115 if (std.mem.eql(u8, record.action_kind, evt.merge_undo_action)) return .{ .action = "merge events", .description = "merged the events ref from a remote" }; │ │116 if (std.mem.eql(u8, record.action_kind, pch.merge_undo_action)) return .{ .action = "merge patch", .description = "merged a patch into its target branch" }; │ │117 if (std.mem.eql(u8, record.action_kind, fork.undo_action)) return .{ .action = "fork", .description = "created a fork to draft a patch in" }; │ │118 + if (std.mem.eql(u8, record.action_kind, pch.mergeability_undo_action)) return .{ .action = "mergeability", .description = "rechecked whether the open patches still merge cleanly" };│ │119 + if (std.mem.eql(u8, record.action_kind, find.undo_action)) return .{ .action = "file index", .description = "reindexed the files on a branch" }; │ │120 + if (std.mem.eql(u8, record.action_kind, srch_cmmt.undo_action)) return .{ .action = "commit index", .description = "reindexed the commits on a branch" }; │ │121 if (std.mem.eql(u8, record.action_kind, push.undo_action)) { │ │122 // a push consumes the events it carried in its own transaction │ │123 var buttons: std.ArrayList(DetailButton) = .empty; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯