╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ────────────╮ │src/ui/Repo/Files.zig│ ╰─────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │186 // their first window (for the in-page detail when selected). │ │187 const is_selected = if (selected_file) |sf| std.mem.eql(u8, sf, name) else false; │ │188 const window_start = if (is_selected) after else 0; │ │188 - const content = readFileContent(repo_opts, state, io, gpa, aa, file_path, tree_entry, window_start) catch │ │189 + const content = readFileContent(repo_kind, repo_opts, state, io, gpa, aa, file_path, tree_entry, window_start) catch│ │190 FileContent{ .lines = &.{} }; │ │191 entry.lines = content.lines; │ │192 entry.is_binary = content.is_binary; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────╮ │221 // line iterator flags binary files (its source becomes `.binary`), in which case│ │222 // we report no lines and let the view show a placeholder. │ │223 fn readFileContent( │ │223 - comptime repo_opts: rp.RepoOpts(.xit), │ │224 - state: rp.Repo(.xit, repo_opts).State(.read_only), │ │224 + comptime repo_kind: rp.RepoKind, │ │225 + comptime repo_opts: rp.RepoOpts(repo_kind), │ │226 + state: rp.Repo(repo_kind, repo_opts).State(.read_only), │ │227 io: std.Io, │ │228 gpa: std.mem.Allocator, │ │229 arena: std.mem.Allocator, │ ╰──────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │231 tree_entry: tr.TreeEntry(repo_opts.hash), │ │232 start: usize, │ │233 ) !FileContent { │ │232 - var line_iter = try df.LineIterator(.xit, repo_opts).initFromTree(state, io, gpa, path, tree_entry); │ │234 + var line_iter = try df.LineIterator(repo_kind, repo_opts).initFromTree(state, io, gpa, path, tree_entry);│ │235 defer line_iter.deinit(); │ │236 if (line_iter.source == .binary) return .{ .lines = &.{}, .is_binary = true }; │ │237 │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─────────────╮ │src/ui/Repo/Header.zig│ ╰──────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────╮ │53 │ │54 const aa = session.page_arena.allocator(); │ │55 │ │56 - // the user's name │ │57 - { │ │56 + // the user's name (local mode has no user pages to link to) │ │57 + if (session.local == null) { │ │58 const text = try std.fmt.allocPrint(aa, "{s}/", .{data.owner_name}); │ │59 const link = try std.fmt.allocPrint(aa, "a:/user/{s}", .{data.owner_name});│ │60 │ ╰───────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────╮ │221 } │ │222 │ │223 // auth tab (login / logout). AuthTab defaults to the global ai:/auth │ │224 - // link; repoint its instance at this repo's auth route so it stays local.│ │225 - { │ │224 + // link; repoint its instance at this repo's auth route so it stays on │ │225 + // this page. local mode has no accounts, so it has no auth tab. │ │226 + if (session.local == null) { │ │227 var auth_tab = try AuthTab.View.init(allocator, session); │ │228 errdefer auth_tab.deinit(allocator); │ │229 auth_tab.text_box.getFocus().kind = .{ .custom = auth_link }; │ ╰───────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─────────────╮ │src/ui/Repo/Issues.zig│ ╰──────────────────────╯ ╭───────────────────────────────────────────────╮ │41 pub fn init( │ │42 arena: *std.heap.ArenaAllocator, │ │43 session: *ui.Session, │ │44 - event_id: *const [evt.event_id_size]u8,│ │44 + source_maybe: ?ui.RepoSource, │ │45 identity: []const u8, │ │46 tag: []const u8, │ │47 selected_id: []const u8, │ ╰───────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────╮ │59 // no filesystem (wasm) or nowhere to look: empty listing. the wasm path │ │60 // never calls init anyway — it rebuilds from the serialized snapshot. │ │61 const io = session.io orelse return empty; │ │62 - const repos_dir = session.repos_dir orelse return empty; │ │62 + const source = source_maybe orelse return empty; │ │63 │ │64 - // the repo's working copy lives at <repos_dir>/<hex event id>. │ │65 - const hex = std.fmt.bytesToHex(event_id.*, .lower); │ │66 - const repo_path = try std.fs.path.join(aa, &.{ repos_dir, &hex }); │ │64 + // issues live in the repo's own xit db, so a git-backed repo has none. │ │65 + if (source.repo_kind == .git) return empty; │ │66 │ │67 // open with the arena's backing allocator (transient; the issue strings are│ │68 // duped into the page arena so they outlive the repo handle). │ ╰────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │69 const gpa = arena.child_allocator; │ │71 - var any_repo = rp.AnyRepo(.xit, .{}).open(io, gpa, .{ .path = repo_path }) catch return empty; │ │70 + var any_repo = rp.AnyRepo(.xit, .{}).open(io, gpa, .{ .path = source.path }) catch return empty;│ │71 defer any_repo.deinit(io, gpa); │ │72 │ │73 return switch (any_repo) { │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───────────╮ │src/ui/Repo/Refs.zig│ ╰────────────────────╯ ╭───────────────────────────────────────────────╮ │37 pub fn init( │ │38 arena: *std.heap.ArenaAllocator, │ │39 session: *ui.Session, │ │40 - event_id: *const [evt.event_id_size]u8,│ │40 + source_maybe: ?ui.RepoSource, │ │41 identity: []const u8, │ │42 kind: ui.RoutablePage.RefKind, │ │43 after: usize, │ ╰───────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────╮ │63 // no filesystem (wasm) or nowhere to look: empty lists. the wasm path never│ │64 // calls init anyway — it rebuilds from the serialized snapshot. │ │65 const io = session.io orelse return empty; │ │66 - const repos_dir = session.repos_dir orelse return empty; │ │67 - │ │68 - // the repo's working copy lives at <repos_dir>/<hex event id>. │ │69 - const hex = std.fmt.bytesToHex(event_id.*, .lower); │ │70 - const repo_path = try std.fs.path.join(aa, &.{ repos_dir, &hex }); │ │66 + const source = source_maybe orelse return empty; │ │67 │ │68 // open with the arena's backing allocator (transient; the ref names are │ │69 // duped into the page arena so they outlive the repo handle). │ ╰────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯