╭ changed ──────────────╮ │src/ui/Repo/Commits.zig│ ╰───────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────╮ │← previous│ ╰──────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────╮ │125 } │ │126 │ │150 - // collect this page's commit metadata, plus a peek at the one after it (its │ │151 - // oid is the next page's start). the diff for each is rendered afterward, so│ │152 - // the log iterator is closed before opening per-commit diff iterators. │ │127 + // collect this page's commits, plus a peek at the one after it (its oid is │ │128 + // the next page's start). │ │129 var buf: [page_size]Commit = undefined; │ │154 - var oids: [page_size][hex_len]u8 = undefined; │ │130 var count: usize = 0; │ │131 var next_start: ?[]const u8 = null; │ │132 var search_available = false; │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │170 } │ │171 var commit_object = try obj.Object(.xit, repo_opts).initCommit(state, io, gpa, &oid); │ │172 defer commit_object.deinit(); │ │198 - @memcpy(&oids[count], &oid); │ │199 - buf[count] = try commitEntry(repo_kind, repo_opts, arena, repo, io, gpa, admin_moment, &commit_object, root_message and count == 0);│ │173 + buf[count] = try commitEntry(repo_kind, repo_opts, arena, repo, io, gpa, admin_moment, &commit_object, message and count == 0); │ │174 count += 1; │ │175 } │ │176 searched = true; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │182 var start_oid = resolved.oid; │ │183 if (from.len != 0) @memcpy(&start_oid, from); │ │184 │ │211 - var iter = repo.log(io, gpa, .{ .start_oids = &.{start_oid}, .first_parent = true }) catch return emptyResult(aa, handle, resolved.ref_or_oid, resolved.value, content, base_oid);│ │185 + var iter = repo.log(io, gpa, .{ .start_oids = &.{start_oid}, .first_parent = true }) catch return emptyResult(aa, handle, resolved.ref_or_oid, resolved.value, base_oid); │ │186 defer iter.deinit(); │ │187 while (try iter.next(gpa)) |commit_object| { │ │188 defer commit_object.deinit(); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │192 next_start = try aa.dupe(u8, &commit_object.oid); │ │193 break; │ │194 } │ │221 - @memcpy(&oids[count], &commit_object.oid); │ │222 - buf[count] = try commitEntry(repo_kind, repo_opts, arena, repo, io, gpa, admin_moment, commit_object, root_message and count == 0); │ │195 + buf[count] = try commitEntry(repo_kind, repo_opts, arena, repo, io, gpa, admin_moment, commit_object, message and count == 0); │ │196 count += 1; │ │224 - } │ │225 - } │ │226 - │ │227 - // render each commit's diff (best effort: a failed diff leaves it empty). │ │228 - // the diff machinery isn't wasm-clean and the wasm client never runs it (it │ │229 - // renders from the snapshot), so gate it out of the wasm build. │ │230 - if (!builtin.cpu.arch.isWasm()) { │ │231 - for (buf[0..count], oids[0..count], 0..) |*commit, oid, i| { │ │232 - if (root_message and i == 0) continue; │ │233 - // the walk root shows the window the url asks for and its filter; │ │234 - // the rest show their first window, unfiltered. │ │235 - const window_start = if (i == 0) root_start else 0; │ │236 - commit.window = renderCommitDiff(repo_kind, repo_opts, io, gpa, aa, repo, oid, window_start, if (i == 0) root_path else "") catch .{ .start = window_start };│ │197 } │ │198 } │ │199 │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────╮ │211 } else null, │ │212 .commits = try aa.dupe(Commit, buf[0..count]),│ │213 .next_start = next_start, │ │254 - .content = try pageContent(aa, content), │ │214 + .message = message, │ │215 .search = query, │ │216 .search_available = search_available, │ │217 .default_branch = default_branch, │ ╰───────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────╮ │218 }; │ │219 } │ │220 │ │261 -// one commit's row: its message, author and stats. the diff window is rendered│ │262 -// afterward, once the log iterator is closed. │ │221 +// one commit's row: its message, author and stats. │ │222 fn commitEntry( │ │223 comptime repo_kind: rp.RepoKind, │ │224 comptime repo_opts: rp.RepoOpts(repo_kind), │ ╰────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │235 const text, const truncated = try readMessage(repo_kind, repo_opts, aa, commit_object, full_message); │ │236 return .{ │ │237 .oid = try aa.dupe(u8, &commit_object.oid), │ │238 + .parent_oid = if (md.firstParent()) |parent| try aa.dupe(u8, parent) else "0" ** xit.hash.hexLen(repo_opts.hash),│ │239 .date = try formatDate(aa, md.timestamp), │ │240 .message = text, │ │241 .message_truncated = truncated, │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │285 } │ │286 │ │287 // an empty listing pinned to a ref, for the wasm / no-repo / unresolved paths. │ │328 -pub fn emptyResult(aa: std.mem.Allocator, handle: ui.RepoHandle, ref_or_oid: ui.RoutablePage.RefOrOid, value: []const u8, content: ui.RoutablePage.RepoCommitsRoute.Content, base_oid: []const u8) !Self {│ │288 +pub fn emptyResult(aa: std.mem.Allocator, handle: ui.RepoHandle, ref_or_oid: ui.RoutablePage.RefOrOid, value: []const u8, base_oid: []const u8) !Self { │ │289 return .{ │ │290 .handle = try handle.dupe(aa), │ │291 .ref_or_oid = ref_or_oid, │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────╮ │294 .commit_count = null, │ │295 .commits = &.{}, │ │296 .next_start = null, │ │337 - .content = try pageContent(aa, content),│ │297 }; │ │298 } │ │299 │ ╰─────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │341 -// the page's content for a route's, duped into `aa`. the diff window doesn't │ │342 -// carry over: each commit holds the one its pane shows as `window.start`. │ │343 -fn pageContent(aa: std.mem.Allocator, content: ui.RoutablePage.RepoCommitsRoute.Content) !Content {│ │344 - return switch (content) { │ │345 - .diff => |d| .{ .diff = .{ .path = try aa.dupe(u8, d.path.slice()) } }, │ │346 - .message => .message, │ │347 - }; │ │348 -} │ │349 - │ │350 -// render the window [start, start+len) of a commit's diff against its first │ │351 -// parent into `arena`-owned hunks. start/has_more identify adjacent windows. │ │352 -// a non-empty `path` filters to that file, so the window indexes its hunks. │ │353 -fn renderCommitDiff( │ │354 - comptime repo_kind: rp.RepoKind, │ │355 - comptime repo_opts: rp.RepoOpts(repo_kind), │ │356 - io: std.Io, │ │357 - gpa: std.mem.Allocator, │ │358 - arena: std.mem.Allocator, │ │359 - repo: *rp.Repo(repo_kind, repo_opts), │ │360 - oid: [xit.hash.hexLen(repo_opts.hash)]u8, │ │361 - start: usize, │ │362 - path: []const u8, │ │363 -) !Diff.Window { │ │364 - const empty = Diff.Window{ .start = start }; │ │365 - │ │366 - // load the commit so we can diff it against its first parent. │ │367 - var commit_iter = repo.log(io, gpa, .{ .start_oids = &.{oid} }) catch return empty; │ │368 - defer commit_iter.deinit(); │ │369 - const commit_object = (commit_iter.next(gpa) catch return empty) orelse return empty; │ │370 - defer commit_object.deinit(); │ │371 - │ │372 - const parent_maybe = commit_object.content.commit.metadata.firstParent(); │ │373 - │ │374 - return Diff.render(repo_kind, repo_opts, io, gpa, arena, repo, parent_maybe, oid, start, path);│ │375 -} │ │376 - │ │300 // "YYYY-MM-DD" for a unix timestamp. │ │301 fn formatDate(arena: std.mem.Allocator, timestamp: u64) ![]const u8 { │ │302 const epoch_secs = std.time.epoch.EpochSeconds{ .secs = timestamp }; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯