╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │102 }; │ │103 }, │ │104 .repo => switch (route) { │ │105 - .repo_files, .repo_commits, .repo_diff, .repo_refs, .repo_issues, .repo_patches, .repo_discussions, .repo_events, .repo_undo, .repo_settings, .repo_members, .repo_repo_new, .repo_user_new, .repo_user => .{ .repo = try Repo.init(arena, session, route) }, │ │105 + .repo_files, .repo_commits, .repo_diff, .repo_refs, .repo_issues, .repo_patches, .repo_discussions, .repo_events, .repo_undo, .repo_settings, .repo_members, .repo_branches, .repo_repo_new, .repo_user_new, .repo_user => .{ .repo = try Repo.init(arena, session, route) },│ │106 else => return error.UnexpectedRoute, │ │107 }, │ │108 .fork => switch (route) { │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────╮ │194 repo_user_new: Array(repo_route_max_len), │ │195 repo_settings: Array(repo_route_max_len), │ │196 repo_members: RepoMembersRoute, │ │197 + repo_branches: RepoBranchesRoute, │ │198 repo_user: struct { name: Array(repo_route_max_len), tab: UserTab = .{} },│ │199 fork_patch: ForkRoute, │ │200 fork_diff: ForkDiffRoute, │ ╰───────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────╮ │335 const merge_seg = @tagName(Params.ParamKey.merge) ++ ":"; │ │336 const theirs_seg = @tagName(Params.ParamKey.theirs) ++ ":"; │ │337 const user_seg = @tagName(Params.ParamKey.user) ++ ":"; │ │338 + const branch_seg = @tagName(Params.ParamKey.branch) ++ ":"; │ │339 const key_seg = @tagName(Params.ParamKey.key) ++ ":"; │ │340 // ends a key removal's confirmation url, so its form posts to the removal│ │341 const remove_key_word = "removekey"; │ ╰───────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────╮ │449 confirm: ?Repo.Members.Action = null, │ │450 }; │ │451 │ │452 + pub const RepoBranchesRoute = struct { │ │453 + name: Array(repo_identity_max_len), │ │454 + // the url-encoded branch a row's form acts on ("" = none) │ │455 + branch: Array(ref_route_max_len) = .{}, │ │456 + }; │ │457 + │ │458 pub fn repoSettingsRoute(identity: []const u8) ?RoutablePage { │ │459 return .{ .repo_settings = Array(repo_route_max_len).from(identity) orelse return null };│ │460 } │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │461 │ │462 pub fn repoMembersRoute(identity: []const u8, start: usize) ?RoutablePage { │ │463 return .{ .repo_members = .{ .name = Array(repo_identity_max_len).from(identity) orelse return null, .start = start } };│ │464 + } │ │465 + │ │466 + pub fn repoBranchesRoute(identity: []const u8) ?RoutablePage { │ │467 + return .{ .repo_branches = .{ .name = Array(repo_identity_max_len).from(identity) orelse return null } }; │ │468 } │ │469 │ │470 pub fn repoUndoRoute(identity: []const u8, index: ?u64) ?RoutablePage { │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1290 if (r.confirm) |action| try out.writer.print("/{s}", .{@tagName(action)}); │ │1291 break :blk out.written(); │ │1292 }, │ │1293 + .repo_branches => |b| blk: { │ │1294 + var out: std.Io.Writer.Allocating = .init(arena.allocator()); │ │1295 + try out.writer.print("{s}/repo/branches", .{try repoUrlPrefix(arena, b.name.slice())}); │ │1296 + if (b.branch.len != 0) try out.writer.print("/" ++ branch_seg ++ "{s}", .{b.branch.slice()});│ │1297 + break :blk out.written(); │ │1298 + }, │ │1299 .repo_user => |u| try userTabUrl(arena, try repoUrlPrefix(arena, u.name.slice()), u.tab), │ │1300 .fork_patch => |f| try arena.allocator().print("/{s}+{s}", .{ f.name.slice(), f.id.slice() }), │ │1301 .fork_diff => |d| blk: { │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────╮ │1475 .repo_events => |*e| e.name.slice(), │ │1476 .repo_undo => |*u| u.name.slice(), │ │1477 .repo_members => |*r| r.name.slice(), │ │1478 + .repo_branches => |*b| b.name.slice(), │ │1479 .repo_user => |*u| u.name.slice(), │ │1480 .repo_settings, .repo_repo_new, .repo_user_new => |*name| name.slice(),│ │1481 else => null, │ ╰─────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1521 return switch (self) { │ │1522 .home_about, .home_users, .home_repo_new, .home_user_new, .home_user => .home, │ │1523 .user_repos, .user_forks, .user_repo_new, .user_user_new, .user_user => .user, │ │1505 - .repo_files, .repo_commits, .repo_diff, .repo_refs, .repo_issues, .repo_patches, .repo_discussions, .repo_events, .repo_undo, .repo_settings, .repo_members, .repo_repo_new, .repo_user_new, .repo_user => .repo, │ │1524 + .repo_files, .repo_commits, .repo_diff, .repo_refs, .repo_issues, .repo_patches, .repo_discussions, .repo_events, .repo_undo, .repo_settings, .repo_members, .repo_branches, .repo_repo_new, .repo_user_new, .repo_user => .repo,│ │1525 .fork_patch, .fork_diff, .fork_files, .fork_commits, .fork_repo_new, .fork_user_new, .fork_user => .fork, │ │1526 .not_found => .not_found, │ │1527 }; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1618 if ((action != .revoke and action != .demote) or route.repo_members.user.len == 0) return null; │ │1619 route.repo_members.confirm = action; │ │1620 } │ │1621 + return route; │ │1622 + } │ │1623 + if (std.mem.eql(u8, word, "branches")) { │ │1624 + _ = segments.next(); │ │1625 + if ((params.scanTail(&segments) catch return null) != null) return null; │ │1626 + if (!params.only(&.{.branch})) return null; │ │1627 + var route = repoBranchesRoute(pair) orelse return null; │ │1628 + if (params.values.get(.branch)) |branch| route.repo_branches.branch = Array(ref_route_max_len).from(branch) orelse return null;│ │1629 return route; │ │1630 } │ │1631 return if (isNewTail(&segments)) .{ .repo_repo_new = Array(repo_route_max_len).from(pair) orelse return null } else null; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1945 a_r.start == b.repo_members.start and │ │1946 std.mem.eql(u8, a_r.user.slice(), b.repo_members.user.slice()) and │ │1947 a_r.confirm == b.repo_members.confirm, │ │1948 + .repo_branches => |a_b| std.mem.eql(u8, a_b.name.slice(), b.repo_branches.name.slice()) and │ │1949 + std.mem.eql(u8, a_b.branch.slice(), b.repo_branches.branch.slice()), │ │1950 .repo_user => |a_u| std.mem.eql(u8, a_u.name.slice(), b.repo_user.name.slice()) and a_u.tab.eql(b.repo_user.tab), │ │1951 .fork_patch => |a_f| std.mem.eql(u8, a_f.name.slice(), b.fork_patch.name.slice()) and std.mem.eql(u8, a_f.id.slice(), b.fork_patch.id.slice()),│ │1952 .fork_diff => |a_d| std.mem.eql(u8, a_d.fork.name.slice(), b.fork_diff.fork.name.slice()) and │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯