╭ changed ──────────────╮ │src/ui/Repo/Commits.zig│ ╰───────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────────────────────────────────────────────────────────────╮ │13 const Focus = xitui.focus.Focus; │ │14 │ │15 const SubHeader = @import("SubHeader.zig"); │ │16 - │ │17 -const RefOrOid = ui.RoutablePage.RefOrOid; │ │18 -const hex_len = ui.ResolvedRefOrOid.hex_len; │ │16 │ │17 // how many commits a page shows before a "next" link appears.│ │18 const page_size = 20; │ ╰──────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │43 identity: []const u8, │ │44 // the resolved ref/oid this log walks from (the default branch when the route│ │45 // didn't name one), so the page can canonicalize its url to it. │ │49 -ref_or_oid: RefOrOid, │ │46 +ref_or_oid: ui.RoutablePage.RefOrOid, │ │47 ref_or_oid_value: []const u8, │ │48 commits: []const Commit, │ │49 // the first oid of the next page, or null when this is the last page. │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────╮ │58 session: *ui.Session, │ │59 event_id: *const [evt.event_id_size]u8, │ │60 identity: []const u8, │ │64 - requested_ref_or_oid: ?RefOrOid, │ │61 + requested_ref_or_oid: ?ui.RoutablePage.RefOrOid, │ │62 requested_value: []const u8, │ │63 // the hunk index the selected commit's (the first one, the walk root) diff│ │64 // window starts at; 0 is the first window. moved by "next"/"previous". │ ╰───────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 75 const repo_path = try std.fs.path.join(aa, &.{ repos_dir, &hex }); │ │ 76 │ │ 77 // walk the log with the arena's backing allocator (transient; the commits │ │ 81 - // we keep are duped into the page arena so they outlive it). │ │ 78 + // we keep are duped into the page arena so they outlive it). AnyRepo opens │ │ 79 + // both sha1 and sha256 repos. │ │ 80 const gpa = arena.child_allocator; │ │ 83 - var repo = rp.Repo(.xit, .{}).open(io, gpa, .{ .path = repo_path }) catch return emptyResult(aa, identity, requested_ref_or_oid orelse .branch, requested_value); │ │ 84 - defer repo.deinit(io, gpa); │ │ 81 + var any_repo = rp.AnyRepo(.xit, .{}).open(io, gpa, .{ .path = repo_path }) catch return emptyResult(aa, identity, requested_ref_or_oid orelse .branch, requested_value);│ │ 82 + defer any_repo.deinit(io, gpa); │ │ 83 + │ │ 84 + return switch (any_repo) { │ │ 85 + inline else => |*repo| collect(repo.self_repo_opts, arena, repo, io, gpa, identity, requested_ref_or_oid, requested_value, after), │ │ 86 + }; │ │ 87 +} │ │ 88 + │ │ 89 +// walk the log for an opened repo. generic over the repo's hash kind so the │ │ 90 +// oid buffers and diff types it threads through match the repo's opts. │ │ 91 +fn collect( │ │ 92 + comptime repo_opts: rp.RepoOpts(.xit), │ │ 93 + arena: *std.heap.ArenaAllocator, │ │ 94 + repo: *rp.Repo(.xit, repo_opts), │ │ 95 + io: std.Io, │ │ 96 + gpa: std.mem.Allocator, │ │ 97 + identity: []const u8, │ │ 98 + requested_ref_or_oid: ?ui.RoutablePage.RefOrOid, │ │ 99 + requested_value: []const u8, │ │100 + after: usize, │ │101 +) !Self { │ │102 + const aa = arena.allocator(); │ │103 + const hex_len = ui.ResolvedRefOrOid(repo_opts).hex_len; │ │104 │ │105 // resolve the requested ref (or the default branch) to the commit oid to │ │106 // walk from. an explicitly named ref that doesn't resolve is a bad url │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │107 // (NotFound -> 404); the default-branch path falls through to empty. │ │ 89 - const resolved = (try ui.ResolvedRefOrOid.init(&repo, io, aa, requested_ref_or_oid, requested_value)) orelse { │ │108 + const resolved = (try ui.ResolvedRefOrOid(repo_opts).init(repo, io, aa, requested_ref_or_oid, requested_value)) orelse {│ │109 if (requested_ref_or_oid != null) return error.NotFound; │ │110 return emptyResult(aa, identity, .branch, requested_value); │ │111 }; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │151 // the selected commit (the first, == start_oid) shows the window the │ │152 // url asks for; the rest show their first window. │ │153 const start = if (i == 0) after else 0; │ │135 - const rendered = renderCommitDiff(io, gpa, aa, &repo, oid, start, diff_page) catch │ │154 + const rendered = renderCommitDiff(repo_opts, io, gpa, aa, repo, oid, start, diff_page) catch│ │155 RenderedDiff{ .hunks = &.{}, .has_prev = false, .has_more = false }; │ │156 commit.hunks = rendered.hunks; │ │157 commit.window_start = start; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │171 } │ │172 │ │173 // an empty listing pinned to a ref, for the wasm / no-repo / unresolved paths. │ │155 -fn emptyResult(aa: std.mem.Allocator, identity: []const u8, ref_or_oid: RefOrOid, value: []const u8) !Self { │ │174 +fn emptyResult(aa: std.mem.Allocator, identity: []const u8, ref_or_oid: ui.RoutablePage.RefOrOid, value: []const u8) !Self {│ │175 return .{ │ │176 .identity = try aa.dupe(u8, identity), │ │177 .ref_or_oid = ref_or_oid, │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────╮ │191 // render the window [start, start+len) of a commit's diff against its first│ │192 // parent into `arena`-owned hunks. has_prev/has_more flag adjacent windows.│ │193 fn renderCommitDiff( │ │194 + comptime repo_opts: rp.RepoOpts(.xit), │ │195 io: std.Io, │ │196 gpa: std.mem.Allocator, │ │197 arena: std.mem.Allocator, │ ╰─────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────╮ │178 - repo: *rp.Repo(.xit, .{}), │ │179 - oid: [xit.hash.hexLen(.sha1)]u8, │ │198 + repo: *rp.Repo(.xit, repo_opts), │ │199 + oid: [xit.hash.hexLen(repo_opts.hash)]u8,│ │200 start: usize, │ │201 len: usize, │ │202 ) !RenderedDiff { │ ╰──────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────╮ │203 const empty = RenderedDiff{ .hunks = &.{}, .has_prev = false, .has_more = false }; │ │204 │ │205 // load the commit so we can diff it against its first parent. │ │186 - var start_oids = [_][xit.hash.hexLen(.sha1)]u8{oid}; │ │206 + var start_oids = [_][xit.hash.hexLen(repo_opts.hash)]u8{oid}; │ │207 var commit_iter = repo.log(io, gpa, start_oids[0..1]) catch return empty; │ │208 defer commit_iter.deinit(); │ │209 const commit_object = (commit_iter.next(gpa) catch return empty) orelse return empty;│ ╰──────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯