╭ changed ──╮ │src/try.zig│ ╰───────────╯ ╭────────────────────────────────────────────────────────────────────────╮ │1126 tags: []const u8, │ │1127 status: ?evt.Patch.StatusKind, │ │1128 alpha_edit: ?ScatterEdit = null, │ │1129 + // based behind master, so merging it makes a merge commit│ │1130 + behind_master: bool = false, │ │1131 }{ │ │1132 .{ │ │1133 .title = "Draft a faster dependency scanner", │ ╰────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1140 .description = "Delete the compatibility loader now that the replacement format has shipped and the migration warning has been available for a full release.",│ │1141 .tags = "cleanup config", │ │1142 .status = .merged, │ │1143 + .behind_master = true, │ │1144 }, │ │1145 .{ │ │1146 .title = "Cache parsed manifests between commands", │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1197 defer arena.deinit(); │ │1198 const aa = arena.allocator(); │ │1199 var base_oid = (try target_repo.readRef(io, .{ .kind = .head, .name = "master" })) orelse return error.NotFound; │ │1197 - var contents: [3][]const u8 = undefined; │ │1198 - const file_path: []const u8, const count: usize = if (patch.alpha_edit) |edit| blk: { │ │1200 + if (patch.alpha_edit != null or patch.behind_master) { │ │1201 // v30 precedes the last scatter commit, even after the sample merge │ │1202 const tag_oid = (try target_repo.readRef(io, .{ .kind = .tag, .name = "v30" })) orelse return error.NotFound;│ │1203 var moment = try target_repo.core.latestMoment(); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1208 .tag => |value| value.target, │ │1209 else => return error.InvalidObject, │ │1210 }; │ │1211 + } │ │1212 + var contents: [3][]const u8 = undefined; │ │1213 + const file_path: []const u8, const count: usize = if (patch.alpha_edit) |edit| blk: {│ │1214 // rev 29 first changes line 4; edit that line or the one above it │ │1215 contents[0] = try scatterContent(aa, 0, 28, edit); │ │1216 break :blk .{ "src/alpha.txt", 1 }; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │200 │ │201 // the "key:value" segments of a url tail, collected in any order │ │202 const Params = struct { │ │203 - const ParamKey = enum { start, line, branch, tag, object, base, patchrev, theirs, find, search, from, moment }; │ │203 + const ParamKey = enum { start, line, branch, tag, object, base, patchrev, theirs, find, search, from, moment, merge };│ │204 │ │205 // a branch:/tag:/object: param; the value stays url-encoded │ │206 const RefParam = struct { kind: RefOrOid, value: []const u8 }; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────╮ │288 const search_seg = @tagName(Params.ParamKey.search) ++ ":";│ │289 const from_seg = @tagName(Params.ParamKey.from) ++ ":"; │ │290 const base_seg = @tagName(Params.ParamKey.base) ++ ":"; │ │291 + const merge_seg = @tagName(Params.ParamKey.merge) ++ ":"; │ │292 const theirs_seg = @tagName(Params.ParamKey.theirs) ++ ":";│ │293 const issue_seg = "issue:"; │ │294 const patch_seg = "patch:"; │ ╰────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────╮ │388 search: Array(search_route_max_len) = .{}, │ │389 // the commit the list starts at ("" = the ref's own commit). │ │390 from: Array(ref_route_max_len) = .{}, │ │391 + // a merge commit whose brought-in commits the page lists, resolved to an│ │392 + // object and base on load. set alone. │ │393 + merge: Array(ref_route_max_len) = .{}, │ │394 // what the pane shows for the commit the log walks from. │ │395 content: Content = .{ .diff = .{} }, │ │396 │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────╮ │491 forkCommitsRoute(f.identity, f.id, value, start, path) │ │492 else │ │493 null, │ │494 + }; │ │495 + } │ │496 + │ │497 + // fork commits routes carry no base, so only a repo can list a merge's commits│ │498 + pub fn commitsMergeRoute(self: RepoLocation, oid: []const u8) ?RoutablePage { │ │499 + return switch (self) { │ │500 + .repo => |repo_identity| repoCommitsMergeRoute(repo_identity, oid), │ │501 + .fork => null, │ │502 }; │ │503 } │ │504 │ ╰────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │678 } }; │ │679 } │ │680 │ │681 + pub fn repoCommitsMergeRoute(identity: []const u8, oid: []const u8) ?RoutablePage { │ │682 + return .{ .repo_commits = .{ │ │683 + .name = Array(repo_identity_max_len).from(identity) orelse return null, │ │684 + .merge = Array(ref_route_max_len).from(oid) orelse return null, │ │685 + } }; │ │686 + } │ │687 + │ │688 pub fn repoDiffRoute(identity: []const u8, ref_or_oid: ?RefOrOid, value: []const u8, start: usize, path: []const u8, base_oid: []const u8) ?RoutablePage {│ │689 if (base_oid.len == 0 or (ref_or_oid == null and value.len != 0)) return null; │ │690 return .{ .repo_diff = .{ │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1050 if (c.base_oid.len != 0) try out.writer.print("/" ++ base_seg ++ "{s}", .{c.base_oid.slice()});│ │1051 if (c.search.len != 0) try out.writer.print("/" ++ search_seg ++ "{s}", .{c.search.slice()}); │ │1052 if (c.from.len != 0) try out.writer.print("/" ++ from_seg ++ "{s}", .{c.from.slice()}); │ │1053 + if (c.merge.len != 0) try out.writer.print("/" ++ merge_seg ++ "{s}", .{c.merge.slice()}); │ │1054 switch (c.content) { │ │1055 .diff => |d| { │ │1056 if (d.start != 0) try out.writer.print("/" ++ start_seg ++ "{d}", .{d.start}); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯