╭ changed ────────────╮ │src/ui/Repo/Files.zig│ ╰─────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │40 loaded: bool = false, │ │41 }; │ │42 │ │43 -// "owner/name", so the view can build /repo/owner/name/files/... links. │ │44 -identity: []const u8, │ │43 +// where links and clone commands for this repository are rooted. │ │44 +location: ui.RoutablePage.RepoLocation, │ │45 // the resolved ref this listing is read at (the default branch when the route│ │46 // didn't name one), so the view's directory links stay pinned to it. │ │47 ref_or_oid: ui.RoutablePage.RefOrOid, │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────╮ │69 repo: *rp.Repo(repo_kind, repo_opts), │ │70 io: std.Io, │ │71 gpa: std.mem.Allocator, │ │72 - identity: []const u8, │ │72 + location: ui.RoutablePage.RepoLocation, │ │73 requested_ref_or_oid: ?ui.RoutablePage.RefOrOid,│ │74 requested_value: []const u8, │ │75 path: []const u8, │ ╰────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │82 // bad url (NotFound -> 404); the default-branch path falls through to empty. │ │83 const resolved = (try ui.ResolvedRefOrOid(repo_kind, repo_opts).init(repo, io, aa, requested_ref_or_oid, requested_value)) orelse {│ │84 if (requested_ref_or_oid != null) return error.NotFound; │ │85 - return emptyResult(aa, identity, .branch, requested_value, path); │ │85 + return emptyResult(aa, location, .branch, requested_value, path); │ │86 }; │ │87 │ │88 // read just the viewed directory of that commit's tree. building the │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │89 // read-only state mirrors what repo.status does internally, but for an │ │90 // arbitrary commit rather than HEAD. a path that doesn't exist in the tree │ │91 // is a bad url (404). │ │92 - var moment = repo.core.latestMoment() catch return emptyResult(aa, identity, resolved.ref_or_oid, resolved.value, path);│ │92 + var moment = repo.core.latestMoment() catch return emptyResult(aa, location, resolved.ref_or_oid, resolved.value, path);│ │93 const state = rp.Repo(repo_kind, repo_opts).State(.read_only){ .core = &repo.core, .extra = .{ .moment = &moment } }; │ │94 var tree_dir = tr.TreeDir(repo_kind, repo_opts).init(state, io, gpa, &resolved.oid, path) catch |err| switch (err) { │ │95 error.TreeEntryNotFound => return error.NotFound, │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────╮ │96 - else => return emptyResult(aa, identity, resolved.ref_or_oid, resolved.value, path),│ │96 + else => return emptyResult(aa, location, resolved.ref_or_oid, resolved.value, path),│ │97 }; │ │98 defer tree_dir.deinit(); │ │99 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────╮ │145 } │ │146 │ │147 return .{ │ │148 - .identity = try aa.dupe(u8, identity),│ │148 + .location = try location.dupe(aa), │ │149 .ref_or_oid = resolved.ref_or_oid, │ │150 .ref_or_oid_value = resolved.value, │ │151 .dir = try aa.dupe(u8, dir), │ ╰───────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │199 } │ │200 │ │201 // an empty listing pinned to a ref, for the wasm / no-repo / unresolved paths. │ │202 -pub fn emptyResult(aa: std.mem.Allocator, identity: []const u8, ref_or_oid: ui.RoutablePage.RefOrOid, ref_or_oid_value: []const u8, dir: []const u8) !Self { │ │202 +pub fn emptyResult(aa: std.mem.Allocator, location: ui.RoutablePage.RepoLocation, ref_or_oid: ui.RoutablePage.RefOrOid, ref_or_oid_value: []const u8, dir: []const u8) !Self {│ │203 return .{ │ │204 - .identity = try aa.dupe(u8, identity), │ │204 + .location = try location.dupe(aa), │ │205 .ref_or_oid = ref_or_oid, │ │206 .ref_or_oid_value = try aa.dupe(u8, ref_or_oid_value), │ │207 .dir = try aa.dupe(u8, dir), │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │239 │ │240 // the ref banner at the top. │ │241 { │ │242 - var header_view = try Header.View.init(allocator, &data.header, session, data.identity); │ │242 + var header_view = try Header.View.init(allocator, &data.header, session, data.location); │ │243 errdefer header_view.deinit(allocator); │ │244 try outer.children.put(allocator, header_view.getFocus().id, .{ .widget = .{ .repo_files_header = header_view }, .rect = null, .min_size = .{ .width = null, .height = 3 } });│ │245 } │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │561 fn addNavLink(self: *View, allocator: std.mem.Allocator, box: *wgt.Box(ui.Widget), label: []const u8, entry: Entry, target_start: usize) !void { │ │562 const page_arena = self.session.page_arena; │ │563 const path = try childDir(page_arena.allocator(), self.data.dir, entry.name); │ │564 - const route = ui.RoutablePage.repoFilesRoute(self.data.identity, self.data.ref_or_oid, self.data.ref_or_oid_value, path, target_start) orelse return error.RouteTooLong;│ │564 + const route = self.data.location.filesRoute(self.data.ref_or_oid, self.data.ref_or_oid_value, path, target_start) orelse return error.RouteTooLong; │ │565 const link = try std.fmt.allocPrint(page_arena.allocator(), "a:{s}", .{try route.toUrl(page_arena)}); │ │566 var tb = try wgt.TextBox.init(allocator, label, .{ .border_style = .single, .rounded_corners = true, .wrap_kind = .none }); │ │567 errdefer tb.deinit(allocator); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │804 // an "a:" link to the files route at `path`, pinned to the listing's ref, so │ │805 // following it navigates to that directory's listing. │ │806 fn dirLink(page_arena: *std.heap.ArenaAllocator, data: *const Self, path: []const u8) ![]const u8 { │ │807 - const route = ui.RoutablePage.repoFilesRoute(data.identity, data.ref_or_oid, data.ref_or_oid_value, path, 0) orelse return error.RouteTooLong;│ │807 + const route = data.location.filesRoute(data.ref_or_oid, data.ref_or_oid_value, path, 0) orelse return error.RouteTooLong; │ │808 return std.fmt.allocPrint(page_arena.allocator(), "a:{s}", .{try route.toUrl(page_arena)}); │ │809 } │ │810 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯