@page "/git/{Repository}/tree" @page "/git/{Repository}/tree/{*Path}" @inherits GitPage @Title — git
@if (View is not { } view) {

No revision @(Reference ?? "HEAD") in @Repository.

} else if (view.Entries is { } entries) {

@(Path is { Length: > 0 } ? Path : "/") @Counted(entries) at @view.Commit.ShortSha

@if (Parent is { } parent) { } @foreach (var entry in entries) { }
mode name size
..
@Mode(entry.Kind) @if (entry.Kind == GitEntryKind.Submodule) { @entry.Name @entry.Sha[..10] } else { @entry.Name } @(entry.Kind == GitEntryKind.Directory ? "" : Size(entry.Size))
} else if (view.Blob is { } blob) {

@blob.Path @Size(blob.Size)@(blob.Lines is { } counted ? $" · {Counted(counted.Count, "line")}" : "") · raw · history

@if (blob.IsBinary) {

Binary file. Download it to look inside.

} else if (blob.TooLarge) {

Too large to print here. Read it raw.

} else if (blob.Lines is { Count: 0 }) {

Empty file.

} else if (blob.Lines is { } lines) { @* Every line is addressable: #L42 scrolls to it and marks it, so a line of code can be linked to from anywhere. *@
@for (var number = 1; number <= lines.Count; number++) { }
@number @lines[number - 1]
}
} else {

Nothing browsable at @Path in @view.Reference.

}
@code { /// The path inside the repository, straight off the catch-all route segment. [Parameter] public string? Path { get; set; } private GitPathView? View { get; set; } /// /// The revision every link on this page stays on: what was asked for, or the branch the /// repository's HEAD is on. Following a tree into a directory should not silently move you. /// private string? At => Reference ?? View?.Reference; private string Title => Path is { Length: > 0 } path ? $"{path} · {Repository}" : $"{Repository} tree"; private IReadOnlyList Crumbs { get; set; } = []; /// The directory above, or null at the root. private string? Parent { get { if (Path is not { Length: > 0 } path) return null; var cut = path.LastIndexOf('/'); return cut < 0 ? "" : path[..cut]; } } protected override void OnParametersSet() { Path = Path?.Trim('/'); View = Service.GetPath(Repository, Reference, Path); if (View is null || (View.Entries is null && View.Blob is null)) NotFound(); Crumbs = BuildCrumbs(); } /// /// One step per path segment, the last of them the page you are on. The bar already holds the /// repository, so this starts inside it. /// private IReadOnlyList BuildCrumbs() { if (Path is not { Length: > 0 } path) return []; var segments = path.Split('/'); var crumbs = new List(segments.Length); var walked = ""; foreach (var segment in segments) { walked = walked.Length == 0 ? segment : $"{walked}/{segment}"; crumbs.Add(new GitBar.Crumb(segment, walked == path ? null : TreeLink(walked, At))); } return crumbs; } private static string Counted(IReadOnlyList entries) => Counted(entries.Count, "entry", "entries"); private static string Counted(int n, string one, string? many = null) => n == 1 ? $"1 {one}" : $"{n} {many ?? one + "s"}"; }