v0.2.0 41cf2ec

refspage.go RawHistoryFolder

1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package web
4
5import (
6	"context"
7	"net/http"
8	"sort"
9
10	"github.com/a-h/templ"
11
12	pb "bnema.dev/ermite-api/gen/ermite"
13)
14
15// refs lists the branches and the tags of a repository with the commit each
16// designates: branches by name with the default first, tags newest first.
17func (s *Server) refs(ctx context.Context, r *http.Request) (templ.Component, int, error) {
18	d, err := s.loadRepo(ctx, r.PathValue("repo"))
19	if err != nil {
20		return nil, 0, err
21	}
22	p := s.refsPage(ctx, d)
23
24	l := s.repoLayout(ctx, d, "refs")
25	l.Title = "refs · " + d.name() + " · " + s.instance
26	l.Live, l.LiveURL = true, liveURL("repo:"+d.name(), "view=refs")
27	l.Crumbs[0].Current = false
28	l.Crumbs = append(l.Crumbs, Crumb{Label: "refs", Current: true})
29	l.Status = Status{
30		Mode: "refs", Context: plural(len(p.Branches), "branch", "branches") + " · " + plural(len(p.Tags), "tag", "tags"),
31		Hints: "j/k move · enter open · / filter · ? help", Cursor: true, Count: len(p.Branches) + len(p.Tags),
32	}
33	l.HasRail, l.RailSum = true, "refs · legend"
34	return Refs(l, p), http.StatusOK, nil
35}
36
37// refsPage is the content of the refs page, which the live updates of the
38// page render again.
39func (s *Server) refsPage(ctx context.Context, d *repoData) RefsPage {
40	commits := s.commitsOf(ctx, d.name(), d.allRefs())
41
42	def := d.repo.GetDefaultBranch()
43	p := RefsPage{Default: def}
44	branches := append([]*pb.Ref(nil), d.branches...)
45	sort.SliceStable(branches, func(i, j int) bool {
46		a, b := branches[i].GetShortName() == def, branches[j].GetShortName() == def
47		return a && !b
48	})
49	for i, b := range branches {
50		p.Branches = append(p.Branches, s.refRow(d, b, commits, b.GetShortName() == def, i == 0))
51	}
52	tags := append([]*pb.Ref(nil), d.tags...)
53	sort.SliceStable(tags, func(i, j int) bool {
54		return commits[tags[i].GetCommitId()].at > commits[tags[j].GetCommitId()].at
55	})
56	for i, t := range tags {
57		p.Tags = append(p.Tags, s.refRow(d, t, commits, false, len(p.Branches) == 0 && i == 0))
58	}
59	if len(tags) > 0 {
60		p.Latest = tags[0].GetShortName()
61	}
62	if d.cut {
63		p.Note = "this repository has more refs than are listed here."
64	}
65	return p
66}
67
68func (s *Server) refRow(d *repoData, r *pb.Ref, commits map[string]refCommit, isDefault, cursor bool) RefRow {
69	c := commits[r.GetCommitId()]
70	row := RefRow{
71		Name: r.GetShortName(), Href: repoHref(d.name(), "tree", r.GetShortName()),
72		Short: short(r.GetCommitId()), Subject: c.subject, When: c.when, WhenAt: c.whenAt,
73		Default: isDefault, Cursor: cursor,
74	}
75	if r.GetCommitId() != "" {
76		row.CHref = repoHref(d.name(), "commit", r.GetCommitId())
77	}
78	return row
79}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 2

Tags 45

↑↓ moveenter openesc close