╭ changed ──────╮ │src/ui/Repo.zig│ ╰───────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭───────────────────────────────────────────────────────────────────────────────────╮ │55 ) !Self { │ │56 const DB = evt.AdminDB; │ │57 const hash_kind = evt.admin_repo_opts.hash; │ │58 - const haxy_moment = session.haxy_moment orelse return error.NoMoment; │ │58 │ │59 // every repo route's stored string starts with "owner/name"; the files and│ │60 // commits routes additionally encode a ref/oid (files also a directory). │ ╰───────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │117 else => "", │ │118 }; │ │119 │ │121 - const found = (try evt.Repo.readByOwnerAndName(DB, hash_kind, haxy_moment, arena, rf.owner, rf.name)) orelse return error.NotFound; │ │122 - const repo = found.repo; │ │120 + // where the on-disk repo lives (null keeps the views' empty fallback), plus │ │121 + // the repo and owner-name metadata the header shows. local mode already │ │122 + // knows all three; the server paths resolve them from the admin db. │ │123 + var source: ?ui.RepoSource = null; │ │124 + var repo: evt.Repo = undefined; │ │125 + var owner_name: []const u8 = undefined; │ │126 + if (session.local) |local| { │ │127 + source = local; │ │128 + repo = .{ │ │129 + .user_id = "", │ │130 + .name = try arena.allocator().dupe(u8, rf.name), │ │131 + .description = "", │ │132 + .enable_issue = true, │ │133 + }; │ │134 + owner_name = try arena.allocator().dupe(u8, rf.owner); │ │135 + } else { │ │136 + const haxy_moment = session.haxy_moment orelse return error.NoMoment; │ │137 + const found = (try evt.Repo.readByOwnerAndName(DB, hash_kind, haxy_moment, arena, rf.owner, rf.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 │ │141 + // of the repo title. │ │142 + const owner = (try evt.User.readById(DB, hash_kind, haxy_moment, arena, repo.user_id)) orelse return error.NotFound; │ │143 + owner_name = owner.name; │ │144 │ │124 - // resolve the creating user so the header can show their name to the left │ │125 - // of the repo title. │ │126 - const owner = (try evt.User.readById(DB, hash_kind, haxy_moment, arena, repo.user_id)) orelse return error.NotFound; │ │145 + // the repo's working copy lives at <repos_dir>/<hex event id>. │ │146 + if (session.repos_dir) |repos_dir| { │ │147 + const hex = std.fmt.bytesToHex(found.event_id, .lower); │ │148 + source = .{ │ │149 + .path = try std.fs.path.join(arena.allocator(), &.{ repos_dir, &hex }), │ │150 + .repo_kind = .xit, │ │151 + }; │ │152 + } │ │153 + } │ │154 │ │155 // build files and commits first so their resolved ref (the default branch │ │156 // when the route named none) can canonicalize each tab's mirror url to the │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │157 // explicit ref it's viewing rather than leaving it bare. both resolve the │ │158 // same requested ref, so they end up viewing the same one. │ │132 - const files = try Files.init(arena, session, &found.event_id, rf.identity, requested_ref_or_oid, requested_ref_value, files_dir, files_after);│ │133 - const commits = try Commits.init(arena, session, &found.event_id, rf.identity, requested_ref_or_oid, requested_ref_value, commits_after); │ │159 + const files = try Files.init(arena, session, source, rf.identity, requested_ref_or_oid, requested_ref_value, files_dir, files_after); │ │160 + const commits = try Commits.init(arena, session, source, rf.identity, requested_ref_or_oid, requested_ref_value, commits_after); │ │161 │ │162 // each tab mirror carries this page's route for that tab; tabs not targeted │ │163 // by the incoming route fall back to their root/first-page route. the files │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │173 return .{ │ │174 // files and commits resolve the same ref, so either's serves the header, │ │175 // which points both tabs at it. │ │149 - .header = try Header.init(arena, repo.name, owner.name, files.ref_or_oid, files.ref_or_oid_value, issues_tag),│ │176 + .header = try Header.init(arena, repo.name, owner_name, files.ref_or_oid, files.ref_or_oid_value, issues_tag),│ │177 .repo = repo, │ │178 .files = files, │ │179 .commits = commits, │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │153 - .refs = try Refs.init(arena, session, &found.event_id, rf.identity, refs_kind, refs_after), │ │154 - .issues = try Issues.init(arena, session, &found.event_id, rf.identity, issues_tag, issues_selected),│ │180 + .refs = try Refs.init(arena, session, source, rf.identity, refs_kind, refs_after), │ │181 + .issues = try Issues.init(arena, session, source, rf.identity, issues_tag, issues_selected), │ │182 .settings = Settings.init(), │ │183 .auth = Auth.init(), │ │184 .quit = Quit.init(), │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │250 try stack.children.put(allocator, settings_view.getFocus().id, .{ .home_settings = settings_view });│ │251 } │ │252 │ │226 - { │ │253 + // the header has no auth tab in local mode, so keep the stack's │ │254 + // children 1:1 with the tabs by skipping the auth view too. │ │255 + if (session.local == null) { │ │256 var auth_view = try Auth.View.init(allocator, &data.auth, session, files_tab_id); │ │257 errdefer auth_view.deinit(allocator); │ │258 try stack.children.put(allocator, auth_view.getFocus().id, .{ .home_auth = auth_view }); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯