v0.26.0 df1db36

signature.go RawHistoryFolder

1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package web
4
5import (
6	"bnema.dev/ermite/internal/domain"
7)
8
9// SignatureBadge is the pill of a signed commit. Label is the verdict, Proto
10// the protocol ("SSH", "GPG", "X.509", empty when unknown), Class the style
11// (sig-ok, sig-warn, sig-bad, sig-none) and Title the tooltip that says why.
12type SignatureBadge struct {
13	Label, Proto, Class, Title string
14}
15
16// signatureProto is the display name of a signature format.
17func signatureProto(f domain.SignatureFormat) string {
18	switch f {
19	case domain.FormatSSH:
20		return "SSH"
21	case domain.FormatGPG:
22		return "GPG"
23	case domain.FormatX509:
24		return "X.509"
25	}
26	return ""
27}
28
29// signatureBadge is the badge of a verification, nil when there is nothing to
30// show: the commit was not checked, or (unless long, the commit page) it is
31// not signed.
32func signatureBadge(v domain.CommitVerification, long bool) *SignatureBadge {
33	switch v.Status {
34	case domain.StatusUnchecked:
35		return nil
36	case domain.StatusUnsigned:
37		if !long {
38			return nil
39		}
40		return &SignatureBadge{Label: "unsigned", Class: "sig-none", Title: "This commit is not signed"}
41	}
42	b := &SignatureBadge{Proto: signatureProto(v.Format)}
43	key := keyPhrase(v)
44	switch v.Status {
45	case domain.StatusVerified:
46		b.Label, b.Class = "Verified", "sig-ok"
47		b.Title = "Signed with " + key + " — verified for the committer email"
48	case domain.StatusUnknownKey:
49		b.Label, b.Class = "Unverified", "sig-warn"
50		b.Title = unknownKeyTitle(v)
51	case domain.StatusEmailMismatch:
52		b.Label, b.Class = "Unverified", "sig-warn"
53		b.Title = "Signed with " + key + " — this key is not trusted for the committer email"
54	case domain.StatusExpired:
55		b.Label, b.Class = "Unverified", "sig-warn"
56		b.Title = "Signed with " + key + " — the key or the signature expired"
57	case domain.StatusRevoked:
58		b.Label, b.Class = "Unverified", "sig-warn"
59		b.Title = "Signed with " + key + " — the key is revoked"
60	case domain.StatusBadSignature:
61		b.Label, b.Class = "Bad signature", "sig-bad"
62		b.Title = "The signature does not match the commit"
63	case domain.StatusUnsupported:
64		b.Label, b.Class = "Unverified", "sig-warn"
65		if proto := signatureProto(v.Format); proto != "" {
66			b.Title = proto + " signatures are not checked"
67		} else {
68			b.Title = "This kind of signature is not checked"
69		}
70	default:
71		return nil
72	}
73	return b
74}
75
76// keyPhrase names the signing key for a tooltip: "SSH key SHA256:… (title)".
77func keyPhrase(v domain.CommitVerification) string {
78	s := "a key"
79	if p := signatureProto(v.Format); p != "" {
80		s = p + " key"
81	}
82	if v.Fingerprint != "" {
83		s += " " + v.Fingerprint
84	}
85	if v.KeyTitle != "" {
86		s += " (" + visibleText(v.KeyTitle) + ")"
87	}
88	return s
89}
90
91// unknownKeyTitle is the tooltip of a signature by a key that is not trusted.
92func unknownKeyTitle(v domain.CommitVerification) string {
93	s := "Signed with an unknown "
94	if p := signatureProto(v.Format); p != "" {
95		s += p + " "
96	}
97	s += "key"
98	if v.Fingerprint != "" {
99		s += " " + v.Fingerprint
100	}
101	return s
102}

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