╭ changed ────╮ │src/event.zig│ ╰─────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │139 } │ │140 var haxy_moments = try DB.HashMap(.read_write).init(haxy_moments_cursor); │ │141 │ │142 - var repo_event_iter = try RepoEventIterator(repo_opts).init(state.readOnly(), io, allocator, haxy_moments.readOnly(), ref);│ │143 - defer repo_event_iter.deinit(io, allocator); │ │142 + var commit_iter = try CommitIterator(repo_opts).init(state.readOnly(), io, allocator, haxy_moments.readOnly(), ref); │ │143 + defer commit_iter.deinit(io, allocator); │ │144 │ │145 // if there are no events to process, look at the oid at HEAD and update │ │146 // the last_object_id to point to it. this is important in situations │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │147 // where we do a merge and then force-push to remove the merge. see the │ │148 // merge test for an example. │ │149 - if (repo_event_iter.newest_object_id == null) { │ │149 + if (commit_iter.newest_object_id == null) { │ │150 const head_oid_hex = (try rf.readRecur(.xit, repo_opts, state.readOnly(), io, .{ .ref = ref })) orelse return error.OidNotFound;│ │151 var head_oid: [hash.byteLen(repo_opts.hash)]u8 = undefined; │ │152 _ = try std.fmt.hexToBytes(&head_oid, &head_oid_hex); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────╮ │168 // we consumed. if it isn't, then we know the haxy state needs to be reverted. │ │169 if (last_object_id_maybe) |*last_object_id| { │ │170 var is_rebased = false; │ │171 - const newest_object_id = repo_event_iter.newest_object_id orelse return error.OidNotFound;│ │171 + const newest_object_id = commit_iter.newest_object_id orelse return error.OidNotFound; │ │172 │ │173 _ = mrg.getDescendent( │ │174 .xit, │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │184 }; │ │185 │ │186 if (is_rebased) { │ │187 - const oldest_object_id = repo_event_iter.oldest_object_id orelse return error.OidNotFound; │ │187 + const oldest_object_id = commit_iter.oldest_object_id orelse return error.OidNotFound; │ │188 var oldest_object = try obj.Object(.xit, repo_opts, .full).init(state.readOnly(), io, allocator, &std.fmt.bytesToHex(oldest_object_id, .lower));│ │189 defer oldest_object.deinit(); │ │190 │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │229 } │ │230 } │ │231 │ │232 - while (try repo_event_iter.next()) |repo_event_oid| { │ │232 + while (try commit_iter.next()) |repo_event_oid| { │ │233 var commit_object = try obj.Object(.xit, repo_opts, .full).init(state.readOnly(), io, allocator, &std.fmt.bytesToHex(repo_event_oid, .lower));│ │234 defer commit_object.deinit(); │ │235 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────╮ │589 return true; │ │590 } │ │591 │ │592 -pub fn RepoEventIterator(comptime repo_opts: rp.RepoOpts(.xit)) type {│ │592 +// │ │593 +// CommitIterator │ │594 +// │ │595 +// differs from xit's ObjectIterator in a few ways: │ │596 +// │ │597 +// 1. iterates parents first, rather than children first │ │598 +// 2. `next` only returns the object id, not the full Object │ │599 +// 3. stores its temporary state in a file on disk to avoid OOMs │ │600 +// │ │601 + │ │602 +pub fn CommitIterator(comptime repo_opts: rp.RepoOpts(.xit)) type { │ │603 return struct { │ │594 - const Self = @This(); │ │604 const DB = rp.Repo(.xit, repo_opts).DB; │ │605 const db_name = "haxy-repo-events.db"; │ │606 │ ╰───────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │624 state: rp.Repo(.xit, repo_opts).State(.read_only), │ │625 io: std.Io, │ │626 allocator: std.mem.Allocator, │ │618 - haxy_moments: DB.HashMap(.read_only), │ │627 + consumed_object_ids: DB.HashMap(.read_only), │ │628 ref: rf.Ref, │ │620 - ) !Self { │ │629 + ) !CommitIterator(repo_opts) { │ │630 const db_file = try state.core.repo_dir.createFile(io, db_name, .{ .truncate = true, .lock = .exclusive, .read = true });│ │631 errdefer { │ │632 db_file.close(io); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │654 const ready_queue_cursor = try map.putCursor(hash.hashInt(repo_opts.hash, "ready-queue"));│ │655 const ready_queue = try DB.ArrayList(.read_write).init(ready_queue_cursor); │ │656 │ │648 - var self = Self{ │ │657 + var self = CommitIterator(repo_opts){ │ │658 .repo_dir = state.core.repo_dir, │ │659 .db_file = db_file, │ │660 .db = db_ptr, │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │667 }; │ │668 errdefer self.deinit(io, allocator); │ │669 │ │661 - try self.collect(state, io, allocator, haxy_moments, ref); │ │670 + try self.collect(state, io, allocator, consumed_object_ids, ref);│ │671 + │ │672 return self; │ │673 } │ │674 │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │665 - pub fn deinit(self: *Self, io: std.Io, allocator: std.mem.Allocator) void { │ │675 + pub fn deinit(self: *CommitIterator(repo_opts), io: std.Io, allocator: std.mem.Allocator) void {│ │676 self.db_file.close(io); │ │677 self.db.core.memory.buffer.deinit(); │ │678 allocator.destroy(self.db.core.memory.buffer); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯