╭ changed ────╮ │src/patch.zig│ ╰─────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │788 }; │ │789 } │ │790 │ │791 +// queue `oid` and its history on `objects`, which reads from `source`, minus │ │792 +// what `holder` already has. a repo and its forks start as copies of each other, │ │793 +// so walking back to the newest commit `holder` has usually skips nearly all of it. │ │794 +pub fn includeMissing( │ │795 + comptime repo_opts: rp.RepoOpts(.xit), │ │796 + objects: *obj.ObjectIterator(.xit, repo_opts), │ │797 + holder: rp.Repo(.xit, repo_opts).State(.read_only), │ │798 + source: rp.Repo(.xit, repo_opts).State(.read_only), │ │799 + io: std.Io, │ │800 + allocator: std.mem.Allocator, │ │801 + oid: *const [hash.hexLen(repo_opts.hash)]u8, │ │802 +) !void { │ │803 + var held_oid = oid.*; │ │804 + while (true) { │ │805 + var reader_or_err = obj.ObjectReader(.xit, repo_opts).init(holder, io, allocator, &held_oid); │ │806 + if (reader_or_err) |*reader| { │ │807 + reader.deinit(); │ │808 + break; │ │809 + } else |err| switch (err) { │ │810 + error.ObjectNotFound => {}, │ │811 + else => |e| return e, │ │812 + } │ │813 + var commit = try obj.Object(.xit, repo_opts).init(source, io, allocator, &held_oid); │ │814 + defer commit.deinit(); │ │815 + const parent_oids = commit.content.commit.metadata.parent_oids orelse return objects.include(oid);│ │816 + if (parent_oids.len == 0) return objects.include(oid); │ │817 + held_oid = parent_oids[0]; │ │818 + } │ │819 + if (std.mem.eql(u8, &held_oid, oid)) return; │ │820 + try objects.include(oid); │ │821 + try objects.exclude(&held_oid); │ │822 +} │ │823 + │ │824 fn calculateMergeCheck( │ │825 comptime repo_opts: rp.RepoOpts(.xit), │ │826 state: rp.Repo(.xit, repo_opts).State(.read_write), │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │838 const fork_state = rp.Repo(.xit, repo_opts).State(.read_only){ .core = &repo.core, .extra = .{ .moment = &fork_moment } };│ │839 var objects = try obj.ObjectIterator(.xit, repo_opts).init(fork_state, io, allocator, .{ .kind = .all }); │ │840 defer objects.deinit(); │ │808 - try objects.include(&source); │ │809 - try objects.include(&squash); │ │841 + try includeMissing(repo_opts, &objects, state.readOnly(), fork_state, io, allocator, &source); │ │842 + try includeMissing(repo_opts, &objects, state.readOnly(), fork_state, io, allocator, &squash); │ │843 try obj.copyFromObjectIterator(.xit, repo_opts, state, .xit, repo_opts, &objects, io, null); │ │844 } │ │845 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1226 const fork_state = State(.read_only){ .core = &repo.core, .extra = .{ .moment = &fork_repo_moment } }; │ │1227 var objects = try obj.ObjectIterator(.xit, repo_opts).init(fork_state, ctx.io, ctx.allocator, .{ .kind = .all });│ │1228 defer objects.deinit(); │ │1196 - try objects.include(&ctx.selected_oid); │ │1229 + try includeMissing(repo_opts, &objects, state.readOnly(), fork_state, ctx.io, ctx.allocator, &ctx.selected_oid); │ │1230 try obj.copyFromObjectIterator(.xit, repo_opts, state, .xit, repo_opts, &objects, ctx.io, null); │ │1231 } │ │1232 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯