╭ changed ─────────╮ │src/event/Repo.zig│ ╰──────────────────╯ ╭────────────────────────────────╮ │ 7 name: []const u8, │ │ 8 description: []const u8, │ │ 9 enable_issue: bool, │ │10 + │ │11 +const Self = @This(); │ │12 │ │13 pub const name_max_len = 32;│ │14 │ ╰────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────╮ │78 } │ │79 } │ │80 │ │81 +// a repo plus its event id (the id is the on-disk repo directory name, so the │ │82 +// caller can locate the working repo under <server>/repos/<hex event id>). │ │83 +pub const RepoWithId = struct { │ │84 + repo: Self, │ │85 + event_id: [evt.event_id_size]u8, │ │86 +}; │ │87 + │ │88 // read a repo by its owner's name and repo name. the owner name is resolved to │ │89 // a user id via name->user-id (the repo index is keyed by "user-id/repo-name"),│ │90 // matching the /repo/username/reponame url. │ ╰────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ 95 arena: *std.heap.ArenaAllocator, │ │ 96 owner_name: []const u8, │ │ 97 repo_name: []const u8, │ │ 89 -) !?@This() { │ │ 98 +) !?RepoWithId { │ │ 99 // owner name -> user id │ │100 const name_to_user_id_cursor = try haxy_moment.getCursor(hash.hashInt(hash_kind, "name->user-id")) orelse return null;│ │101 const name_to_user_id = try DB.HashMap(.read_only).init(name_to_user_id_cursor); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │115 const event_id_to_repo = try DB.HashMap(.read_only).init(event_id_to_repo_cursor); │ │116 const repo_cursor = try event_id_to_repo.getCursor(hash.hashInt(hash_kind, &repo_id)) orelse return null;│ │117 const repo_map = try DB.HashMap(.read_only).init(repo_cursor); │ │109 - return try evt.read(@This(), DB, hash_kind, arena, repo_map); │ │118 + return .{ .repo = try evt.read(@This(), DB, hash_kind, arena, repo_map), .event_id = repo_id }; │ │119 } │ │120 │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ────────╮ │src/serve_ssh.zig│ ╰─────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │74 defer repo.deinit(io, allocator); │ │75 var ui_session = try ui.Session.init(&session_arena, &repo, .{}); │ │76 ui_session.is_terminal = true; │ │77 + // let page builders open on-disk repos (sibling "repos" dir of the admin repo) │ │78 + ui_session.io = io; │ │79 + ui_session.repos_dir = try std.fs.path.join(session_arena.allocator(), &.{ std.fs.path.dirname(handler.admin_repo_path) orelse ".", "repos" });│ │80 │ │81 var nav = try ui.Nav.init(allocator, &ui_session); │ │82 defer nav.deinit(allocator); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──╮ │src/try.zig│ ╰───────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────╮ │183 try repo_i.addConfig(io, allocator, .{ .name = "user.name", .value = "haxy" }); │ │184 try repo_i.addConfig(io, allocator, .{ .name = "user.email", .value = "admin@haxy" });│ │185 │ │186 - // write the repo's name and description into a README │ │186 + // write the repo's name and description into a README, plus a │ │187 + // nested doc so the file tree has a directory to descend into │ │188 { │ │189 var repo_dir = try cwd.openDir(io, repo_path, .{}); │ │190 defer repo_dir.close(io); │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │191 + │ │192 const readme = try repo_dir.createFile(io, "README.md", .{}); │ │193 defer readme.close(io); │ │194 const readme_content = try std.fmt.allocPrint(arena.allocator(), "# {s}\n\n{s}\n", .{ r.name, r.description });│ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────╮ │195 try readme.writeStreamingAll(io, readme_content); │ │196 + │ │197 + try repo_dir.createDirPath(io, "docs/dev"); │ │198 + const doc = try repo_dir.createFile(io, "docs/dev/contribute.md", .{}); │ │199 + defer doc.close(io); │ │200 + try doc.writeStreamingAll(io, "To contribute, please make a pull request");│ │201 } │ │202 │ │196 - try repo_i.add(io, allocator, &.{"README.md"}); │ │203 + try repo_i.add(io, allocator, &.{ "README.md", "docs/dev/contribute.md" }); │ │204 _ = try repo_i.commit(io, allocator, .{ .message = "let there be light" }); │ │205 } │ │206 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │224 const server_path = try std.fs.path.join(allocator, &.{ cwd_path, temp_dir_name, "server" }); │ │225 defer allocator.free(server_path); │ │226 │ │227 + // let the native TUI's page builders open the on-disk repos for the file tree │ │228 + session.io = io; │ │229 + session.repos_dir = try std.fs.path.join(session_arena.allocator(), &.{ server_path, "repos" });│ │230 + │ │231 if (cli) { │ │232 var stdout_writer = std.Io.File.stdout().writer(io, &.{}); │ │233 var stderr_writer = std.Io.File.stderr().writer(io, &.{}); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │27 user: User, │ │28 repo: Repo, │ │29 │ │30 - pub fn init(arena: *std.heap.ArenaAllocator, haxy_moment: evt.AdminDB.HashMap(.read_only), route: RoutablePage) !Page {│ │30 + pub fn init(arena: *std.heap.ArenaAllocator, session: *Session, route: RoutablePage) !Page { │ │31 + const haxy_moment = session.haxy_moment orelse return error.NoMoment; │ │32 return switch (route.parent()) { │ │33 .home => .{ .home = try Home.init(arena, haxy_moment) }, │ │34 .user => switch (route) { │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯