╭ changed ──────╮ │src/ui/Fork.zig│ ╰───────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │135 const files_find: []const u8 = switch (route) { │ │136 .fork_files => |*f| f.find.slice(), │ │137 else => "", │ │138 - }; │ │139 - const commits_content: ui.RoutablePage.RepoCommitsRoute.Content = switch (route) { │ │140 - .fork_commits => |c| c.content, │ │141 - else => .{ .diff = .{} }, │ │138 }; │ │139 + const commits_message = route == .fork_commits and route.fork_commits.message; │ │140 const files = try Files.init(.xit, repo_opts, arena, fork_repo, io, arena.child_allocator, handle, requested_ref, requested_value, files_path, files_line, files_find); │ │144 - var commits = try Commits.init(.xit, repo_opts, arena, fork_repo, io, arena.child_allocator, haxy_moment, handle, requested_ref, requested_value, commits_content, &commits_base_oid, "", "");│ │141 + var commits = try Commits.init(.xit, repo_opts, arena, fork_repo, io, arena.child_allocator, haxy_moment, handle, requested_ref, requested_value, commits_message, &commits_base_oid, "", "");│ │142 commits.commit_count = if (newest_revision) |revision| revision.record.commit_count else 0; │ │143 const diff_start: usize = switch (route) { │ │144 .fork_diff => |d| d.start, │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │147 const diff_path = switch (route) { │ │148 .fork_diff => |*d| try aa.dupe(u8, d.path.slice()), │ │149 else => "", │ │150 + }; │ │151 + // a named commit's diff is against the route's base (all zeros for │ │152 + // none), else the diff is the whole patch's │ │153 + const diff_oid: []const u8, const diff_base_oid: []const u8 = switch (route) { │ │154 + .fork_diff => |*d| .{ try aa.dupe(u8, d.oid.slice()), try aa.dupe(u8, d.base_oid.slice()) }, │ │155 + else => .{ "", "" }, │ │156 }; │ │157 + const diff_base: ?@TypeOf(fork_oid), const diff_head: @TypeOf(fork_oid) = if (diff_oid.len == 0) .{ commits_base_oid, fork_oid } else named: {│ │158 + evt.PatchRev.validateOid(repo_opts.hash, diff_oid) catch return error.NotFound; │ │159 + evt.PatchRev.validateOid(repo_opts.hash, diff_base_oid) catch return error.NotFound; │ │160 + break :named .{ if (std.mem.allEqual(u8, diff_base_oid, '0')) null else diff_base_oid[0..fork_oid.len].*, diff_oid[0..fork_oid.len].* }; │ │161 + }; │ │162 │ │163 return .{ │ │164 .header = try Header.init(arena, target_record.event.name, identity.owner, &id_hex, requested_value), │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │166 .commits = commits, │ │167 .patch = patch_data, │ │168 .diff = .{ │ │161 - .route = .{ .fork = .{ .identity = try aa.dupe(u8, identity.identity), .id = try aa.dupe(u8, &id_hex) } }, │ │169 + .route = .{ .fork = .{ .identity = try aa.dupe(u8, identity.identity), .id = try aa.dupe(u8, &id_hex), .oid = diff_oid, .base_oid = diff_base_oid } }, │ │170 .path = diff_path, │ │163 - .window = try Diff.render(.xit, repo_opts, io, arena.child_allocator, aa, fork_repo, &commits_base_oid, fork_oid, diff_start, diff_path), │ │171 + .window = try Diff.render(.xit, repo_opts, io, arena.child_allocator, aa, fork_repo, if (diff_base) |*base| base else null, diff_head, diff_start, diff_path),│ │172 }, │ │173 .auth = Auth.init(), │ │174 .quit = Quit.init(), │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯