╭ changed ────────────╮ │src/search_commit.zig│ ╰─────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────╮ │← previous│ ╰──────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────╮ │147 │ │148 - // the commits that already have a version │ │149 - var existing: std.AutoArrayHashMapUnmanaged(Oid, void) = .empty; │ │148 if (try moment.getCursor(hash.hashInt(repo_opts.hash, index_key))) |index_cursor| {│ │149 const index = try DB.HashMap(.read_only).init(index_cursor); │ │150 var iter = try index.iterator(); │ ╰────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │151 while (try iter.next()) |cursor| { │ │152 const pair = try cursor.readKeyValuePair(); │ │155 - var oid_bytes: [hash.byteLen(repo_opts.hash)]u8 = undefined; │ │156 - if ((try pair.key_cursor.readBytes(&oid_bytes)).len != oid_bytes.len) return error.InvalidCommitIndex;│ │157 - try existing.put(aa, std.fmt.bytesToHex(oid_bytes, .lower), {}); │ │153 + var entry: Entry = undefined; │ │154 + if ((try pair.key_cursor.readBytes(&entry)).len != entry.len) return error.InvalidCommitIndex; │ │155 + const oid = std.fmt.bytesToHex(entry[0..oid_len].*, .lower); │ │156 + try versions.put(aa, oid, std.mem.readInt(u64, entry[oid_len..], .big)); │ │157 } │ │158 } │ │159 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────╮ │181 var missing: std.AutoArrayHashMapUnmanaged(Oid, Work) = .empty;│ │182 for (tips.items) |tip| { │ │183 // a tip that already has a version needs no reading │ │185 - if (existing.contains(tip)) { │ │184 + if (versions.contains(tip)) { │ │185 try wanted.put(aa, tip, {}); │ │186 continue; │ │187 } │ ╰────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │188 var commit = obj.Object(.xit, repo_opts).initCommit(read_state, io, allocator, &tip) catch continue;│ │189 defer commit.deinit(); │ │190 try wanted.put(aa, commit.oid, {}); │ │192 - if (existing.contains(commit.oid)) continue; │ │191 + if (versions.contains(commit.oid)) continue; │ │192 const entry = try missing.getOrPut(aa, commit.oid); │ │193 if (!entry.found_existing) entry.value_ptr.* = .{ │ │194 .oid = commit.oid, │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │195 .timestamp = commit.content.commit.metadata.timestamp, │ │196 .base = null, │ │197 }; │ │199 - if (entry.value_ptr.base == null) entry.value_ptr.base = pushedFrom(repo_opts, updates, &tip, existing);│ │198 + if (entry.value_ptr.base == null) entry.value_ptr.base = movedFrom(repo_opts, moves, &tip, versions); │ │199 } │ │200 │ │201 var head_buffer: [rf.MAX_REF_CONTENT_SIZE]u8 = undefined; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │202 if (rf.readHead(.xit, repo_opts, read_state, io, &head_buffer) catch null) |head| switch (head) { │ │203 .ref => |ref| default_tip = try rf.readRecur(.xit, repo_opts, read_state, io, .{ .ref = .{ .kind = .head, .name = ref.name } }),│ │204 .oid => {}, │ │206 - }; │ │207 - │ │208 - // an entry whose commit is gone can't be walked from, so it isn't a │ │209 - // candidate. │ │210 - const unbased = for (missing.values()) |item| { │ │211 - if (item.base == null) break true; │ │212 - } else false; │ │213 - if (unbased) for (existing.keys()) |oid| { │ │214 - var commit = obj.Object(.xit, repo_opts).initCommit(read_state, io, allocator, &oid) catch continue; │ │215 - defer commit.deinit(); │ │216 - try versions.append(aa, .{ .oid = oid, .timestamp = commit.content.commit.metadata.timestamp }); │ │205 }; │ │206 │ │207 try work.appendSlice(aa, missing.values()); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────╮ │212 } │ │213 }.lessThan); │ │214 │ │227 - for (existing.keys()) |oid| { │ │215 + for (versions.keys()) |oid| { │ │216 if (!wanted.contains(oid)) try gone.append(aa, oid);│ │217 } │ │218 } │ ╰─────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ │221 │ │222 { │ │223 const index_hash = hash.hashInt(repo_opts.hash, index_key); │ │236 - │ │237 - var message: std.ArrayList(u8) = .empty; │ │238 - defer message.deinit(allocator); │ │224 │ │225 for (work.items) |item| { │ │226 const index = try DB.HashMap(.read_write).init(try moment.putCursor(index_hash));│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │242 - const base = item.base orelse nearestVersion(repo_opts.hash, versions.items, default_tip, item.timestamp); │ │227 + const base = item.base orelse nearestVersion(repo_opts.hash, versions, default_tip, item.timestamp); │ │228 │ │244 - var oid_bytes: [hash.byteLen(repo_opts.hash)]u8 = undefined; │ │245 - _ = try std.fmt.hexToBytes(&oid_bytes, &item.oid); │ │246 - const oid_int = hash.bytesToInt(repo_opts.hash, &oid_bytes); │ │247 - try index.putKey(oid_int, .{ .bytes = &oid_bytes }); │ │229 + var entry: Entry = undefined; │ │230 + _ = try std.fmt.hexToBytes(entry[0..oid_len], &item.oid); │ │231 + std.mem.writeInt(u64, entry[oid_len..], item.timestamp, .big); │ │232 + const oid_int = hash.bytesToInt(repo_opts.hash, entry[0..oid_len]); │ │233 + try index.putKey(oid_int, .{ .bytes = &entry }); │ │234 var version_cursor = try index.putCursor(oid_int); │ │235 if (base) |base_oid| { │ │236 const base_cursor = (try index.getCursor(try hash.hexToInt(repo_opts.hash, &base_oid))) orelse return error.InvalidCommitIndex;│ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │237 try version_cursor.write(.{ .slot = base_cursor.slot() }); │ │238 } │ │239 const version = try DB.SortedMap(.read_write).init(version_cursor); │ │254 - │ │255 - var diff_arena = std.heap.ArenaAllocator.init(allocator); │ │256 - defer diff_arena.deinit(); │ │257 - const diff = try commitDiff(repo_opts, state.readOnly(), io, allocator, diff_arena.allocator(), if (base) |*base_oid| base_oid else null, &item.oid, progress_ctx_maybe);│ │240 │ │259 - // the walk is done, so the messages left to read are the total │ │260 - progress.report(repo_opts, io, progress_ctx_maybe, .{ .text = "Indexing commits" }); │ │261 - progress.report(repo_opts, io, progress_ctx_maybe, .{ .start = .{ .kind = .writing_patch, .estimated_total_items = diff.removed.len + diff.added.len } }); │ │262 - for (diff.removed) |commit| { │ │263 - if (progress.cancelled(repo_opts, progress_ctx_maybe)) return error.ClientGone; │ │264 - defer progress.report(repo_opts, io, progress_ctx_maybe, .{ .complete_one = .writing_patch }); │ │265 - const key = try readPosting(repo_opts, state.readOnly(), io, allocator, &message, commit); │ │266 - try srch.remove(DB, version, allocator, &key, message.items); │ │267 - } │ │268 - for (diff.added) |commit| { │ │269 - if (progress.cancelled(repo_opts, progress_ctx_maybe)) return error.ClientGone; │ │270 - defer progress.report(repo_opts, io, progress_ctx_maybe, .{ .complete_one = .writing_patch }); │ │271 - const key = try readPosting(repo_opts, state.readOnly(), io, allocator, &message, commit); │ │272 - try srch.add(DB, version, allocator, &key, message.items); │ │241 + if (base) |*base_oid| { │ │242 + try derive(repo_opts, state.readOnly(), io, allocator, version, base_oid, &item.oid, progress_ctx_maybe); │ │243 + } else { │ │244 + try indexHistory(repo_opts, state.readOnly(), io, allocator, version, &item.oid, progress_ctx_maybe); │ │245 } │ │274 - progress.report(repo_opts, io, progress_ctx_maybe, .{ .end = .writing_patch }); │ │246 │ │276 - try versions.append(aa, .{ .oid = item.oid, .timestamp = item.timestamp }); │ │247 + try versions.put(aa, item.oid, item.timestamp); │ │248 // the next version copies this one's slot, so everything │ │249 // written so far has to be shared rather than mutated │ │250 try state.core.db.freeze(); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯