╭ changed ──────╮ │src/ui/Repo.zig│ ╰───────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭───────────────────────────────────────────────────────────────────────────────╮ │20 pub const Auth = @import("./Auth.zig"); │ │21 pub const Quit = @import("./Quit.zig"); │ │22 │ │23 -const Array = ui.RoutablePage.Array(ui.RoutablePage.repo_route_max_len); │ │23 +const Array = ui.RoutablePage.Array(ui.RoutablePage.repo_identity_max_len);│ │24 │ │25 header: Header, │ │26 repo: evt.Repo, │ ╰───────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────╮ │33 quit: Quit, │ │34 // the full files route this page renders, mirrored into current_page when │ │35 // the files tab is selected. │ │36 -route_name: Array, │ │36 +route_name: ui.RoutablePage.RepoFilesRoute, │ │37 // the commits route this page renders ("owner/name/commits[/<oid>]"), mirrored│ │38 // when the commits tab is selected. │ │39 -commits_route_name: Array, │ │39 +commits_route_name: ui.RoutablePage.RepoCommitsRoute, │ │40 // "owner/name" alone, mirrored when the settings/auth tab is selected. │ │41 identity: Array, │ │42 │ ╰───────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────╮ │50 const DB = evt.AdminDB; │ │51 const hash_kind = evt.admin_repo_opts.hash; │ │52 │ │53 - // every repo route's stored string starts with "owner/name"; the files and│ │54 - // commits routes additionally encode a ref/oid (files also a directory). │ │53 + // every repo route stores its identity as "owner/name" (or elides it in │ │54 + // local mode); files and commits carry their remaining fields directly. │ │55 const name_str: []const u8 = switch (route) { │ │56 - .repo_files, .repo_settings, .repo_auth => |n| n.slice(), │ │57 - .repo_commits => |c| c.slice(), │ │56 + .repo_files => |f| f.name.slice(), │ │57 + .repo_commits => |c| c.name.slice(), │ │58 + .repo_settings, .repo_auth => |n| n.slice(), │ │59 .repo_refs => |r| r.name.slice(), │ │60 .repo_issues => |i| i.name.slice(), │ │61 else => return error.UnexpectedRoute, │ ╰───────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │62 }; │ │62 - const rf = ui.RoutablePage.RepoFiles.parse(name_str) orelse return error.NotFound; │ │63 - const tag = std.meta.activeTag(route); │ │64 - │ │63 + const repo_identity = ui.RoutablePage.RepoIdentity.parse(name_str) orelse return error.NotFound;│ │64 // the files and commits tabs share one ref/oid: whichever the incoming route │ │65 // names (it rides on the route's target tab), or the default branch when │ │66 // neither tab is targeted. building both views at it keeps switching tabs │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │67 // (even by key, without a reload) on the same ref. a null ref means the │ │68 // default branch (Files/Commits.init resolve it). the directory and the diff │ │69 // window only apply to their own tab. │ │71 - const commits_ref = if (tag == .repo_commits) ui.RoutablePage.repoCommitsRef(name_str) else ui.RoutablePage.CommitsRef{ .ref_or_oid = null, .value = "", .start = 0 };│ │72 - const requested_ref_or_oid: ?ui.RoutablePage.RefOrOid = switch (tag) { │ │73 - .repo_files => rf.ref_kind, │ │74 - .repo_commits => commits_ref.ref_or_oid, │ │70 + const requested_ref_or_oid: ?ui.RoutablePage.RefOrOid = switch (route) { │ │71 + .repo_files => |f| f.ref_kind, │ │72 + .repo_commits => |c| c.ref_or_oid, │ │73 else => null, │ │74 }; │ │77 - const requested_ref_value: []const u8 = switch (tag) { │ │78 - .repo_files => rf.ref_value, │ │79 - .repo_commits => commits_ref.value, │ │75 + const requested_ref_value: []const u8 = switch (route) { │ │76 + .repo_files => |f| f.ref_value.slice(), │ │77 + .repo_commits => |c| c.value.slice(), │ │78 else => "", │ │79 }; │ │82 - const files_dir = if (tag == .repo_files) rf.dir else ""; │ │83 - // 0 for non-files routes, whose tails parse as the bare root │ │84 - const files_start = rf.start; │ │80 + const files_dir = switch (route) { │ │81 + .repo_files => |f| f.path.slice(), │ │82 + else => "", │ │83 + }; │ │84 + const files_start = switch (route) { │ │85 + .repo_files => |f| f.start, │ │86 + else => 0, │ │87 + }; │ │88 // the hunk the commits view's selected commit's diff window starts at. │ │86 - const commits_start = commits_ref.start; │ │89 + const commits_start = switch (route) { │ │90 + .repo_commits => |c| c.start, │ │91 + else => 0, │ │92 + }; │ │93 // the refs tab windows one column at a time: `refs_from` (a url-encoded │ │94 // ref name) roots `refs_kind`'s column, the other stays at its first window. │ │95 const refs_kind: ui.RoutablePage.RefKind = switch (route) { │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │134 owner_name = ""; │ │135 } else { │ │136 const haxy_moment = session.haxy_moment orelse return error.NoMoment; │ │131 - const found = (try evt.Repo.readByOwnerAndName(DB, hash_kind, haxy_moment, arena, rf.owner, rf.name)) orelse return error.NotFound; │ │137 + const found = (try evt.Repo.readByOwnerAndName(DB, hash_kind, haxy_moment, arena, repo_identity.owner, repo_identity.name)) orelse return error.NotFound;│ │138 repo = found.repo; │ │139 │ │140 // resolve the creating user so the header can show their name to the left │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │172 const is_local = session.local != null; │ │173 if (is_local) try evt.syncLocalEvents(repo_kind, opened.self_repo_opts, io, gpa, opened); │ │174 break :blk .{ │ │169 - try Files.init(repo_kind, opened.self_repo_opts, arena, opened, io, gpa, rf.identity, requested_ref_or_oid, requested_ref_value, files_dir, files_start), │ │170 - try Commits.init(repo_kind, opened.self_repo_opts, arena, opened, io, gpa, rf.identity, requested_ref_or_oid, requested_ref_value, commits_start), │ │171 - try Refs.init(repo_kind, opened.self_repo_opts, arena, opened, io, gpa, rf.identity, refs_kind, refs_from), │ │172 - try Issues.init(repo_kind, opened.self_repo_opts, arena, opened, io, is_local, rf.identity, issues_tag, issues_selected, issues_view), │ │175 + try Files.init(repo_kind, opened.self_repo_opts, arena, opened, io, gpa, repo_identity.identity, requested_ref_or_oid, requested_ref_value, files_dir, files_start),│ │176 + try Commits.init(repo_kind, opened.self_repo_opts, arena, opened, io, gpa, repo_identity.identity, requested_ref_or_oid, requested_ref_value, commits_start), │ │177 + try Refs.init(repo_kind, opened.self_repo_opts, arena, opened, io, gpa, repo_identity.identity, refs_kind, refs_from), │ │178 + try Issues.init(repo_kind, opened.self_repo_opts, arena, opened, io, is_local, repo_identity.identity, issues_tag, issues_selected, issues_view), │ │179 }; │ │180 }, │ │181 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │184 } │ │185 const aa = arena.allocator(); │ │186 break :blk .{ │ │181 - try Files.emptyResult(aa, rf.identity, requested_ref_or_oid orelse .branch, requested_ref_value, files_dir), │ │182 - try Commits.emptyResult(aa, rf.identity, requested_ref_or_oid orelse .branch, requested_ref_value), │ │183 - try Refs.emptyResult(arena, rf.identity, refs_kind, refs_from), │ │184 - try Issues.emptyResult(aa, rf.identity, issues_tag, issues_selected, issues_view), │ │187 + try Files.emptyResult(aa, repo_identity.identity, requested_ref_or_oid orelse .branch, requested_ref_value, files_dir),│ │188 + try Commits.emptyResult(aa, repo_identity.identity, requested_ref_or_oid orelse .branch, requested_ref_value), │ │189 + try Refs.emptyResult(arena, repo_identity.identity, refs_kind, refs_from), │ │190 + try Issues.emptyResult(aa, repo_identity.identity, issues_tag, issues_selected, issues_view), │ │191 }; │ │192 }; │ │193 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │199 // the content window only applies to a selected file, so the bare │ │200 // directory route drops it. │ │201 const files_route_start = if (files.selected_file != null) files_start else 0; │ │196 - const route_name = (ui.RoutablePage.repoFilesRoute(rf.identity, files.ref_or_oid, files.ref_or_oid_value, files_path, files_route_start) orelse return error.NotFound).repo_files; │ │197 - const commits_route_name = (ui.RoutablePage.repoCommitsRoute(rf.identity, commits.ref_or_oid, commits.ref_or_oid_value, commits_start) orelse return error.NotFound).repo_commits; │ │202 + const route_name = (ui.RoutablePage.repoFilesRoute(repo_identity.identity, files.ref_or_oid, files.ref_or_oid_value, files_path, files_route_start) orelse return error.NotFound).repo_files;│ │203 + const commits_route_name = (ui.RoutablePage.repoCommitsRoute(repo_identity.identity, commits.ref_or_oid, commits.ref_or_oid_value, commits_start) orelse return error.NotFound).repo_commits;│ │204 │ │205 return .{ │ │206 // files and commits resolve the same ref, so either's serves the header, │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────╮ │216 .quit = Quit.init(), │ │217 .route_name = route_name, │ │218 .commits_route_name = commits_route_name, │ │213 - .identity = Array.from(rf.identity) orelse return error.NotFound, │ │219 + .identity = Array.from(repo_identity.identity) orelse return error.NotFound,│ │220 }; │ │221 } │ │222 │ ╰─────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯