detached 5228465

fix(commit): trim all trailing whitespace from signature names

commit
5228465d7a80374c8b4a6261aa7ac49da53ff641
author
brice · · 2026-10-11 01:07 UTC
parent
585a2d1
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
refs
tag: v0.1.0
2 files · +23 -1
M commit.go +1 -1
@@ -140,7 +140,7 @@ func parseSignature(b []byte) Signature {
140140 s.Name = bytes.TrimSpace(b)
141141 return s
142142 }
143- s.Name = bytes.TrimRight(b[:lt], " ")
143+ s.Name = bytes.TrimRight(b[:lt], " \t\r\n")
144144 s.Email = b[lt+1 : gt]
145145 rest := bytes.TrimLeft(b[gt+1:], " ")
146146 secs, rest, _ := bytes.Cut(rest, []byte{' '})
@@ -140,7 +140,7 @@ func parseSignature(b []byte) Signature {
140 s.Name = bytes.TrimSpace(b)140 s.Name = bytes.TrimSpace(b)
141 return s141 return s
142 }142 }
143- s.Name = bytes.TrimRight(b[:lt], " ")143+ s.Name = bytes.TrimRight(b[:lt], " \t\r\n")
144 s.Email = b[lt+1 : gt]144 s.Email = b[lt+1 : gt]
145 rest := bytes.TrimLeft(b[gt+1:], " ")145 rest := bytes.TrimLeft(b[gt+1:], " ")
146 secs, rest, _ := bytes.Cut(rest, []byte{' '})146 secs, rest, _ := bytes.Cut(rest, []byte{' '})
M conformance_test.go +22 -0
@@ -818,3 +818,25 @@ func TestConformanceDeltaCacheSizes(t *testing.T) {
818818 })
819819 }
820820 }
821+
822+// The name of a signature loses all its trailing whitespace, as in git's
823+// split_ident_line (%an), not only spaces.
824+func TestSignatureNameTrimming(t *testing.T) {
825+ f := newFx(t)
826+ f.write("f", []byte("x\n"), 0o644)
827+ f.commit("one")
828+ tree := f.git("rev-parse", "HEAD^{tree}")
829+ for _, name := range []string{"A B", "A \t\r ", "A\t", "A\r", "A \t B \t", "\tlead \t", "A\v", "A\f", " "} {
830+ raw := "tree " + tree + "\nauthor " + name + "<a@b.c> 1700000000 +0100\ncommitter x <a@b.c> 1700000000 +0100\n\nm\n"
831+ id := f.gitIn([]byte(raw), "hash-object", "-t", "commit", "-w", "--literally", "--stdin")
832+ want := string(runGit(t, f.root(), nil, f.env(), "log", "-1", "--format=%an", id))
833+ want = strings.TrimSuffix(want, "\n")
834+ var c Commit
835+ if err := f.open().ReadCommit(mustID(t, id), &c); err != nil {
836+ t.Fatal(err)
837+ }
838+ if string(c.Author.Name) != want {
839+ t.Errorf("author %q: name %q, git %%an %q", name, c.Author.Name, want)
840+ }
841+ }
842+}
@@ -818,3 +818,25 @@ func TestConformanceDeltaCacheSizes(t *testing.T) {
818 })818 })
819 }819 }
820 }820 }
821+
822+// The name of a signature loses all its trailing whitespace, as in git's
823+// split_ident_line (%an), not only spaces.
824+func TestSignatureNameTrimming(t *testing.T) {
825+ f := newFx(t)
826+ f.write("f", []byte("x\n"), 0o644)
827+ f.commit("one")
828+ tree := f.git("rev-parse", "HEAD^{tree}")
829+ for _, name := range []string{"A B", "A \t\r ", "A\t", "A\r", "A \t B \t", "\tlead \t", "A\v", "A\f", " "} {
830+ raw := "tree " + tree + "\nauthor " + name + "<a@b.c> 1700000000 +0100\ncommitter x <a@b.c> 1700000000 +0100\n\nm\n"
831+ id := f.gitIn([]byte(raw), "hash-object", "-t", "commit", "-w", "--literally", "--stdin")
832+ want := string(runGit(t, f.root(), nil, f.env(), "log", "-1", "--format=%an", id))
833+ want = strings.TrimSuffix(want, "\n")
834+ var c Commit
835+ if err := f.open().ReadCommit(mustID(t, id), &c); err != nil {
836+ t.Fatal(err)
837+ }
838+ if string(c.Author.Name) != want {
839+ t.Errorf("author %q: name %q, git %%an %q", name, c.Author.Name, want)
840+ }
841+ }
842+}

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 1

Tags 2

↑↓ moveenter openesc close