detached df1db36

feat: signature badges on merge request commits (#73)

commit
df1db3633d13a90a4e152cfc1cd566ae4e863c9a
author
brice · · 2026-10-18 18:36 UTC
committer
bnema · · 2026-10-18 18:36 UTC
parent
94ae608
signature
SSH UnverifiedSHA256:VOCA5lYARHcbKDZ7GhTV45VmcjWnJ6ZQIBazj17LivA The key is unknown
refs
tag: v0.26.0
10 files · +275 -167
M docs/commit-signatures.md +1 -1
@@ -1,6 +1,6 @@
11 # Commit signatures
22
3-ermite checks commit signatures on the commit list and the commit page and shows a badge with the protocol and the result. The API returns the same result in `Commit.verification` from `ListCommits` and `GetCommit`.
3+ermite checks commit signatures on the commit list, the commit page and the commits of a merge request, and shows a badge with the protocol and the result. The API returns the same result in `Commit.verification` from `ListCommits`, `GetCommit` and `GetMergeRequest`.
44
55 ## Formats
66
@@ -1,6 +1,6 @@
1 # Commit signatures1 # Commit signatures
2 2
3-ermite checks commit signatures on the commit list and the commit page and shows a badge with the protocol and the result. The API returns the same result in `Commit.verification` from `ListCommits` and `GetCommit`.3+ermite checks commit signatures on the commit list, the commit page and the commits of a merge request, and shows a badge with the protocol and the result. The API returns the same result in `Commit.verification` from `ListCommits`, `GetCommit` and `GetMergeRequest`.
4 4
5 ## Formats5 ## Formats
6 6
M internal/adapters/web/mr.go +3 -0
@@ -148,6 +148,8 @@ type MRCommit struct {
148148 Short, Href, Subject, Author, When, WhenAt string
149149 // New is true for a commit pushed after the head the reviewer last read.
150150 New bool
151+ // Sig is the signature badge, nil for an unsigned or unchecked commit.
152+ Sig *SignatureBadge
151153 }
152154
153155 // MergeBox is what the owner does with an open request.
@@ -534,6 +536,7 @@ func (s *Server) mrPage(ctx context.Context, r *http.Request, since bool) (templ
534536 row := commitRow(d.name(), c, now)
535537 p.Commits = append(p.Commits, MRCommit{
536538 Short: row.Short, Href: row.CHref, Subject: row.Subject, Author: row.Author, When: row.When, WhenAt: row.WhenAt,
539+ Sig: row.Sig,
537540 })
538541 }
539542 lastRead := res.LastReadID.String()
@@ -148,6 +148,8 @@ type MRCommit struct {
148 Short, Href, Subject, Author, When, WhenAt string148 Short, Href, Subject, Author, When, WhenAt string
149 // New is true for a commit pushed after the head the reviewer last read.149 // New is true for a commit pushed after the head the reviewer last read.
150 New bool150 New bool
151+ // Sig is the signature badge, nil for an unsigned or unchecked commit.
152+ Sig *SignatureBadge
151 }153 }
152 154
153 // MergeBox is what the owner does with an open request.155 // MergeBox is what the owner does with an open request.
@@ -534,6 +536,7 @@ func (s *Server) mrPage(ctx context.Context, r *http.Request, since bool) (templ
534 row := commitRow(d.name(), c, now)536 row := commitRow(d.name(), c, now)
535 p.Commits = append(p.Commits, MRCommit{537 p.Commits = append(p.Commits, MRCommit{
536 Short: row.Short, Href: row.CHref, Subject: row.Subject, Author: row.Author, When: row.When, WhenAt: row.WhenAt,538 Short: row.Short, Href: row.CHref, Subject: row.Subject, Author: row.Author, When: row.When, WhenAt: row.WhenAt,
539+ Sig: row.Sig,
537 })540 })
538 }541 }
539 lastRead := res.LastReadID.String()542 lastRead := res.LastReadID.String()
M internal/adapters/web/mr.templ +3 -0
@@ -318,6 +318,9 @@ templ mrRail(p MRPage) {
318318 <li data-new?={ c.New }>
319319 <a href={ templ.SafeURL(c.Href) }>{ c.Short }</a>
320320 <span class="s">{ c.Subject }</span>
321+ if c.Sig != nil {
322+ @signaturePill(c.Sig)
323+ }
321324 <span class="mute">
322325 { c.Author }
323326 if c.WhenAt != "" {
@@ -318,6 +318,9 @@ templ mrRail(p MRPage) {
318 <li data-new?={ c.New }>318 <li data-new?={ c.New }>
319 <a href={ templ.SafeURL(c.Href) }>{ c.Short }</a>319 <a href={ templ.SafeURL(c.Href) }>{ c.Short }</a>
320 <span class="s">{ c.Subject }</span>320 <span class="s">{ c.Subject }</span>
321+ if c.Sig != nil {
322+ @signaturePill(c.Sig)
323+ }
321 <span class="mute">324 <span class="mute">
322 { c.Author }325 { c.Author }
323 if c.WhenAt != "" {326 if c.WhenAt != "" {
M internal/adapters/web/mr_templ.go +174 -164
@@ -1788,20 +1788,30 @@ func mrRail(p MRPage) templ.Component {
17881788 if templ_7745c5c3_Err != nil {
17891789 return templ_7745c5c3_Err
17901790 }
1791- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 158, "</span> <span class=\"mute\">")
1791+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 158, "</span> ")
1792+ if templ_7745c5c3_Err != nil {
1793+ return templ_7745c5c3_Err
1794+ }
1795+ if c.Sig != nil {
1796+ templ_7745c5c3_Err = signaturePill(c.Sig).Render(ctx, templ_7745c5c3_Buffer)
1797+ if templ_7745c5c3_Err != nil {
1798+ return templ_7745c5c3_Err
1799+ }
1800+ }
1801+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 159, "<span class=\"mute\">")
17921802 if templ_7745c5c3_Err != nil {
17931803 return templ_7745c5c3_Err
17941804 }
17951805 var templ_7745c5c3_Var90 string
17961806 templ_7745c5c3_Var90, templ_7745c5c3_Err = templ.JoinStringErrs(c.Author)
17971807 if templ_7745c5c3_Err != nil {
1798- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 322, Col: 16}
1808+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 325, Col: 16}
17991809 }
18001810 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var90))
18011811 if templ_7745c5c3_Err != nil {
18021812 return templ_7745c5c3_Err
18031813 }
1804- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 159, " ")
1814+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 160, " ")
18051815 if templ_7745c5c3_Err != nil {
18061816 return templ_7745c5c3_Err
18071817 }
@@ -1809,39 +1819,39 @@ func mrRail(p MRPage) templ.Component {
18091819 var templ_7745c5c3_Var91 string
18101820 templ_7745c5c3_Var91, templ_7745c5c3_Err = templ.JoinStringErrs(" · ")
18111821 if templ_7745c5c3_Err != nil {
1812- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 324, Col: 15}
1822+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 327, Col: 15}
18131823 }
18141824 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var91))
18151825 if templ_7745c5c3_Err != nil {
18161826 return templ_7745c5c3_Err
18171827 }
1818- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 160, "<time datetime=\"")
1828+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 161, "<time datetime=\"")
18191829 if templ_7745c5c3_Err != nil {
18201830 return templ_7745c5c3_Err
18211831 }
18221832 var templ_7745c5c3_Var92 string
18231833 templ_7745c5c3_Var92, templ_7745c5c3_Err = templ.ResolveAttributeValue(c.WhenAt)
18241834 if templ_7745c5c3_Err != nil {
1825- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 324, Col: 42}
1835+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 327, Col: 42}
18261836 }
18271837 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var92)
18281838 if templ_7745c5c3_Err != nil {
18291839 return templ_7745c5c3_Err
18301840 }
1831- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 161, "\">")
1841+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 162, "\">")
18321842 if templ_7745c5c3_Err != nil {
18331843 return templ_7745c5c3_Err
18341844 }
18351845 var templ_7745c5c3_Var93 string
18361846 templ_7745c5c3_Var93, templ_7745c5c3_Err = templ.JoinStringErrs(c.When)
18371847 if templ_7745c5c3_Err != nil {
1838- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 324, Col: 53}
1848+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 327, Col: 53}
18391849 }
18401850 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var93))
18411851 if templ_7745c5c3_Err != nil {
18421852 return templ_7745c5c3_Err
18431853 }
1844- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 162, "</time> ")
1854+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 163, "</time> ")
18451855 if templ_7745c5c3_Err != nil {
18461856 return templ_7745c5c3_Err
18471857 }
@@ -1850,76 +1860,76 @@ func mrRail(p MRPage) templ.Component {
18501860 var templ_7745c5c3_Var94 string
18511861 templ_7745c5c3_Var94, templ_7745c5c3_Err = templ.JoinStringErrs(" · new")
18521862 if templ_7745c5c3_Err != nil {
1853- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 327, Col: 18}
1863+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 330, Col: 18}
18541864 }
18551865 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var94))
18561866 if templ_7745c5c3_Err != nil {
18571867 return templ_7745c5c3_Err
18581868 }
18591869 }
1860- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 163, "</span></li>")
1870+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 164, "</span></li>")
18611871 if templ_7745c5c3_Err != nil {
18621872 return templ_7745c5c3_Err
18631873 }
18641874 }
1865- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 164, "</ul>")
1875+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 165, "</ul>")
18661876 if templ_7745c5c3_Err != nil {
18671877 return templ_7745c5c3_Err
18681878 }
18691879 if len(p.Commits) == 0 {
1870- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 165, "<p class=\"dim\">no commit to merge.</p>")
1880+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 166, "<p class=\"dim\">no commit to merge.</p>")
18711881 if templ_7745c5c3_Err != nil {
18721882 return templ_7745c5c3_Err
18731883 }
18741884 }
18751885 if p.CommitsNote != "" {
1876- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 166, "<p class=\"note\">")
1886+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 167, "<p class=\"note\">")
18771887 if templ_7745c5c3_Err != nil {
18781888 return templ_7745c5c3_Err
18791889 }
18801890 var templ_7745c5c3_Var95 string
18811891 templ_7745c5c3_Var95, templ_7745c5c3_Err = templ.JoinStringErrs(p.CommitsNote)
18821892 if templ_7745c5c3_Err != nil {
1883- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 337, Col: 34}
1893+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 340, Col: 34}
18841894 }
18851895 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var95))
18861896 if templ_7745c5c3_Err != nil {
18871897 return templ_7745c5c3_Err
18881898 }
1889- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 167, "</p>")
1899+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 168, "</p>")
18901900 if templ_7745c5c3_Err != nil {
18911901 return templ_7745c5c3_Err
18921902 }
18931903 }
1894- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 168, "</section><section aria-labelledby=\"r-settings\"><h2 id=\"r-settings\">Settings</h2><dl class=\"kv\"><dt>modes</dt><dd>")
1904+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 169, "</section><section aria-labelledby=\"r-settings\"><h2 id=\"r-settings\">Settings</h2><dl class=\"kv\"><dt>modes</dt><dd>")
18951905 if templ_7745c5c3_Err != nil {
18961906 return templ_7745c5c3_Err
18971907 }
18981908 var templ_7745c5c3_Var96 string
18991909 templ_7745c5c3_Var96, templ_7745c5c3_Err = templ.JoinStringErrs(strings.Join(p.Modes, ", "))
19001910 if templ_7745c5c3_Err != nil {
1901- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 344, Col: 36}
1911+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 347, Col: 36}
19021912 }
19031913 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var96))
19041914 if templ_7745c5c3_Err != nil {
19051915 return templ_7745c5c3_Err
19061916 }
1907- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 169, "</dd><dt>checks</dt><dd>")
1917+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 170, "</dd><dt>checks</dt><dd>")
19081918 if templ_7745c5c3_Err != nil {
19091919 return templ_7745c5c3_Err
19101920 }
19111921 if p.ChecksBlock {
1912- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 170, "failing ones block the merge")
1922+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 171, "failing ones block the merge")
19131923 if templ_7745c5c3_Err != nil {
19141924 return templ_7745c5c3_Err
19151925 }
19161926 } else {
1917- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 171, "do not block the merge")
1927+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 172, "do not block the merge")
19181928 if templ_7745c5c3_Err != nil {
19191929 return templ_7745c5c3_Err
19201930 }
19211931 }
1922- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 172, "</dd></dl></section>")
1932+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 173, "</dd></dl></section>")
19231933 if templ_7745c5c3_Err != nil {
19241934 return templ_7745c5c3_Err
19251935 }
@@ -1952,46 +1962,46 @@ func mrBar(p MRPage) templ.Component {
19521962 templ_7745c5c3_Var97 = templ.NopComponent
19531963 }
19541964 ctx = templ.ClearChildren(ctx)
1955- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 173, "<div class=\"diff-tools mr-bar\" role=\"group\" aria-label=\"Diff view and merge\"><span class=\"dim\">")
1965+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 174, "<div class=\"diff-tools mr-bar\" role=\"group\" aria-label=\"Diff view and merge\"><span class=\"dim\">")
19561966 if templ_7745c5c3_Err != nil {
19571967 return templ_7745c5c3_Err
19581968 }
19591969 var templ_7745c5c3_Var98 string
19601970 templ_7745c5c3_Var98, templ_7745c5c3_Err = templ.JoinStringErrs(plural(p.NFiles, "file", "files"))
19611971 if templ_7745c5c3_Err != nil {
1962- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 363, Col: 55}
1972+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 366, Col: 55}
19631973 }
19641974 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var98))
19651975 if templ_7745c5c3_Err != nil {
19661976 return templ_7745c5c3_Err
19671977 }
1968- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 174, " · <span class=\"plus\">+")
1978+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 175, " · <span class=\"plus\">+")
19691979 if templ_7745c5c3_Err != nil {
19701980 return templ_7745c5c3_Err
19711981 }
19721982 var templ_7745c5c3_Var99 string
19731983 templ_7745c5c3_Var99, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.Adds))
19741984 if templ_7745c5c3_Err != nil {
1975- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 363, Col: 95}
1985+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 366, Col: 95}
19761986 }
19771987 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var99))
19781988 if templ_7745c5c3_Err != nil {
19791989 return templ_7745c5c3_Err
19801990 }
1981- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 175, "</span> <span class=\"minus\">-")
1991+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 176, "</span> <span class=\"minus\">-")
19821992 if templ_7745c5c3_Err != nil {
19831993 return templ_7745c5c3_Err
19841994 }
19851995 var templ_7745c5c3_Var100 string
19861996 templ_7745c5c3_Var100, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.Dels))
19871997 if templ_7745c5c3_Err != nil {
1988- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 363, Col: 140}
1998+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 366, Col: 140}
19891999 }
19902000 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var100))
19912001 if templ_7745c5c3_Err != nil {
19922002 return templ_7745c5c3_Err
19932003 }
1994- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 176, "</span></span>")
2004+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 177, "</span></span>")
19952005 if templ_7745c5c3_Err != nil {
19962006 return templ_7745c5c3_Err
19972007 }
@@ -2007,7 +2017,7 @@ func mrBar(p MRPage) templ.Component {
20072017 if templ_7745c5c3_Err != nil {
20082018 return templ_7745c5c3_Err
20092019 }
2010- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 177, "<span class=\"grow\"></span>")
2020+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 178, "<span class=\"grow\"></span>")
20112021 if templ_7745c5c3_Err != nil {
20122022 return templ_7745c5c3_Err
20132023 }
@@ -2020,7 +2030,7 @@ func mrBar(p MRPage) templ.Component {
20202030 if templ_7745c5c3_Err != nil {
20212031 return templ_7745c5c3_Err
20222032 }
2023- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 178, " ")
2033+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 179, " ")
20242034 if templ_7745c5c3_Err != nil {
20252035 return templ_7745c5c3_Err
20262036 }
@@ -2029,7 +2039,7 @@ func mrBar(p MRPage) templ.Component {
20292039 return templ_7745c5c3_Err
20302040 }
20312041 }
2032- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 179, "</div>")
2042+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 180, "</div>")
20332043 if templ_7745c5c3_Err != nil {
20342044 return templ_7745c5c3_Err
20352045 }
@@ -2061,27 +2071,27 @@ func mergeMenu(p MRPage) templ.Component {
20612071 templ_7745c5c3_Var101 = templ.NopComponent
20622072 }
20632073 ctx = templ.ClearChildren(ctx)
2064- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 180, "<details class=\"menu mmenu\" id=\"merge-menu\" data-state=\"open\"><summary class=\"btn primary\" aria-keyshortcuts=\"Shift+M\">")
2074+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 181, "<details class=\"menu mmenu\" id=\"merge-menu\" data-state=\"open\"><summary class=\"btn primary\" aria-keyshortcuts=\"Shift+M\">")
20652075 if templ_7745c5c3_Err != nil {
20662076 return templ_7745c5c3_Err
20672077 }
20682078 if p.Box.ReadyAction != "" {
2069- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 181, "Draft ")
2079+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 182, "Draft ")
20702080 if templ_7745c5c3_Err != nil {
20712081 return templ_7745c5c3_Err
20722082 }
20732083 } else {
2074- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 182, "Merge ")
2084+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 183, "Merge ")
20752085 if templ_7745c5c3_Err != nil {
20762086 return templ_7745c5c3_Err
20772087 }
20782088 }
2079- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 183, "<kbd aria-hidden=\"true\">M</kbd></summary><div class=\"menu-pop\" role=\"group\" aria-label=\"Merge\"><dl class=\"kv\"><dt>head</dt><dd>")
2089+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 184, "<kbd aria-hidden=\"true\">M</kbd></summary><div class=\"menu-pop\" role=\"group\" aria-label=\"Merge\"><dl class=\"kv\"><dt>head</dt><dd>")
20802090 if templ_7745c5c3_Err != nil {
20812091 return templ_7745c5c3_Err
20822092 }
20832093 if p.Box.HeadGone {
2084- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 184, "gone: the source branch was deleted")
2094+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 185, "gone: the source branch was deleted")
20852095 if templ_7745c5c3_Err != nil {
20862096 return templ_7745c5c3_Err
20872097 }
@@ -2089,186 +2099,186 @@ func mergeMenu(p MRPage) templ.Component {
20892099 var templ_7745c5c3_Var102 string
20902100 templ_7745c5c3_Var102, templ_7745c5c3_Err = templ.JoinStringErrs(p.HeadShort)
20912101 if templ_7745c5c3_Err != nil {
2092- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 396, Col: 19}
2102+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 399, Col: 19}
20932103 }
20942104 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var102))
20952105 if templ_7745c5c3_Err != nil {
20962106 return templ_7745c5c3_Err
20972107 }
20982108 }
2099- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 185, "</dd><dt>into</dt><dd>")
2109+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 186, "</dd><dt>into</dt><dd>")
21002110 if templ_7745c5c3_Err != nil {
21012111 return templ_7745c5c3_Err
21022112 }
21032113 var templ_7745c5c3_Var103 string
21042114 templ_7745c5c3_Var103, templ_7745c5c3_Err = templ.JoinStringErrs(p.Target)
21052115 if templ_7745c5c3_Err != nil {
2106- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 400, Col: 18}
2116+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 403, Col: 18}
21072117 }
21082118 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var103))
21092119 if templ_7745c5c3_Err != nil {
21102120 return templ_7745c5c3_Err
21112121 }
2112- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 186, "</dd></dl>")
2122+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 187, "</dd></dl>")
21132123 if templ_7745c5c3_Err != nil {
21142124 return templ_7745c5c3_Err
21152125 }
21162126 if p.Box.ReadyAction != "" {
2117- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 187, "<p class=\"d-draft\">this is a draft: it cannot be merged until it is ready for review.</p><form class=\"d-btns\" method=\"post\" action=\"")
2127+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 188, "<p class=\"d-draft\">this is a draft: it cannot be merged until it is ready for review.</p><form class=\"d-btns\" method=\"post\" action=\"")
21182128 if templ_7745c5c3_Err != nil {
21192129 return templ_7745c5c3_Err
21202130 }
21212131 var templ_7745c5c3_Var104 templ.SafeURL
21222132 templ_7745c5c3_Var104, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.Box.ReadyAction))
21232133 if templ_7745c5c3_Err != nil {
2124- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 404, Col: 80}
2134+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 407, Col: 80}
21252135 }
21262136 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var104))
21272137 if templ_7745c5c3_Err != nil {
21282138 return templ_7745c5c3_Err
21292139 }
2130- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 188, "\"><button type=\"submit\" class=\"btn primary\" data-default title=\"remove the draft prefix from the title\">Ready for review</button></form>")
2140+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 189, "\"><button type=\"submit\" class=\"btn primary\" data-default title=\"remove the draft prefix from the title\">Ready for review</button></form>")
21312141 if templ_7745c5c3_Err != nil {
21322142 return templ_7745c5c3_Err
21332143 }
21342144 } else if !p.Box.HeadGone {
2135- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 189, "<form class=\"d-acts\" method=\"post\" action=\"")
2145+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 190, "<form class=\"d-acts\" method=\"post\" action=\"")
21362146 if templ_7745c5c3_Err != nil {
21372147 return templ_7745c5c3_Err
21382148 }
21392149 var templ_7745c5c3_Var105 templ.SafeURL
21402150 templ_7745c5c3_Var105, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.Box.MergeAction))
21412151 if templ_7745c5c3_Err != nil {
2142- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 408, Col: 80}
2152+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 411, Col: 80}
21432153 }
21442154 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var105))
21452155 if templ_7745c5c3_Err != nil {
21462156 return templ_7745c5c3_Err
21472157 }
2148- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 190, "\"><input type=\"hidden\" name=\"head_id\" value=\"")
2158+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 191, "\"><input type=\"hidden\" name=\"head_id\" value=\"")
21492159 if templ_7745c5c3_Err != nil {
21502160 return templ_7745c5c3_Err
21512161 }
21522162 var templ_7745c5c3_Var106 string
21532163 templ_7745c5c3_Var106, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.Box.Head)
21542164 if templ_7745c5c3_Err != nil {
2155- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 409, Col: 59}
2165+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 412, Col: 59}
21562166 }
21572167 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var106)
21582168 if templ_7745c5c3_Err != nil {
21592169 return templ_7745c5c3_Err
21602170 }
2161- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 191, "\"><fieldset class=\"d-modes\"><legend class=\"sr\">merge mode</legend> ")
2171+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 192, "\"><fieldset class=\"d-modes\"><legend class=\"sr\">merge mode</legend> ")
21622172 if templ_7745c5c3_Err != nil {
21632173 return templ_7745c5c3_Err
21642174 }
21652175 for i, m := range p.Box.Modes {
2166- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 192, "<label><input type=\"radio\" name=\"mode\" value=\"")
2176+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 193, "<label><input type=\"radio\" name=\"mode\" value=\"")
21672177 if templ_7745c5c3_Err != nil {
21682178 return templ_7745c5c3_Err
21692179 }
21702180 var templ_7745c5c3_Var107 string
21712181 templ_7745c5c3_Var107, templ_7745c5c3_Err = templ.ResolveAttributeValue(m.Value)
21722182 if templ_7745c5c3_Err != nil {
2173- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 414, Col: 55}
2183+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 417, Col: 55}
21742184 }
21752185 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var107)
21762186 if templ_7745c5c3_Err != nil {
21772187 return templ_7745c5c3_Err
21782188 }
2179- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 193, "\"")
2189+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 194, "\"")
21802190 if templ_7745c5c3_Err != nil {
21812191 return templ_7745c5c3_Err
21822192 }
21832193 if i == 0 {
2184- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 194, " checked")
2194+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 195, " checked")
21852195 if templ_7745c5c3_Err != nil {
21862196 return templ_7745c5c3_Err
21872197 }
21882198 }
2189- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 195, "> ")
2199+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 196, "> ")
21902200 if templ_7745c5c3_Err != nil {
21912201 return templ_7745c5c3_Err
21922202 }
21932203 var templ_7745c5c3_Var108 string
21942204 templ_7745c5c3_Var108, templ_7745c5c3_Err = templ.JoinStringErrs(m.Label)
21952205 if templ_7745c5c3_Err != nil {
2196- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 415, Col: 17}
2206+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 418, Col: 17}
21972207 }
21982208 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var108))
21992209 if templ_7745c5c3_Err != nil {
22002210 return templ_7745c5c3_Err
22012211 }
2202- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 196, " ")
2212+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 197, " ")
22032213 if templ_7745c5c3_Err != nil {
22042214 return templ_7745c5c3_Err
22052215 }
22062216 if i < 9 {
2207- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 197, "<kbd aria-hidden=\"true\">")
2217+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 198, "<kbd aria-hidden=\"true\">")
22082218 if templ_7745c5c3_Err != nil {
22092219 return templ_7745c5c3_Err
22102220 }
22112221 var templ_7745c5c3_Var109 string
22122222 templ_7745c5c3_Var109, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(i + 1))
22132223 if templ_7745c5c3_Err != nil {
2214- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 417, Col: 46}
2224+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 420, Col: 46}
22152225 }
22162226 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var109))
22172227 if templ_7745c5c3_Err != nil {
22182228 return templ_7745c5c3_Err
22192229 }
2220- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 198, "</kbd>")
2230+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 199, "</kbd>")
22212231 if templ_7745c5c3_Err != nil {
22222232 return templ_7745c5c3_Err
22232233 }
22242234 }
2225- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 199, "</label>")
2235+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 200, "</label>")
22262236 if templ_7745c5c3_Err != nil {
22272237 return templ_7745c5c3_Err
22282238 }
22292239 }
2230- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 200, "</fieldset>")
2240+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 201, "</fieldset>")
22312241 if templ_7745c5c3_Err != nil {
22322242 return templ_7745c5c3_Err
22332243 }
22342244 if p.Box.CanDeleteBranch {
2235- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 201, "<label class=\"d-check\"><input type=\"checkbox\" name=\"delete_branch\" value=\"1\"> delete ")
2245+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 202, "<label class=\"d-check\"><input type=\"checkbox\" name=\"delete_branch\" value=\"1\"> delete ")
22362246 if templ_7745c5c3_Err != nil {
22372247 return templ_7745c5c3_Err
22382248 }
22392249 var templ_7745c5c3_Var110 string
22402250 templ_7745c5c3_Var110, templ_7745c5c3_Err = templ.JoinStringErrs(p.Source)
22412251 if templ_7745c5c3_Err != nil {
2242- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 423, Col: 102}
2252+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 426, Col: 102}
22432253 }
22442254 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var110))
22452255 if templ_7745c5c3_Err != nil {
22462256 return templ_7745c5c3_Err
22472257 }
2248- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 202, " after the merge <kbd aria-hidden=\"true\">D</kbd></label>")
2258+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 203, " after the merge <kbd aria-hidden=\"true\">D</kbd></label>")
22492259 if templ_7745c5c3_Err != nil {
22502260 return templ_7745c5c3_Err
22512261 }
22522262 }
2253- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 203, "<div class=\"d-btns\"><button type=\"submit\" class=\"btn primary\" data-default>Merge into ")
2263+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 204, "<div class=\"d-btns\"><button type=\"submit\" class=\"btn primary\" data-default>Merge into ")
22542264 if templ_7745c5c3_Err != nil {
22552265 return templ_7745c5c3_Err
22562266 }
22572267 var templ_7745c5c3_Var111 string
22582268 templ_7745c5c3_Var111, templ_7745c5c3_Err = templ.JoinStringErrs(p.Target)
22592269 if templ_7745c5c3_Err != nil {
2260- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 426, Col: 82}
2270+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 429, Col: 82}
22612271 }
22622272 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var111))
22632273 if templ_7745c5c3_Err != nil {
22642274 return templ_7745c5c3_Err
22652275 }
2266- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 204, "</button></div></form>")
2276+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 205, "</button></div></form>")
22672277 if templ_7745c5c3_Err != nil {
22682278 return templ_7745c5c3_Err
22692279 }
22702280 }
2271- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 205, "</div></details>")
2281+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 206, "</div></details>")
22722282 if templ_7745c5c3_Err != nil {
22732283 return templ_7745c5c3_Err
22742284 }
@@ -2299,61 +2309,61 @@ func moreMenu(p MRPage) templ.Component {
22992309 templ_7745c5c3_Var112 = templ.NopComponent
23002310 }
23012311 ctx = templ.ClearChildren(ctx)
2302- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 206, "<details class=\"menu omenu\"><summary class=\"btn icon\" aria-label=\"More actions\" title=\"more actions\">⋯</summary><div class=\"menu-pop\" role=\"group\" aria-label=\"More actions\">")
2312+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 207, "<details class=\"menu omenu\"><summary class=\"btn icon\" aria-label=\"More actions\" title=\"more actions\">⋯</summary><div class=\"menu-pop\" role=\"group\" aria-label=\"More actions\">")
23032313 if templ_7745c5c3_Err != nil {
23042314 return templ_7745c5c3_Err
23052315 }
23062316 if p.Box.CanMarkRead {
2307- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 207, "<form method=\"post\" action=\"")
2317+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 208, "<form method=\"post\" action=\"")
23082318 if templ_7745c5c3_Err != nil {
23092319 return templ_7745c5c3_Err
23102320 }
23112321 var templ_7745c5c3_Var113 templ.SafeURL
23122322 templ_7745c5c3_Var113, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.Box.ReadAction))
23132323 if templ_7745c5c3_Err != nil {
2314- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 441, Col: 64}
2324+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 444, Col: 64}
23152325 }
23162326 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var113))
23172327 if templ_7745c5c3_Err != nil {
23182328 return templ_7745c5c3_Err
23192329 }
2320- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 208, "\"><input type=\"hidden\" name=\"head_id\" value=\"")
2330+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 209, "\"><input type=\"hidden\" name=\"head_id\" value=\"")
23212331 if templ_7745c5c3_Err != nil {
23222332 return templ_7745c5c3_Err
23232333 }
23242334 var templ_7745c5c3_Var114 string
23252335 templ_7745c5c3_Var114, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.Box.Head)
23262336 if templ_7745c5c3_Err != nil {
2327- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 442, Col: 59}
2337+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 445, Col: 59}
23282338 }
23292339 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var114)
23302340 if templ_7745c5c3_Err != nil {
23312341 return templ_7745c5c3_Err
23322342 }
2333- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 209, "\"> <button type=\"submit\" title=\"the next visit can show only what changed after this head\" class=\"btn\" aria-keyshortcuts=\"Shift+R\" data-read>Mark read <kbd aria-hidden=\"true\">R</kbd></button></form>")
2343+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 210, "\"> <button type=\"submit\" title=\"the next visit can show only what changed after this head\" class=\"btn\" aria-keyshortcuts=\"Shift+R\" data-read>Mark read <kbd aria-hidden=\"true\">R</kbd></button></form>")
23342344 if templ_7745c5c3_Err != nil {
23352345 return templ_7745c5c3_Err
23362346 }
23372347 }
2338- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 210, "<form method=\"post\" action=\"")
2348+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 211, "<form method=\"post\" action=\"")
23392349 if templ_7745c5c3_Err != nil {
23402350 return templ_7745c5c3_Err
23412351 }
23422352 var templ_7745c5c3_Var115 templ.SafeURL
23432353 templ_7745c5c3_Var115, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.Box.CloseAction))
23442354 if templ_7745c5c3_Err != nil {
2345- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 446, Col: 64}
2355+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 449, Col: 64}
23462356 }
23472357 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var115))
23482358 if templ_7745c5c3_Err != nil {
23492359 return templ_7745c5c3_Err
23502360 }
2351- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 211, "\"><button type=\"submit\" title=\"close without merging; the branch is kept\" class=\"btn danger\">Close</button></form>")
2361+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 212, "\"><button type=\"submit\" title=\"close without merging; the branch is kept\" class=\"btn danger\">Close</button></form>")
23522362 if templ_7745c5c3_Err != nil {
23532363 return templ_7745c5c3_Err
23542364 }
23552365 if !p.Box.HeadGone && p.Box.ReadyAction == "" {
2356- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 212, "<details class=\"d-or\"><summary class=\"mute\">or from a terminal</summary>")
2366+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 213, "<details class=\"d-or\"><summary class=\"mute\">or from a terminal</summary>")
23572367 if templ_7745c5c3_Err != nil {
23582368 return templ_7745c5c3_Err
23592369 }
@@ -2361,12 +2371,12 @@ func moreMenu(p MRPage) templ.Component {
23612371 if templ_7745c5c3_Err != nil {
23622372 return templ_7745c5c3_Err
23632373 }
2364- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 213, "</details>")
2374+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 214, "</details>")
23652375 if templ_7745c5c3_Err != nil {
23662376 return templ_7745c5c3_Err
23672377 }
23682378 }
2369- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 214, "</div></details>")
2379+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 215, "</div></details>")
23702380 if templ_7745c5c3_Err != nil {
23712381 return templ_7745c5c3_Err
23722382 }
@@ -2407,263 +2417,263 @@ func Compare(l Layout, p ComparePage) templ.Component {
24072417 }()
24082418 }
24092419 ctx = templ.InitializeContext(ctx)
2410- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 215, "<header class=\"show mr-h\"><h1>")
2420+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 216, "<header class=\"show mr-h\"><h1>")
24112421 if templ_7745c5c3_Err != nil {
24122422 return templ_7745c5c3_Err
24132423 }
24142424 var templ_7745c5c3_Var118 string
24152425 templ_7745c5c3_Var118, templ_7745c5c3_Err = templ.JoinStringErrs(p.Source)
24162426 if templ_7745c5c3_Err != nil {
2417- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 462, Col: 17}
2427+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 465, Col: 17}
24182428 }
24192429 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var118))
24202430 if templ_7745c5c3_Err != nil {
24212431 return templ_7745c5c3_Err
24222432 }
2423- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 216, " → ")
2433+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 217, " → ")
24242434 if templ_7745c5c3_Err != nil {
24252435 return templ_7745c5c3_Err
24262436 }
24272437 var templ_7745c5c3_Var119 string
24282438 templ_7745c5c3_Var119, templ_7745c5c3_Err = templ.JoinStringErrs(p.Target)
24292439 if templ_7745c5c3_Err != nil {
2430- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 462, Col: 34}
2440+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 465, Col: 34}
24312441 }
24322442 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var119))
24332443 if templ_7745c5c3_Err != nil {
24342444 return templ_7745c5c3_Err
24352445 }
2436- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 217, "</h1><dl class=\"kv show-kv\"><dt>branch</dt><dd><a href=\"")
2446+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 218, "</h1><dl class=\"kv show-kv\"><dt>branch</dt><dd><a href=\"")
24372447 if templ_7745c5c3_Err != nil {
24382448 return templ_7745c5c3_Err
24392449 }
24402450 var templ_7745c5c3_Var120 templ.SafeURL
24412451 templ_7745c5c3_Var120, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.SourceHref))
24422452 if templ_7745c5c3_Err != nil {
2443- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 465, Col: 45}
2453+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 468, Col: 45}
24442454 }
24452455 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var120))
24462456 if templ_7745c5c3_Err != nil {
24472457 return templ_7745c5c3_Err
24482458 }
2449- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 218, "\">")
2459+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 219, "\">")
24502460 if templ_7745c5c3_Err != nil {
24512461 return templ_7745c5c3_Err
24522462 }
24532463 var templ_7745c5c3_Var121 string
24542464 templ_7745c5c3_Var121, templ_7745c5c3_Err = templ.JoinStringErrs(p.Source)
24552465 if templ_7745c5c3_Err != nil {
2456- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 465, Col: 58}
2466+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 468, Col: 58}
24572467 }
24582468 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var121))
24592469 if templ_7745c5c3_Err != nil {
24602470 return templ_7745c5c3_Err
24612471 }
2462- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 219, "</a></dd><dt>target</dt><dd><a href=\"")
2472+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 220, "</a></dd><dt>target</dt><dd><a href=\"")
24632473 if templ_7745c5c3_Err != nil {
24642474 return templ_7745c5c3_Err
24652475 }
24662476 var templ_7745c5c3_Var122 templ.SafeURL
24672477 templ_7745c5c3_Var122, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.TargetHref))
24682478 if templ_7745c5c3_Err != nil {
2469- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 467, Col: 45}
2479+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 470, Col: 45}
24702480 }
24712481 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var122))
24722482 if templ_7745c5c3_Err != nil {
24732483 return templ_7745c5c3_Err
24742484 }
2475- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 220, "\">")
2485+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 221, "\">")
24762486 if templ_7745c5c3_Err != nil {
24772487 return templ_7745c5c3_Err
24782488 }
24792489 var templ_7745c5c3_Var123 string
24802490 templ_7745c5c3_Var123, templ_7745c5c3_Err = templ.JoinStringErrs(p.Target)
24812491 if templ_7745c5c3_Err != nil {
2482- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 467, Col: 58}
2492+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 470, Col: 58}
24832493 }
24842494 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var123))
24852495 if templ_7745c5c3_Err != nil {
24862496 return templ_7745c5c3_Err
24872497 }
2488- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 221, "</a></dd><dt>ahead</dt><dd>")
2498+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 222, "</a></dd><dt>ahead</dt><dd>")
24892499 if templ_7745c5c3_Err != nil {
24902500 return templ_7745c5c3_Err
24912501 }
24922502 var templ_7745c5c3_Var124 string
24932503 templ_7745c5c3_Var124, templ_7745c5c3_Err = templ.JoinStringErrs(p.AheadText)
24942504 if templ_7745c5c3_Err != nil {
2495- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 469, Col: 21}
2505+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 472, Col: 21}
24962506 }
24972507 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var124))
24982508 if templ_7745c5c3_Err != nil {
24992509 return templ_7745c5c3_Err
25002510 }
2501- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 222, "</dd></dl></header>")
2511+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 223, "</dd></dl></header>")
25022512 if templ_7745c5c3_Err != nil {
25032513 return templ_7745c5c3_Err
25042514 }
25052515 if p.Note != "" {
2506- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 223, "<p class=\"notice\">")
2516+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 224, "<p class=\"notice\">")
25072517 if templ_7745c5c3_Err != nil {
25082518 return templ_7745c5c3_Err
25092519 }
25102520 var templ_7745c5c3_Var125 string
25112521 templ_7745c5c3_Var125, templ_7745c5c3_Err = templ.JoinStringErrs(p.Note)
25122522 if templ_7745c5c3_Err != nil {
2513- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 473, Col: 29}
2523+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 476, Col: 29}
25142524 }
25152525 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var125))
25162526 if templ_7745c5c3_Err != nil {
25172527 return templ_7745c5c3_Err
25182528 }
2519- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 224, "</p>")
2529+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 225, "</p>")
25202530 if templ_7745c5c3_Err != nil {
25212531 return templ_7745c5c3_Err
25222532 }
25232533 }
2524- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 225, " ")
2534+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 226, " ")
25252535 if templ_7745c5c3_Err != nil {
25262536 return templ_7745c5c3_Err
25272537 }
25282538 if p.Existing != nil {
2529- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 226, "<p class=\"notice\">an open merge request already covers these branches: <a href=\"")
2539+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 227, "<p class=\"notice\">an open merge request already covers these branches: <a href=\"")
25302540 if templ_7745c5c3_Err != nil {
25312541 return templ_7745c5c3_Err
25322542 }
25332543 var templ_7745c5c3_Var126 templ.SafeURL
25342544 templ_7745c5c3_Var126, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.Existing.Href))
25352545 if templ_7745c5c3_Err != nil {
2536- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 476, Col: 114}
2546+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 479, Col: 114}
25372547 }
25382548 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var126))
25392549 if templ_7745c5c3_Err != nil {
25402550 return templ_7745c5c3_Err
25412551 }
2542- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 227, "\">")
2552+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 228, "\">")
25432553 if templ_7745c5c3_Err != nil {
25442554 return templ_7745c5c3_Err
25452555 }
25462556 var templ_7745c5c3_Var127 string
25472557 templ_7745c5c3_Var127, templ_7745c5c3_Err = templ.JoinStringErrs(p.Existing.Label)
25482558 if templ_7745c5c3_Err != nil {
2549- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 476, Col: 135}
2559+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 479, Col: 135}
25502560 }
25512561 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var127))
25522562 if templ_7745c5c3_Err != nil {
25532563 return templ_7745c5c3_Err
25542564 }
2555- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 228, "</a></p>")
2565+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 229, "</a></p>")
25562566 if templ_7745c5c3_Err != nil {
25572567 return templ_7745c5c3_Err
25582568 }
25592569 }
2560- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 229, " ")
2570+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 230, " ")
25612571 if templ_7745c5c3_Err != nil {
25622572 return templ_7745c5c3_Err
25632573 }
25642574 if p.Create != nil {
2565- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 230, "<form class=\"cform create\" method=\"post\" action=\"")
2575+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 231, "<form class=\"cform create\" method=\"post\" action=\"")
25662576 if templ_7745c5c3_Err != nil {
25672577 return templ_7745c5c3_Err
25682578 }
25692579 var templ_7745c5c3_Var128 templ.SafeURL
25702580 templ_7745c5c3_Var128, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.Create.Action))
25712581 if templ_7745c5c3_Err != nil {
2572- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 479, Col: 83}
2582+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 482, Col: 83}
25732583 }
25742584 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var128))
25752585 if templ_7745c5c3_Err != nil {
25762586 return templ_7745c5c3_Err
25772587 }
2578- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 231, "\"><input type=\"hidden\" name=\"source\" value=\"")
2588+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 232, "\"><input type=\"hidden\" name=\"source\" value=\"")
25792589 if templ_7745c5c3_Err != nil {
25802590 return templ_7745c5c3_Err
25812591 }
25822592 var templ_7745c5c3_Var129 string
25832593 templ_7745c5c3_Var129, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.Create.Source)
25842594 if templ_7745c5c3_Err != nil {
2585- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 480, Col: 62}
2595+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 483, Col: 62}
25862596 }
25872597 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var129)
25882598 if templ_7745c5c3_Err != nil {
25892599 return templ_7745c5c3_Err
25902600 }
2591- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 232, "\"> <input type=\"hidden\" name=\"target\" value=\"")
2601+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 233, "\"> <input type=\"hidden\" name=\"target\" value=\"")
25922602 if templ_7745c5c3_Err != nil {
25932603 return templ_7745c5c3_Err
25942604 }
25952605 var templ_7745c5c3_Var130 string
25962606 templ_7745c5c3_Var130, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.Create.Target)
25972607 if templ_7745c5c3_Err != nil {
2598- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 481, Col: 62}
2608+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 484, Col: 62}
25992609 }
26002610 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var130)
26012611 if templ_7745c5c3_Err != nil {
26022612 return templ_7745c5c3_Err
26032613 }
2604- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 233, "\"> <label for=\"mr-title\">title</label> <input id=\"mr-title\" name=\"title\" type=\"text\" maxlength=\"120\" required value=\"")
2614+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 234, "\"> <label for=\"mr-title\">title</label> <input id=\"mr-title\" name=\"title\" type=\"text\" maxlength=\"120\" required value=\"")
26052615 if templ_7745c5c3_Err != nil {
26062616 return templ_7745c5c3_Err
26072617 }
26082618 var templ_7745c5c3_Var131 string
26092619 templ_7745c5c3_Var131, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.Create.Title)
26102620 if templ_7745c5c3_Err != nil {
2611- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 483, Col: 97}
2621+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 486, Col: 97}
26122622 }
26132623 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var131)
26142624 if templ_7745c5c3_Err != nil {
26152625 return templ_7745c5c3_Err
26162626 }
2617- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 234, "\" autocomplete=\"off\"> <label for=\"mr-desc\">description</label> <textarea id=\"mr-desc\" name=\"description\" rows=\"4\" maxlength=\"8000\" placeholder=\"Markdown, optional\"></textarea><div class=\"f-btns\"><button type=\"submit\" class=\"btn primary\">Create merge request</button></div></form>")
2627+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 235, "\" autocomplete=\"off\"> <label for=\"mr-desc\">description</label> <textarea id=\"mr-desc\" name=\"description\" rows=\"4\" maxlength=\"8000\" placeholder=\"Markdown, optional\"></textarea><div class=\"f-btns\"><button type=\"submit\" class=\"btn primary\">Create merge request</button></div></form>")
26182628 if templ_7745c5c3_Err != nil {
26192629 return templ_7745c5c3_Err
26202630 }
26212631 }
2622- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 235, " ")
2632+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 236, " ")
26232633 if templ_7745c5c3_Err != nil {
26242634 return templ_7745c5c3_Err
26252635 }
26262636 if p.HasDiff {
2627- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 236, "<div class=\"diff-tools\" role=\"group\" aria-label=\"Diff view\"><span class=\"dim\">")
2637+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 237, "<div class=\"diff-tools\" role=\"group\" aria-label=\"Diff view\"><span class=\"dim\">")
26282638 if templ_7745c5c3_Err != nil {
26292639 return templ_7745c5c3_Err
26302640 }
26312641 var templ_7745c5c3_Var132 string
26322642 templ_7745c5c3_Var132, templ_7745c5c3_Err = templ.JoinStringErrs(plural(p.NFiles, "file", "files"))
26332643 if templ_7745c5c3_Err != nil {
2634- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 493, Col: 57}
2644+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 496, Col: 57}
26352645 }
26362646 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var132))
26372647 if templ_7745c5c3_Err != nil {
26382648 return templ_7745c5c3_Err
26392649 }
2640- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 237, " · <span class=\"plus\">+")
2650+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 238, " · <span class=\"plus\">+")
26412651 if templ_7745c5c3_Err != nil {
26422652 return templ_7745c5c3_Err
26432653 }
26442654 var templ_7745c5c3_Var133 string
26452655 templ_7745c5c3_Var133, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.Adds))
26462656 if templ_7745c5c3_Err != nil {
2647- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 493, Col: 97}
2657+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 496, Col: 97}
26482658 }
26492659 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var133))
26502660 if templ_7745c5c3_Err != nil {
26512661 return templ_7745c5c3_Err
26522662 }
2653- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 238, "</span> <span class=\"minus\">-")
2663+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 239, "</span> <span class=\"minus\">-")
26542664 if templ_7745c5c3_Err != nil {
26552665 return templ_7745c5c3_Err
26562666 }
26572667 var templ_7745c5c3_Var134 string
26582668 templ_7745c5c3_Var134, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.Dels))
26592669 if templ_7745c5c3_Err != nil {
2660- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 493, Col: 142}
2670+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 496, Col: 142}
26612671 }
26622672 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var134))
26632673 if templ_7745c5c3_Err != nil {
26642674 return templ_7745c5c3_Err
26652675 }
2666- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 239, "</span></span> <span class=\"grow\"></span>")
2676+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 240, "</span></span> <span class=\"grow\"></span>")
26672677 if templ_7745c5c3_Err != nil {
26682678 return templ_7745c5c3_Err
26692679 }
@@ -2679,64 +2689,64 @@ func Compare(l Layout, p ComparePage) templ.Component {
26792689 if templ_7745c5c3_Err != nil {
26802690 return templ_7745c5c3_Err
26812691 }
2682- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 240, "</div>")
2692+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 241, "</div>")
26832693 if templ_7745c5c3_Err != nil {
26842694 return templ_7745c5c3_Err
26852695 }
26862696 if p.Invisible {
2687- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 241, "<p class=\"notice\">this diff holds invisible characters (direction controls, zero-width characters). They are shown as <span class=\"inv\">&lt;U+XXXX&gt;</span> markers, never applied.</p>")
2697+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 242, "<p class=\"notice\">this diff holds invisible characters (direction controls, zero-width characters). They are shown as <span class=\"inv\">&lt;U+XXXX&gt;</span> markers, never applied.</p>")
26882698 if templ_7745c5c3_Err != nil {
26892699 return templ_7745c5c3_Err
26902700 }
26912701 }
2692- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 242, " <div id=\"diffs\"")
2702+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 243, " <div id=\"diffs\"")
26932703 if templ_7745c5c3_Err != nil {
26942704 return templ_7745c5c3_Err
26952705 }
26962706 if p.Both {
2697- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 243, " data-diff=\"")
2707+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 244, " data-diff=\"")
26982708 if templ_7745c5c3_Err != nil {
26992709 return templ_7745c5c3_Err
27002710 }
27012711 var templ_7745c5c3_Var135 string
27022712 templ_7745c5c3_Var135, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.View)
27032713 if templ_7745c5c3_Err != nil {
2704- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 508, Col: 23}
2714+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 511, Col: 23}
27052715 }
27062716 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var135)
27072717 if templ_7745c5c3_Err != nil {
27082718 return templ_7745c5c3_Err
27092719 }
2710- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 244, "\"")
2720+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 245, "\"")
27112721 if templ_7745c5c3_Err != nil {
27122722 return templ_7745c5c3_Err
27132723 }
27142724 } else {
2715- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 245, " data-view=\"")
2725+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 246, " data-view=\"")
27162726 if templ_7745c5c3_Err != nil {
27172727 return templ_7745c5c3_Err
27182728 }
27192729 var templ_7745c5c3_Var136 string
27202730 templ_7745c5c3_Var136, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.View)
27212731 if templ_7745c5c3_Err != nil {
2722- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 510, Col: 23}
2732+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 513, Col: 23}
27232733 }
27242734 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var136)
27252735 if templ_7745c5c3_Err != nil {
27262736 return templ_7745c5c3_Err
27272737 }
2728- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 246, "\"")
2738+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 247, "\"")
27292739 if templ_7745c5c3_Err != nil {
27302740 return templ_7745c5c3_Err
27312741 }
27322742 }
27332743 if p.Both && !p.Pinned {
2734- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 247, " hx-live=\"this.dataset.diff = sessionStorage.getItem('diff') || this.dataset.diff\"")
2744+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 248, " hx-live=\"this.dataset.diff = sessionStorage.getItem('diff') || this.dataset.diff\"")
27352745 if templ_7745c5c3_Err != nil {
27362746 return templ_7745c5c3_Err
27372747 }
27382748 }
2739- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 248, ">")
2749+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 249, ">")
27402750 if templ_7745c5c3_Err != nil {
27412751 return templ_7745c5c3_Err
27422752 }
@@ -2746,7 +2756,7 @@ func Compare(l Layout, p ComparePage) templ.Component {
27462756 return templ_7745c5c3_Err
27472757 }
27482758 }
2749- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 249, "</div>")
2759+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 250, "</div>")
27502760 if templ_7745c5c3_Err != nil {
27512761 return templ_7745c5c3_Err
27522762 }
@@ -2782,77 +2792,77 @@ func compareRail(p ComparePage) templ.Component {
27822792 templ_7745c5c3_Var137 = templ.NopComponent
27832793 }
27842794 ctx = templ.ClearChildren(ctx)
2785- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 250, "<section aria-labelledby=\"r-ahead\"><h2 id=\"r-ahead\">Commits <span class=\"count\">")
2795+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 251, "<section aria-labelledby=\"r-ahead\"><h2 id=\"r-ahead\">Commits <span class=\"count\">")
27862796 if templ_7745c5c3_Err != nil {
27872797 return templ_7745c5c3_Err
27882798 }
27892799 var templ_7745c5c3_Var138 string
27902800 templ_7745c5c3_Var138, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(len(p.Ahead)))
27912801 if templ_7745c5c3_Err != nil {
2792- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 526, Col: 67}
2802+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 529, Col: 67}
27932803 }
27942804 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var138))
27952805 if templ_7745c5c3_Err != nil {
27962806 return templ_7745c5c3_Err
27972807 }
2798- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 251, "</span></h2><ul class=\"pcommits\">")
2808+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 252, "</span></h2><ul class=\"pcommits\">")
27992809 if templ_7745c5c3_Err != nil {
28002810 return templ_7745c5c3_Err
28012811 }
28022812 for _, c := range p.Ahead {
2803- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 252, "<li><a href=\"")
2813+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 253, "<li><a href=\"")
28042814 if templ_7745c5c3_Err != nil {
28052815 return templ_7745c5c3_Err
28062816 }
28072817 var templ_7745c5c3_Var139 templ.SafeURL
28082818 templ_7745c5c3_Var139, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(c.CHref))
28092819 if templ_7745c5c3_Err != nil {
2810- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 530, Col: 37}
2820+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 533, Col: 37}
28112821 }
28122822 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var139))
28132823 if templ_7745c5c3_Err != nil {
28142824 return templ_7745c5c3_Err
28152825 }
2816- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 253, "\">")
2826+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 254, "\">")
28172827 if templ_7745c5c3_Err != nil {
28182828 return templ_7745c5c3_Err
28192829 }
28202830 var templ_7745c5c3_Var140 string
28212831 templ_7745c5c3_Var140, templ_7745c5c3_Err = templ.JoinStringErrs(c.Short)
28222832 if templ_7745c5c3_Err != nil {
2823- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 530, Col: 49}
2833+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 533, Col: 49}
28242834 }
28252835 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var140))
28262836 if templ_7745c5c3_Err != nil {
28272837 return templ_7745c5c3_Err
28282838 }
2829- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 254, "</a> <span class=\"s\">")
2839+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 255, "</a> <span class=\"s\">")
28302840 if templ_7745c5c3_Err != nil {
28312841 return templ_7745c5c3_Err
28322842 }
28332843 var templ_7745c5c3_Var141 string
28342844 templ_7745c5c3_Var141, templ_7745c5c3_Err = templ.JoinStringErrs(c.Subject)
28352845 if templ_7745c5c3_Err != nil {
2836- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 531, Col: 32}
2846+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 534, Col: 32}
28372847 }
28382848 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var141))
28392849 if templ_7745c5c3_Err != nil {
28402850 return templ_7745c5c3_Err
28412851 }
2842- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 255, "</span> <span class=\"mute\">")
2852+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 256, "</span> <span class=\"mute\">")
28432853 if templ_7745c5c3_Err != nil {
28442854 return templ_7745c5c3_Err
28452855 }
28462856 var templ_7745c5c3_Var142 string
28472857 templ_7745c5c3_Var142, templ_7745c5c3_Err = templ.JoinStringErrs(c.Author)
28482858 if templ_7745c5c3_Err != nil {
2849- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 533, Col: 16}
2859+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 536, Col: 16}
28502860 }
28512861 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var142))
28522862 if templ_7745c5c3_Err != nil {
28532863 return templ_7745c5c3_Err
28542864 }
2855- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 256, " ")
2865+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 257, " ")
28562866 if templ_7745c5c3_Err != nil {
28572867 return templ_7745c5c3_Err
28582868 }
@@ -2860,90 +2870,90 @@ func compareRail(p ComparePage) templ.Component {
28602870 var templ_7745c5c3_Var143 string
28612871 templ_7745c5c3_Var143, templ_7745c5c3_Err = templ.JoinStringErrs(" · ")
28622872 if templ_7745c5c3_Err != nil {
2863- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 535, Col: 15}
2873+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 538, Col: 15}
28642874 }
28652875 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var143))
28662876 if templ_7745c5c3_Err != nil {
28672877 return templ_7745c5c3_Err
28682878 }
2869- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 257, "<time datetime=\"")
2879+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 258, "<time datetime=\"")
28702880 if templ_7745c5c3_Err != nil {
28712881 return templ_7745c5c3_Err
28722882 }
28732883 var templ_7745c5c3_Var144 string
28742884 templ_7745c5c3_Var144, templ_7745c5c3_Err = templ.ResolveAttributeValue(c.WhenAt)
28752885 if templ_7745c5c3_Err != nil {
2876- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 535, Col: 42}
2886+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 538, Col: 42}
28772887 }
28782888 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var144)
28792889 if templ_7745c5c3_Err != nil {
28802890 return templ_7745c5c3_Err
28812891 }
2882- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 258, "\">")
2892+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 259, "\">")
28832893 if templ_7745c5c3_Err != nil {
28842894 return templ_7745c5c3_Err
28852895 }
28862896 var templ_7745c5c3_Var145 string
28872897 templ_7745c5c3_Var145, templ_7745c5c3_Err = templ.JoinStringErrs(c.When)
28882898 if templ_7745c5c3_Err != nil {
2889- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 535, Col: 53}
2899+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 538, Col: 53}
28902900 }
28912901 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var145))
28922902 if templ_7745c5c3_Err != nil {
28932903 return templ_7745c5c3_Err
28942904 }
2895- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 259, "</time>")
2905+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 260, "</time>")
28962906 if templ_7745c5c3_Err != nil {
28972907 return templ_7745c5c3_Err
28982908 }
28992909 }
2900- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 260, "</span></li>")
2910+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 261, "</span></li>")
29012911 if templ_7745c5c3_Err != nil {
29022912 return templ_7745c5c3_Err
29032913 }
29042914 }
2905- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 261, "</ul>")
2915+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 262, "</ul>")
29062916 if templ_7745c5c3_Err != nil {
29072917 return templ_7745c5c3_Err
29082918 }
29092919 if len(p.Ahead) == 0 {
2910- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 262, "<p class=\"dim\">no commit ahead of ")
2920+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 263, "<p class=\"dim\">no commit ahead of ")
29112921 if templ_7745c5c3_Err != nil {
29122922 return templ_7745c5c3_Err
29132923 }
29142924 var templ_7745c5c3_Var146 string
29152925 templ_7745c5c3_Var146, templ_7745c5c3_Err = templ.JoinStringErrs(p.Target)
29162926 if templ_7745c5c3_Err != nil {
2917- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 542, Col: 47}
2927+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 545, Col: 47}
29182928 }
29192929 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var146))
29202930 if templ_7745c5c3_Err != nil {
29212931 return templ_7745c5c3_Err
29222932 }
2923- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 263, ".</p>")
2933+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 264, ".</p>")
29242934 if templ_7745c5c3_Err != nil {
29252935 return templ_7745c5c3_Err
29262936 }
29272937 }
2928- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 264, "</section>")
2938+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 265, "</section>")
29292939 if templ_7745c5c3_Err != nil {
29302940 return templ_7745c5c3_Err
29312941 }
29322942 if p.HasDiff {
2933- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 265, "<section aria-labelledby=\"r-files\"><h2 id=\"r-files\">Files <span class=\"count\">")
2943+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 266, "<section aria-labelledby=\"r-files\"><h2 id=\"r-files\">Files <span class=\"count\">")
29342944 if templ_7745c5c3_Err != nil {
29352945 return templ_7745c5c3_Err
29362946 }
29372947 var templ_7745c5c3_Var147 string
29382948 templ_7745c5c3_Var147, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(len(p.Files)))
29392949 if templ_7745c5c3_Err != nil {
2940- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 547, Col: 66}
2950+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 550, Col: 66}
29412951 }
29422952 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var147))
29432953 if templ_7745c5c3_Err != nil {
29442954 return templ_7745c5c3_Err
29452955 }
2946- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 266, "</span></h2>")
2956+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 267, "</span></h2>")
29472957 if templ_7745c5c3_Err != nil {
29482958 return templ_7745c5c3_Err
29492959 }
@@ -2951,12 +2961,12 @@ func compareRail(p ComparePage) templ.Component {
29512961 if templ_7745c5c3_Err != nil {
29522962 return templ_7745c5c3_Err
29532963 }
2954- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 267, "</section>")
2964+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 268, "</section>")
29552965 if templ_7745c5c3_Err != nil {
29562966 return templ_7745c5c3_Err
29572967 }
29582968 }
2959- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 268, "<section aria-labelledby=\"r-cli\"><h2 id=\"r-cli\">From a terminal</h2>")
2969+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 269, "<section aria-labelledby=\"r-cli\"><h2 id=\"r-cli\">From a terminal</h2>")
29602970 if templ_7745c5c3_Err != nil {
29612971 return templ_7745c5c3_Err
29622972 }
@@ -2964,7 +2974,7 @@ func compareRail(p ComparePage) templ.Component {
29642974 if templ_7745c5c3_Err != nil {
29652975 return templ_7745c5c3_Err
29662976 }
2967- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 269, "</section>")
2977+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 270, "</section>")
29682978 if templ_7745c5c3_Err != nil {
29692979 return templ_7745c5c3_Err
29702980 }
@@ -1788,20 +1788,30 @@ func mrRail(p MRPage) templ.Component {
1788 if templ_7745c5c3_Err != nil {1788 if templ_7745c5c3_Err != nil {
1789 return templ_7745c5c3_Err1789 return templ_7745c5c3_Err
1790 }1790 }
1791- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 158, "</span> <span class=\"mute\">")1791+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 158, "</span> ")
1792+ if templ_7745c5c3_Err != nil {
1793+ return templ_7745c5c3_Err
1794+ }
1795+ if c.Sig != nil {
1796+ templ_7745c5c3_Err = signaturePill(c.Sig).Render(ctx, templ_7745c5c3_Buffer)
1797+ if templ_7745c5c3_Err != nil {
1798+ return templ_7745c5c3_Err
1799+ }
1800+ }
1801+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 159, "<span class=\"mute\">")
1792 if templ_7745c5c3_Err != nil {1802 if templ_7745c5c3_Err != nil {
1793 return templ_7745c5c3_Err1803 return templ_7745c5c3_Err
1794 }1804 }
1795 var templ_7745c5c3_Var90 string1805 var templ_7745c5c3_Var90 string
1796 templ_7745c5c3_Var90, templ_7745c5c3_Err = templ.JoinStringErrs(c.Author)1806 templ_7745c5c3_Var90, templ_7745c5c3_Err = templ.JoinStringErrs(c.Author)
1797 if templ_7745c5c3_Err != nil {1807 if templ_7745c5c3_Err != nil {
1798- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 322, Col: 16}1808+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 325, Col: 16}
1799 }1809 }
1800 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var90))1810 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var90))
1801 if templ_7745c5c3_Err != nil {1811 if templ_7745c5c3_Err != nil {
1802 return templ_7745c5c3_Err1812 return templ_7745c5c3_Err
1803 }1813 }
1804- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 159, " ")1814+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 160, " ")
1805 if templ_7745c5c3_Err != nil {1815 if templ_7745c5c3_Err != nil {
1806 return templ_7745c5c3_Err1816 return templ_7745c5c3_Err
1807 }1817 }
@@ -1809,39 +1819,39 @@ func mrRail(p MRPage) templ.Component {
1809 var templ_7745c5c3_Var91 string1819 var templ_7745c5c3_Var91 string
1810 templ_7745c5c3_Var91, templ_7745c5c3_Err = templ.JoinStringErrs(" · ")1820 templ_7745c5c3_Var91, templ_7745c5c3_Err = templ.JoinStringErrs(" · ")
1811 if templ_7745c5c3_Err != nil {1821 if templ_7745c5c3_Err != nil {
1812- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 324, Col: 15}1822+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 327, Col: 15}
1813 }1823 }
1814 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var91))1824 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var91))
1815 if templ_7745c5c3_Err != nil {1825 if templ_7745c5c3_Err != nil {
1816 return templ_7745c5c3_Err1826 return templ_7745c5c3_Err
1817 }1827 }
1818- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 160, "<time datetime=\"")1828+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 161, "<time datetime=\"")
1819 if templ_7745c5c3_Err != nil {1829 if templ_7745c5c3_Err != nil {
1820 return templ_7745c5c3_Err1830 return templ_7745c5c3_Err
1821 }1831 }
1822 var templ_7745c5c3_Var92 string1832 var templ_7745c5c3_Var92 string
1823 templ_7745c5c3_Var92, templ_7745c5c3_Err = templ.ResolveAttributeValue(c.WhenAt)1833 templ_7745c5c3_Var92, templ_7745c5c3_Err = templ.ResolveAttributeValue(c.WhenAt)
1824 if templ_7745c5c3_Err != nil {1834 if templ_7745c5c3_Err != nil {
1825- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 324, Col: 42}1835+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 327, Col: 42}
1826 }1836 }
1827 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var92)1837 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var92)
1828 if templ_7745c5c3_Err != nil {1838 if templ_7745c5c3_Err != nil {
1829 return templ_7745c5c3_Err1839 return templ_7745c5c3_Err
1830 }1840 }
1831- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 161, "\">")1841+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 162, "\">")
1832 if templ_7745c5c3_Err != nil {1842 if templ_7745c5c3_Err != nil {
1833 return templ_7745c5c3_Err1843 return templ_7745c5c3_Err
1834 }1844 }
1835 var templ_7745c5c3_Var93 string1845 var templ_7745c5c3_Var93 string
1836 templ_7745c5c3_Var93, templ_7745c5c3_Err = templ.JoinStringErrs(c.When)1846 templ_7745c5c3_Var93, templ_7745c5c3_Err = templ.JoinStringErrs(c.When)
1837 if templ_7745c5c3_Err != nil {1847 if templ_7745c5c3_Err != nil {
1838- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 324, Col: 53}1848+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 327, Col: 53}
1839 }1849 }
1840 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var93))1850 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var93))
1841 if templ_7745c5c3_Err != nil {1851 if templ_7745c5c3_Err != nil {
1842 return templ_7745c5c3_Err1852 return templ_7745c5c3_Err
1843 }1853 }
1844- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 162, "</time> ")1854+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 163, "</time> ")
1845 if templ_7745c5c3_Err != nil {1855 if templ_7745c5c3_Err != nil {
1846 return templ_7745c5c3_Err1856 return templ_7745c5c3_Err
1847 }1857 }
@@ -1850,76 +1860,76 @@ func mrRail(p MRPage) templ.Component {
1850 var templ_7745c5c3_Var94 string1860 var templ_7745c5c3_Var94 string
1851 templ_7745c5c3_Var94, templ_7745c5c3_Err = templ.JoinStringErrs(" · new")1861 templ_7745c5c3_Var94, templ_7745c5c3_Err = templ.JoinStringErrs(" · new")
1852 if templ_7745c5c3_Err != nil {1862 if templ_7745c5c3_Err != nil {
1853- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 327, Col: 18}1863+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 330, Col: 18}
1854 }1864 }
1855 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var94))1865 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var94))
1856 if templ_7745c5c3_Err != nil {1866 if templ_7745c5c3_Err != nil {
1857 return templ_7745c5c3_Err1867 return templ_7745c5c3_Err
1858 }1868 }
1859 }1869 }
1860- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 163, "</span></li>")1870+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 164, "</span></li>")
1861 if templ_7745c5c3_Err != nil {1871 if templ_7745c5c3_Err != nil {
1862 return templ_7745c5c3_Err1872 return templ_7745c5c3_Err
1863 }1873 }
1864 }1874 }
1865- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 164, "</ul>")1875+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 165, "</ul>")
1866 if templ_7745c5c3_Err != nil {1876 if templ_7745c5c3_Err != nil {
1867 return templ_7745c5c3_Err1877 return templ_7745c5c3_Err
1868 }1878 }
1869 if len(p.Commits) == 0 {1879 if len(p.Commits) == 0 {
1870- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 165, "<p class=\"dim\">no commit to merge.</p>")1880+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 166, "<p class=\"dim\">no commit to merge.</p>")
1871 if templ_7745c5c3_Err != nil {1881 if templ_7745c5c3_Err != nil {
1872 return templ_7745c5c3_Err1882 return templ_7745c5c3_Err
1873 }1883 }
1874 }1884 }
1875 if p.CommitsNote != "" {1885 if p.CommitsNote != "" {
1876- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 166, "<p class=\"note\">")1886+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 167, "<p class=\"note\">")
1877 if templ_7745c5c3_Err != nil {1887 if templ_7745c5c3_Err != nil {
1878 return templ_7745c5c3_Err1888 return templ_7745c5c3_Err
1879 }1889 }
1880 var templ_7745c5c3_Var95 string1890 var templ_7745c5c3_Var95 string
1881 templ_7745c5c3_Var95, templ_7745c5c3_Err = templ.JoinStringErrs(p.CommitsNote)1891 templ_7745c5c3_Var95, templ_7745c5c3_Err = templ.JoinStringErrs(p.CommitsNote)
1882 if templ_7745c5c3_Err != nil {1892 if templ_7745c5c3_Err != nil {
1883- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 337, Col: 34}1893+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 340, Col: 34}
1884 }1894 }
1885 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var95))1895 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var95))
1886 if templ_7745c5c3_Err != nil {1896 if templ_7745c5c3_Err != nil {
1887 return templ_7745c5c3_Err1897 return templ_7745c5c3_Err
1888 }1898 }
1889- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 167, "</p>")1899+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 168, "</p>")
1890 if templ_7745c5c3_Err != nil {1900 if templ_7745c5c3_Err != nil {
1891 return templ_7745c5c3_Err1901 return templ_7745c5c3_Err
1892 }1902 }
1893 }1903 }
1894- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 168, "</section><section aria-labelledby=\"r-settings\"><h2 id=\"r-settings\">Settings</h2><dl class=\"kv\"><dt>modes</dt><dd>")1904+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 169, "</section><section aria-labelledby=\"r-settings\"><h2 id=\"r-settings\">Settings</h2><dl class=\"kv\"><dt>modes</dt><dd>")
1895 if templ_7745c5c3_Err != nil {1905 if templ_7745c5c3_Err != nil {
1896 return templ_7745c5c3_Err1906 return templ_7745c5c3_Err
1897 }1907 }
1898 var templ_7745c5c3_Var96 string1908 var templ_7745c5c3_Var96 string
1899 templ_7745c5c3_Var96, templ_7745c5c3_Err = templ.JoinStringErrs(strings.Join(p.Modes, ", "))1909 templ_7745c5c3_Var96, templ_7745c5c3_Err = templ.JoinStringErrs(strings.Join(p.Modes, ", "))
1900 if templ_7745c5c3_Err != nil {1910 if templ_7745c5c3_Err != nil {
1901- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 344, Col: 36}1911+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 347, Col: 36}
1902 }1912 }
1903 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var96))1913 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var96))
1904 if templ_7745c5c3_Err != nil {1914 if templ_7745c5c3_Err != nil {
1905 return templ_7745c5c3_Err1915 return templ_7745c5c3_Err
1906 }1916 }
1907- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 169, "</dd><dt>checks</dt><dd>")1917+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 170, "</dd><dt>checks</dt><dd>")
1908 if templ_7745c5c3_Err != nil {1918 if templ_7745c5c3_Err != nil {
1909 return templ_7745c5c3_Err1919 return templ_7745c5c3_Err
1910 }1920 }
1911 if p.ChecksBlock {1921 if p.ChecksBlock {
1912- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 170, "failing ones block the merge")1922+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 171, "failing ones block the merge")
1913 if templ_7745c5c3_Err != nil {1923 if templ_7745c5c3_Err != nil {
1914 return templ_7745c5c3_Err1924 return templ_7745c5c3_Err
1915 }1925 }
1916 } else {1926 } else {
1917- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 171, "do not block the merge")1927+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 172, "do not block the merge")
1918 if templ_7745c5c3_Err != nil {1928 if templ_7745c5c3_Err != nil {
1919 return templ_7745c5c3_Err1929 return templ_7745c5c3_Err
1920 }1930 }
1921 }1931 }
1922- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 172, "</dd></dl></section>")1932+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 173, "</dd></dl></section>")
1923 if templ_7745c5c3_Err != nil {1933 if templ_7745c5c3_Err != nil {
1924 return templ_7745c5c3_Err1934 return templ_7745c5c3_Err
1925 }1935 }
@@ -1952,46 +1962,46 @@ func mrBar(p MRPage) templ.Component {
1952 templ_7745c5c3_Var97 = templ.NopComponent1962 templ_7745c5c3_Var97 = templ.NopComponent
1953 }1963 }
1954 ctx = templ.ClearChildren(ctx)1964 ctx = templ.ClearChildren(ctx)
1955- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 173, "<div class=\"diff-tools mr-bar\" role=\"group\" aria-label=\"Diff view and merge\"><span class=\"dim\">")1965+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 174, "<div class=\"diff-tools mr-bar\" role=\"group\" aria-label=\"Diff view and merge\"><span class=\"dim\">")
1956 if templ_7745c5c3_Err != nil {1966 if templ_7745c5c3_Err != nil {
1957 return templ_7745c5c3_Err1967 return templ_7745c5c3_Err
1958 }1968 }
1959 var templ_7745c5c3_Var98 string1969 var templ_7745c5c3_Var98 string
1960 templ_7745c5c3_Var98, templ_7745c5c3_Err = templ.JoinStringErrs(plural(p.NFiles, "file", "files"))1970 templ_7745c5c3_Var98, templ_7745c5c3_Err = templ.JoinStringErrs(plural(p.NFiles, "file", "files"))
1961 if templ_7745c5c3_Err != nil {1971 if templ_7745c5c3_Err != nil {
1962- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 363, Col: 55}1972+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 366, Col: 55}
1963 }1973 }
1964 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var98))1974 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var98))
1965 if templ_7745c5c3_Err != nil {1975 if templ_7745c5c3_Err != nil {
1966 return templ_7745c5c3_Err1976 return templ_7745c5c3_Err
1967 }1977 }
1968- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 174, " · <span class=\"plus\">+")1978+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 175, " · <span class=\"plus\">+")
1969 if templ_7745c5c3_Err != nil {1979 if templ_7745c5c3_Err != nil {
1970 return templ_7745c5c3_Err1980 return templ_7745c5c3_Err
1971 }1981 }
1972 var templ_7745c5c3_Var99 string1982 var templ_7745c5c3_Var99 string
1973 templ_7745c5c3_Var99, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.Adds))1983 templ_7745c5c3_Var99, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.Adds))
1974 if templ_7745c5c3_Err != nil {1984 if templ_7745c5c3_Err != nil {
1975- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 363, Col: 95}1985+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 366, Col: 95}
1976 }1986 }
1977 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var99))1987 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var99))
1978 if templ_7745c5c3_Err != nil {1988 if templ_7745c5c3_Err != nil {
1979 return templ_7745c5c3_Err1989 return templ_7745c5c3_Err
1980 }1990 }
1981- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 175, "</span> <span class=\"minus\">-")1991+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 176, "</span> <span class=\"minus\">-")
1982 if templ_7745c5c3_Err != nil {1992 if templ_7745c5c3_Err != nil {
1983 return templ_7745c5c3_Err1993 return templ_7745c5c3_Err
1984 }1994 }
1985 var templ_7745c5c3_Var100 string1995 var templ_7745c5c3_Var100 string
1986 templ_7745c5c3_Var100, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.Dels))1996 templ_7745c5c3_Var100, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.Dels))
1987 if templ_7745c5c3_Err != nil {1997 if templ_7745c5c3_Err != nil {
1988- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 363, Col: 140}1998+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 366, Col: 140}
1989 }1999 }
1990 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var100))2000 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var100))
1991 if templ_7745c5c3_Err != nil {2001 if templ_7745c5c3_Err != nil {
1992 return templ_7745c5c3_Err2002 return templ_7745c5c3_Err
1993 }2003 }
1994- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 176, "</span></span>")2004+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 177, "</span></span>")
1995 if templ_7745c5c3_Err != nil {2005 if templ_7745c5c3_Err != nil {
1996 return templ_7745c5c3_Err2006 return templ_7745c5c3_Err
1997 }2007 }
@@ -2007,7 +2017,7 @@ func mrBar(p MRPage) templ.Component {
2007 if templ_7745c5c3_Err != nil {2017 if templ_7745c5c3_Err != nil {
2008 return templ_7745c5c3_Err2018 return templ_7745c5c3_Err
2009 }2019 }
2010- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 177, "<span class=\"grow\"></span>")2020+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 178, "<span class=\"grow\"></span>")
2011 if templ_7745c5c3_Err != nil {2021 if templ_7745c5c3_Err != nil {
2012 return templ_7745c5c3_Err2022 return templ_7745c5c3_Err
2013 }2023 }
@@ -2020,7 +2030,7 @@ func mrBar(p MRPage) templ.Component {
2020 if templ_7745c5c3_Err != nil {2030 if templ_7745c5c3_Err != nil {
2021 return templ_7745c5c3_Err2031 return templ_7745c5c3_Err
2022 }2032 }
2023- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 178, " ")2033+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 179, " ")
2024 if templ_7745c5c3_Err != nil {2034 if templ_7745c5c3_Err != nil {
2025 return templ_7745c5c3_Err2035 return templ_7745c5c3_Err
2026 }2036 }
@@ -2029,7 +2039,7 @@ func mrBar(p MRPage) templ.Component {
2029 return templ_7745c5c3_Err2039 return templ_7745c5c3_Err
2030 }2040 }
2031 }2041 }
2032- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 179, "</div>")2042+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 180, "</div>")
2033 if templ_7745c5c3_Err != nil {2043 if templ_7745c5c3_Err != nil {
2034 return templ_7745c5c3_Err2044 return templ_7745c5c3_Err
2035 }2045 }
@@ -2061,27 +2071,27 @@ func mergeMenu(p MRPage) templ.Component {
2061 templ_7745c5c3_Var101 = templ.NopComponent2071 templ_7745c5c3_Var101 = templ.NopComponent
2062 }2072 }
2063 ctx = templ.ClearChildren(ctx)2073 ctx = templ.ClearChildren(ctx)
2064- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 180, "<details class=\"menu mmenu\" id=\"merge-menu\" data-state=\"open\"><summary class=\"btn primary\" aria-keyshortcuts=\"Shift+M\">")2074+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 181, "<details class=\"menu mmenu\" id=\"merge-menu\" data-state=\"open\"><summary class=\"btn primary\" aria-keyshortcuts=\"Shift+M\">")
2065 if templ_7745c5c3_Err != nil {2075 if templ_7745c5c3_Err != nil {
2066 return templ_7745c5c3_Err2076 return templ_7745c5c3_Err
2067 }2077 }
2068 if p.Box.ReadyAction != "" {2078 if p.Box.ReadyAction != "" {
2069- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 181, "Draft ")2079+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 182, "Draft ")
2070 if templ_7745c5c3_Err != nil {2080 if templ_7745c5c3_Err != nil {
2071 return templ_7745c5c3_Err2081 return templ_7745c5c3_Err
2072 }2082 }
2073 } else {2083 } else {
2074- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 182, "Merge ")2084+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 183, "Merge ")
2075 if templ_7745c5c3_Err != nil {2085 if templ_7745c5c3_Err != nil {
2076 return templ_7745c5c3_Err2086 return templ_7745c5c3_Err
2077 }2087 }
2078 }2088 }
2079- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 183, "<kbd aria-hidden=\"true\">M</kbd></summary><div class=\"menu-pop\" role=\"group\" aria-label=\"Merge\"><dl class=\"kv\"><dt>head</dt><dd>")2089+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 184, "<kbd aria-hidden=\"true\">M</kbd></summary><div class=\"menu-pop\" role=\"group\" aria-label=\"Merge\"><dl class=\"kv\"><dt>head</dt><dd>")
2080 if templ_7745c5c3_Err != nil {2090 if templ_7745c5c3_Err != nil {
2081 return templ_7745c5c3_Err2091 return templ_7745c5c3_Err
2082 }2092 }
2083 if p.Box.HeadGone {2093 if p.Box.HeadGone {
2084- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 184, "gone: the source branch was deleted")2094+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 185, "gone: the source branch was deleted")
2085 if templ_7745c5c3_Err != nil {2095 if templ_7745c5c3_Err != nil {
2086 return templ_7745c5c3_Err2096 return templ_7745c5c3_Err
2087 }2097 }
@@ -2089,186 +2099,186 @@ func mergeMenu(p MRPage) templ.Component {
2089 var templ_7745c5c3_Var102 string2099 var templ_7745c5c3_Var102 string
2090 templ_7745c5c3_Var102, templ_7745c5c3_Err = templ.JoinStringErrs(p.HeadShort)2100 templ_7745c5c3_Var102, templ_7745c5c3_Err = templ.JoinStringErrs(p.HeadShort)
2091 if templ_7745c5c3_Err != nil {2101 if templ_7745c5c3_Err != nil {
2092- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 396, Col: 19}2102+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 399, Col: 19}
2093 }2103 }
2094 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var102))2104 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var102))
2095 if templ_7745c5c3_Err != nil {2105 if templ_7745c5c3_Err != nil {
2096 return templ_7745c5c3_Err2106 return templ_7745c5c3_Err
2097 }2107 }
2098 }2108 }
2099- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 185, "</dd><dt>into</dt><dd>")2109+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 186, "</dd><dt>into</dt><dd>")
2100 if templ_7745c5c3_Err != nil {2110 if templ_7745c5c3_Err != nil {
2101 return templ_7745c5c3_Err2111 return templ_7745c5c3_Err
2102 }2112 }
2103 var templ_7745c5c3_Var103 string2113 var templ_7745c5c3_Var103 string
2104 templ_7745c5c3_Var103, templ_7745c5c3_Err = templ.JoinStringErrs(p.Target)2114 templ_7745c5c3_Var103, templ_7745c5c3_Err = templ.JoinStringErrs(p.Target)
2105 if templ_7745c5c3_Err != nil {2115 if templ_7745c5c3_Err != nil {
2106- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 400, Col: 18}2116+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 403, Col: 18}
2107 }2117 }
2108 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var103))2118 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var103))
2109 if templ_7745c5c3_Err != nil {2119 if templ_7745c5c3_Err != nil {
2110 return templ_7745c5c3_Err2120 return templ_7745c5c3_Err
2111 }2121 }
2112- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 186, "</dd></dl>")2122+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 187, "</dd></dl>")
2113 if templ_7745c5c3_Err != nil {2123 if templ_7745c5c3_Err != nil {
2114 return templ_7745c5c3_Err2124 return templ_7745c5c3_Err
2115 }2125 }
2116 if p.Box.ReadyAction != "" {2126 if p.Box.ReadyAction != "" {
2117- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 187, "<p class=\"d-draft\">this is a draft: it cannot be merged until it is ready for review.</p><form class=\"d-btns\" method=\"post\" action=\"")2127+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 188, "<p class=\"d-draft\">this is a draft: it cannot be merged until it is ready for review.</p><form class=\"d-btns\" method=\"post\" action=\"")
2118 if templ_7745c5c3_Err != nil {2128 if templ_7745c5c3_Err != nil {
2119 return templ_7745c5c3_Err2129 return templ_7745c5c3_Err
2120 }2130 }
2121 var templ_7745c5c3_Var104 templ.SafeURL2131 var templ_7745c5c3_Var104 templ.SafeURL
2122 templ_7745c5c3_Var104, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.Box.ReadyAction))2132 templ_7745c5c3_Var104, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.Box.ReadyAction))
2123 if templ_7745c5c3_Err != nil {2133 if templ_7745c5c3_Err != nil {
2124- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 404, Col: 80}2134+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 407, Col: 80}
2125 }2135 }
2126 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var104))2136 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var104))
2127 if templ_7745c5c3_Err != nil {2137 if templ_7745c5c3_Err != nil {
2128 return templ_7745c5c3_Err2138 return templ_7745c5c3_Err
2129 }2139 }
2130- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 188, "\"><button type=\"submit\" class=\"btn primary\" data-default title=\"remove the draft prefix from the title\">Ready for review</button></form>")2140+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 189, "\"><button type=\"submit\" class=\"btn primary\" data-default title=\"remove the draft prefix from the title\">Ready for review</button></form>")
2131 if templ_7745c5c3_Err != nil {2141 if templ_7745c5c3_Err != nil {
2132 return templ_7745c5c3_Err2142 return templ_7745c5c3_Err
2133 }2143 }
2134 } else if !p.Box.HeadGone {2144 } else if !p.Box.HeadGone {
2135- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 189, "<form class=\"d-acts\" method=\"post\" action=\"")2145+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 190, "<form class=\"d-acts\" method=\"post\" action=\"")
2136 if templ_7745c5c3_Err != nil {2146 if templ_7745c5c3_Err != nil {
2137 return templ_7745c5c3_Err2147 return templ_7745c5c3_Err
2138 }2148 }
2139 var templ_7745c5c3_Var105 templ.SafeURL2149 var templ_7745c5c3_Var105 templ.SafeURL
2140 templ_7745c5c3_Var105, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.Box.MergeAction))2150 templ_7745c5c3_Var105, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.Box.MergeAction))
2141 if templ_7745c5c3_Err != nil {2151 if templ_7745c5c3_Err != nil {
2142- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 408, Col: 80}2152+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 411, Col: 80}
2143 }2153 }
2144 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var105))2154 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var105))
2145 if templ_7745c5c3_Err != nil {2155 if templ_7745c5c3_Err != nil {
2146 return templ_7745c5c3_Err2156 return templ_7745c5c3_Err
2147 }2157 }
2148- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 190, "\"><input type=\"hidden\" name=\"head_id\" value=\"")2158+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 191, "\"><input type=\"hidden\" name=\"head_id\" value=\"")
2149 if templ_7745c5c3_Err != nil {2159 if templ_7745c5c3_Err != nil {
2150 return templ_7745c5c3_Err2160 return templ_7745c5c3_Err
2151 }2161 }
2152 var templ_7745c5c3_Var106 string2162 var templ_7745c5c3_Var106 string
2153 templ_7745c5c3_Var106, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.Box.Head)2163 templ_7745c5c3_Var106, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.Box.Head)
2154 if templ_7745c5c3_Err != nil {2164 if templ_7745c5c3_Err != nil {
2155- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 409, Col: 59}2165+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 412, Col: 59}
2156 }2166 }
2157 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var106)2167 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var106)
2158 if templ_7745c5c3_Err != nil {2168 if templ_7745c5c3_Err != nil {
2159 return templ_7745c5c3_Err2169 return templ_7745c5c3_Err
2160 }2170 }
2161- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 191, "\"><fieldset class=\"d-modes\"><legend class=\"sr\">merge mode</legend> ")2171+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 192, "\"><fieldset class=\"d-modes\"><legend class=\"sr\">merge mode</legend> ")
2162 if templ_7745c5c3_Err != nil {2172 if templ_7745c5c3_Err != nil {
2163 return templ_7745c5c3_Err2173 return templ_7745c5c3_Err
2164 }2174 }
2165 for i, m := range p.Box.Modes {2175 for i, m := range p.Box.Modes {
2166- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 192, "<label><input type=\"radio\" name=\"mode\" value=\"")2176+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 193, "<label><input type=\"radio\" name=\"mode\" value=\"")
2167 if templ_7745c5c3_Err != nil {2177 if templ_7745c5c3_Err != nil {
2168 return templ_7745c5c3_Err2178 return templ_7745c5c3_Err
2169 }2179 }
2170 var templ_7745c5c3_Var107 string2180 var templ_7745c5c3_Var107 string
2171 templ_7745c5c3_Var107, templ_7745c5c3_Err = templ.ResolveAttributeValue(m.Value)2181 templ_7745c5c3_Var107, templ_7745c5c3_Err = templ.ResolveAttributeValue(m.Value)
2172 if templ_7745c5c3_Err != nil {2182 if templ_7745c5c3_Err != nil {
2173- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 414, Col: 55}2183+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 417, Col: 55}
2174 }2184 }
2175 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var107)2185 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var107)
2176 if templ_7745c5c3_Err != nil {2186 if templ_7745c5c3_Err != nil {
2177 return templ_7745c5c3_Err2187 return templ_7745c5c3_Err
2178 }2188 }
2179- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 193, "\"")2189+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 194, "\"")
2180 if templ_7745c5c3_Err != nil {2190 if templ_7745c5c3_Err != nil {
2181 return templ_7745c5c3_Err2191 return templ_7745c5c3_Err
2182 }2192 }
2183 if i == 0 {2193 if i == 0 {
2184- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 194, " checked")2194+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 195, " checked")
2185 if templ_7745c5c3_Err != nil {2195 if templ_7745c5c3_Err != nil {
2186 return templ_7745c5c3_Err2196 return templ_7745c5c3_Err
2187 }2197 }
2188 }2198 }
2189- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 195, "> ")2199+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 196, "> ")
2190 if templ_7745c5c3_Err != nil {2200 if templ_7745c5c3_Err != nil {
2191 return templ_7745c5c3_Err2201 return templ_7745c5c3_Err
2192 }2202 }
2193 var templ_7745c5c3_Var108 string2203 var templ_7745c5c3_Var108 string
2194 templ_7745c5c3_Var108, templ_7745c5c3_Err = templ.JoinStringErrs(m.Label)2204 templ_7745c5c3_Var108, templ_7745c5c3_Err = templ.JoinStringErrs(m.Label)
2195 if templ_7745c5c3_Err != nil {2205 if templ_7745c5c3_Err != nil {
2196- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 415, Col: 17}2206+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 418, Col: 17}
2197 }2207 }
2198 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var108))2208 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var108))
2199 if templ_7745c5c3_Err != nil {2209 if templ_7745c5c3_Err != nil {
2200 return templ_7745c5c3_Err2210 return templ_7745c5c3_Err
2201 }2211 }
2202- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 196, " ")2212+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 197, " ")
2203 if templ_7745c5c3_Err != nil {2213 if templ_7745c5c3_Err != nil {
2204 return templ_7745c5c3_Err2214 return templ_7745c5c3_Err
2205 }2215 }
2206 if i < 9 {2216 if i < 9 {
2207- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 197, "<kbd aria-hidden=\"true\">")2217+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 198, "<kbd aria-hidden=\"true\">")
2208 if templ_7745c5c3_Err != nil {2218 if templ_7745c5c3_Err != nil {
2209 return templ_7745c5c3_Err2219 return templ_7745c5c3_Err
2210 }2220 }
2211 var templ_7745c5c3_Var109 string2221 var templ_7745c5c3_Var109 string
2212 templ_7745c5c3_Var109, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(i + 1))2222 templ_7745c5c3_Var109, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(i + 1))
2213 if templ_7745c5c3_Err != nil {2223 if templ_7745c5c3_Err != nil {
2214- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 417, Col: 46}2224+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 420, Col: 46}
2215 }2225 }
2216 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var109))2226 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var109))
2217 if templ_7745c5c3_Err != nil {2227 if templ_7745c5c3_Err != nil {
2218 return templ_7745c5c3_Err2228 return templ_7745c5c3_Err
2219 }2229 }
2220- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 198, "</kbd>")2230+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 199, "</kbd>")
2221 if templ_7745c5c3_Err != nil {2231 if templ_7745c5c3_Err != nil {
2222 return templ_7745c5c3_Err2232 return templ_7745c5c3_Err
2223 }2233 }
2224 }2234 }
2225- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 199, "</label>")2235+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 200, "</label>")
2226 if templ_7745c5c3_Err != nil {2236 if templ_7745c5c3_Err != nil {
2227 return templ_7745c5c3_Err2237 return templ_7745c5c3_Err
2228 }2238 }
2229 }2239 }
2230- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 200, "</fieldset>")2240+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 201, "</fieldset>")
2231 if templ_7745c5c3_Err != nil {2241 if templ_7745c5c3_Err != nil {
2232 return templ_7745c5c3_Err2242 return templ_7745c5c3_Err
2233 }2243 }
2234 if p.Box.CanDeleteBranch {2244 if p.Box.CanDeleteBranch {
2235- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 201, "<label class=\"d-check\"><input type=\"checkbox\" name=\"delete_branch\" value=\"1\"> delete ")2245+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 202, "<label class=\"d-check\"><input type=\"checkbox\" name=\"delete_branch\" value=\"1\"> delete ")
2236 if templ_7745c5c3_Err != nil {2246 if templ_7745c5c3_Err != nil {
2237 return templ_7745c5c3_Err2247 return templ_7745c5c3_Err
2238 }2248 }
2239 var templ_7745c5c3_Var110 string2249 var templ_7745c5c3_Var110 string
2240 templ_7745c5c3_Var110, templ_7745c5c3_Err = templ.JoinStringErrs(p.Source)2250 templ_7745c5c3_Var110, templ_7745c5c3_Err = templ.JoinStringErrs(p.Source)
2241 if templ_7745c5c3_Err != nil {2251 if templ_7745c5c3_Err != nil {
2242- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 423, Col: 102}2252+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 426, Col: 102}
2243 }2253 }
2244 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var110))2254 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var110))
2245 if templ_7745c5c3_Err != nil {2255 if templ_7745c5c3_Err != nil {
2246 return templ_7745c5c3_Err2256 return templ_7745c5c3_Err
2247 }2257 }
2248- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 202, " after the merge <kbd aria-hidden=\"true\">D</kbd></label>")2258+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 203, " after the merge <kbd aria-hidden=\"true\">D</kbd></label>")
2249 if templ_7745c5c3_Err != nil {2259 if templ_7745c5c3_Err != nil {
2250 return templ_7745c5c3_Err2260 return templ_7745c5c3_Err
2251 }2261 }
2252 }2262 }
2253- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 203, "<div class=\"d-btns\"><button type=\"submit\" class=\"btn primary\" data-default>Merge into ")2263+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 204, "<div class=\"d-btns\"><button type=\"submit\" class=\"btn primary\" data-default>Merge into ")
2254 if templ_7745c5c3_Err != nil {2264 if templ_7745c5c3_Err != nil {
2255 return templ_7745c5c3_Err2265 return templ_7745c5c3_Err
2256 }2266 }
2257 var templ_7745c5c3_Var111 string2267 var templ_7745c5c3_Var111 string
2258 templ_7745c5c3_Var111, templ_7745c5c3_Err = templ.JoinStringErrs(p.Target)2268 templ_7745c5c3_Var111, templ_7745c5c3_Err = templ.JoinStringErrs(p.Target)
2259 if templ_7745c5c3_Err != nil {2269 if templ_7745c5c3_Err != nil {
2260- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 426, Col: 82}2270+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 429, Col: 82}
2261 }2271 }
2262 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var111))2272 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var111))
2263 if templ_7745c5c3_Err != nil {2273 if templ_7745c5c3_Err != nil {
2264 return templ_7745c5c3_Err2274 return templ_7745c5c3_Err
2265 }2275 }
2266- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 204, "</button></div></form>")2276+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 205, "</button></div></form>")
2267 if templ_7745c5c3_Err != nil {2277 if templ_7745c5c3_Err != nil {
2268 return templ_7745c5c3_Err2278 return templ_7745c5c3_Err
2269 }2279 }
2270 }2280 }
2271- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 205, "</div></details>")2281+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 206, "</div></details>")
2272 if templ_7745c5c3_Err != nil {2282 if templ_7745c5c3_Err != nil {
2273 return templ_7745c5c3_Err2283 return templ_7745c5c3_Err
2274 }2284 }
@@ -2299,61 +2309,61 @@ func moreMenu(p MRPage) templ.Component {
2299 templ_7745c5c3_Var112 = templ.NopComponent2309 templ_7745c5c3_Var112 = templ.NopComponent
2300 }2310 }
2301 ctx = templ.ClearChildren(ctx)2311 ctx = templ.ClearChildren(ctx)
2302- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 206, "<details class=\"menu omenu\"><summary class=\"btn icon\" aria-label=\"More actions\" title=\"more actions\">⋯</summary><div class=\"menu-pop\" role=\"group\" aria-label=\"More actions\">")2312+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 207, "<details class=\"menu omenu\"><summary class=\"btn icon\" aria-label=\"More actions\" title=\"more actions\">⋯</summary><div class=\"menu-pop\" role=\"group\" aria-label=\"More actions\">")
2303 if templ_7745c5c3_Err != nil {2313 if templ_7745c5c3_Err != nil {
2304 return templ_7745c5c3_Err2314 return templ_7745c5c3_Err
2305 }2315 }
2306 if p.Box.CanMarkRead {2316 if p.Box.CanMarkRead {
2307- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 207, "<form method=\"post\" action=\"")2317+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 208, "<form method=\"post\" action=\"")
2308 if templ_7745c5c3_Err != nil {2318 if templ_7745c5c3_Err != nil {
2309 return templ_7745c5c3_Err2319 return templ_7745c5c3_Err
2310 }2320 }
2311 var templ_7745c5c3_Var113 templ.SafeURL2321 var templ_7745c5c3_Var113 templ.SafeURL
2312 templ_7745c5c3_Var113, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.Box.ReadAction))2322 templ_7745c5c3_Var113, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.Box.ReadAction))
2313 if templ_7745c5c3_Err != nil {2323 if templ_7745c5c3_Err != nil {
2314- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 441, Col: 64}2324+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 444, Col: 64}
2315 }2325 }
2316 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var113))2326 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var113))
2317 if templ_7745c5c3_Err != nil {2327 if templ_7745c5c3_Err != nil {
2318 return templ_7745c5c3_Err2328 return templ_7745c5c3_Err
2319 }2329 }
2320- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 208, "\"><input type=\"hidden\" name=\"head_id\" value=\"")2330+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 209, "\"><input type=\"hidden\" name=\"head_id\" value=\"")
2321 if templ_7745c5c3_Err != nil {2331 if templ_7745c5c3_Err != nil {
2322 return templ_7745c5c3_Err2332 return templ_7745c5c3_Err
2323 }2333 }
2324 var templ_7745c5c3_Var114 string2334 var templ_7745c5c3_Var114 string
2325 templ_7745c5c3_Var114, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.Box.Head)2335 templ_7745c5c3_Var114, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.Box.Head)
2326 if templ_7745c5c3_Err != nil {2336 if templ_7745c5c3_Err != nil {
2327- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 442, Col: 59}2337+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 445, Col: 59}
2328 }2338 }
2329 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var114)2339 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var114)
2330 if templ_7745c5c3_Err != nil {2340 if templ_7745c5c3_Err != nil {
2331 return templ_7745c5c3_Err2341 return templ_7745c5c3_Err
2332 }2342 }
2333- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 209, "\"> <button type=\"submit\" title=\"the next visit can show only what changed after this head\" class=\"btn\" aria-keyshortcuts=\"Shift+R\" data-read>Mark read <kbd aria-hidden=\"true\">R</kbd></button></form>")2343+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 210, "\"> <button type=\"submit\" title=\"the next visit can show only what changed after this head\" class=\"btn\" aria-keyshortcuts=\"Shift+R\" data-read>Mark read <kbd aria-hidden=\"true\">R</kbd></button></form>")
2334 if templ_7745c5c3_Err != nil {2344 if templ_7745c5c3_Err != nil {
2335 return templ_7745c5c3_Err2345 return templ_7745c5c3_Err
2336 }2346 }
2337 }2347 }
2338- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 210, "<form method=\"post\" action=\"")2348+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 211, "<form method=\"post\" action=\"")
2339 if templ_7745c5c3_Err != nil {2349 if templ_7745c5c3_Err != nil {
2340 return templ_7745c5c3_Err2350 return templ_7745c5c3_Err
2341 }2351 }
2342 var templ_7745c5c3_Var115 templ.SafeURL2352 var templ_7745c5c3_Var115 templ.SafeURL
2343 templ_7745c5c3_Var115, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.Box.CloseAction))2353 templ_7745c5c3_Var115, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.Box.CloseAction))
2344 if templ_7745c5c3_Err != nil {2354 if templ_7745c5c3_Err != nil {
2345- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 446, Col: 64}2355+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 449, Col: 64}
2346 }2356 }
2347 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var115))2357 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var115))
2348 if templ_7745c5c3_Err != nil {2358 if templ_7745c5c3_Err != nil {
2349 return templ_7745c5c3_Err2359 return templ_7745c5c3_Err
2350 }2360 }
2351- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 211, "\"><button type=\"submit\" title=\"close without merging; the branch is kept\" class=\"btn danger\">Close</button></form>")2361+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 212, "\"><button type=\"submit\" title=\"close without merging; the branch is kept\" class=\"btn danger\">Close</button></form>")
2352 if templ_7745c5c3_Err != nil {2362 if templ_7745c5c3_Err != nil {
2353 return templ_7745c5c3_Err2363 return templ_7745c5c3_Err
2354 }2364 }
2355 if !p.Box.HeadGone && p.Box.ReadyAction == "" {2365 if !p.Box.HeadGone && p.Box.ReadyAction == "" {
2356- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 212, "<details class=\"d-or\"><summary class=\"mute\">or from a terminal</summary>")2366+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 213, "<details class=\"d-or\"><summary class=\"mute\">or from a terminal</summary>")
2357 if templ_7745c5c3_Err != nil {2367 if templ_7745c5c3_Err != nil {
2358 return templ_7745c5c3_Err2368 return templ_7745c5c3_Err
2359 }2369 }
@@ -2361,12 +2371,12 @@ func moreMenu(p MRPage) templ.Component {
2361 if templ_7745c5c3_Err != nil {2371 if templ_7745c5c3_Err != nil {
2362 return templ_7745c5c3_Err2372 return templ_7745c5c3_Err
2363 }2373 }
2364- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 213, "</details>")2374+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 214, "</details>")
2365 if templ_7745c5c3_Err != nil {2375 if templ_7745c5c3_Err != nil {
2366 return templ_7745c5c3_Err2376 return templ_7745c5c3_Err
2367 }2377 }
2368 }2378 }
2369- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 214, "</div></details>")2379+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 215, "</div></details>")
2370 if templ_7745c5c3_Err != nil {2380 if templ_7745c5c3_Err != nil {
2371 return templ_7745c5c3_Err2381 return templ_7745c5c3_Err
2372 }2382 }
@@ -2407,263 +2417,263 @@ func Compare(l Layout, p ComparePage) templ.Component {
2407 }()2417 }()
2408 }2418 }
2409 ctx = templ.InitializeContext(ctx)2419 ctx = templ.InitializeContext(ctx)
2410- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 215, "<header class=\"show mr-h\"><h1>")2420+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 216, "<header class=\"show mr-h\"><h1>")
2411 if templ_7745c5c3_Err != nil {2421 if templ_7745c5c3_Err != nil {
2412 return templ_7745c5c3_Err2422 return templ_7745c5c3_Err
2413 }2423 }
2414 var templ_7745c5c3_Var118 string2424 var templ_7745c5c3_Var118 string
2415 templ_7745c5c3_Var118, templ_7745c5c3_Err = templ.JoinStringErrs(p.Source)2425 templ_7745c5c3_Var118, templ_7745c5c3_Err = templ.JoinStringErrs(p.Source)
2416 if templ_7745c5c3_Err != nil {2426 if templ_7745c5c3_Err != nil {
2417- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 462, Col: 17}2427+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 465, Col: 17}
2418 }2428 }
2419 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var118))2429 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var118))
2420 if templ_7745c5c3_Err != nil {2430 if templ_7745c5c3_Err != nil {
2421 return templ_7745c5c3_Err2431 return templ_7745c5c3_Err
2422 }2432 }
2423- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 216, " → ")2433+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 217, " → ")
2424 if templ_7745c5c3_Err != nil {2434 if templ_7745c5c3_Err != nil {
2425 return templ_7745c5c3_Err2435 return templ_7745c5c3_Err
2426 }2436 }
2427 var templ_7745c5c3_Var119 string2437 var templ_7745c5c3_Var119 string
2428 templ_7745c5c3_Var119, templ_7745c5c3_Err = templ.JoinStringErrs(p.Target)2438 templ_7745c5c3_Var119, templ_7745c5c3_Err = templ.JoinStringErrs(p.Target)
2429 if templ_7745c5c3_Err != nil {2439 if templ_7745c5c3_Err != nil {
2430- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 462, Col: 34}2440+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 465, Col: 34}
2431 }2441 }
2432 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var119))2442 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var119))
2433 if templ_7745c5c3_Err != nil {2443 if templ_7745c5c3_Err != nil {
2434 return templ_7745c5c3_Err2444 return templ_7745c5c3_Err
2435 }2445 }
2436- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 217, "</h1><dl class=\"kv show-kv\"><dt>branch</dt><dd><a href=\"")2446+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 218, "</h1><dl class=\"kv show-kv\"><dt>branch</dt><dd><a href=\"")
2437 if templ_7745c5c3_Err != nil {2447 if templ_7745c5c3_Err != nil {
2438 return templ_7745c5c3_Err2448 return templ_7745c5c3_Err
2439 }2449 }
2440 var templ_7745c5c3_Var120 templ.SafeURL2450 var templ_7745c5c3_Var120 templ.SafeURL
2441 templ_7745c5c3_Var120, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.SourceHref))2451 templ_7745c5c3_Var120, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.SourceHref))
2442 if templ_7745c5c3_Err != nil {2452 if templ_7745c5c3_Err != nil {
2443- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 465, Col: 45}2453+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 468, Col: 45}
2444 }2454 }
2445 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var120))2455 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var120))
2446 if templ_7745c5c3_Err != nil {2456 if templ_7745c5c3_Err != nil {
2447 return templ_7745c5c3_Err2457 return templ_7745c5c3_Err
2448 }2458 }
2449- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 218, "\">")2459+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 219, "\">")
2450 if templ_7745c5c3_Err != nil {2460 if templ_7745c5c3_Err != nil {
2451 return templ_7745c5c3_Err2461 return templ_7745c5c3_Err
2452 }2462 }
2453 var templ_7745c5c3_Var121 string2463 var templ_7745c5c3_Var121 string
2454 templ_7745c5c3_Var121, templ_7745c5c3_Err = templ.JoinStringErrs(p.Source)2464 templ_7745c5c3_Var121, templ_7745c5c3_Err = templ.JoinStringErrs(p.Source)
2455 if templ_7745c5c3_Err != nil {2465 if templ_7745c5c3_Err != nil {
2456- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 465, Col: 58}2466+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 468, Col: 58}
2457 }2467 }
2458 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var121))2468 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var121))
2459 if templ_7745c5c3_Err != nil {2469 if templ_7745c5c3_Err != nil {
2460 return templ_7745c5c3_Err2470 return templ_7745c5c3_Err
2461 }2471 }
2462- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 219, "</a></dd><dt>target</dt><dd><a href=\"")2472+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 220, "</a></dd><dt>target</dt><dd><a href=\"")
2463 if templ_7745c5c3_Err != nil {2473 if templ_7745c5c3_Err != nil {
2464 return templ_7745c5c3_Err2474 return templ_7745c5c3_Err
2465 }2475 }
2466 var templ_7745c5c3_Var122 templ.SafeURL2476 var templ_7745c5c3_Var122 templ.SafeURL
2467 templ_7745c5c3_Var122, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.TargetHref))2477 templ_7745c5c3_Var122, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.TargetHref))
2468 if templ_7745c5c3_Err != nil {2478 if templ_7745c5c3_Err != nil {
2469- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 467, Col: 45}2479+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 470, Col: 45}
2470 }2480 }
2471 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var122))2481 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var122))
2472 if templ_7745c5c3_Err != nil {2482 if templ_7745c5c3_Err != nil {
2473 return templ_7745c5c3_Err2483 return templ_7745c5c3_Err
2474 }2484 }
2475- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 220, "\">")2485+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 221, "\">")
2476 if templ_7745c5c3_Err != nil {2486 if templ_7745c5c3_Err != nil {
2477 return templ_7745c5c3_Err2487 return templ_7745c5c3_Err
2478 }2488 }
2479 var templ_7745c5c3_Var123 string2489 var templ_7745c5c3_Var123 string
2480 templ_7745c5c3_Var123, templ_7745c5c3_Err = templ.JoinStringErrs(p.Target)2490 templ_7745c5c3_Var123, templ_7745c5c3_Err = templ.JoinStringErrs(p.Target)
2481 if templ_7745c5c3_Err != nil {2491 if templ_7745c5c3_Err != nil {
2482- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 467, Col: 58}2492+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 470, Col: 58}
2483 }2493 }
2484 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var123))2494 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var123))
2485 if templ_7745c5c3_Err != nil {2495 if templ_7745c5c3_Err != nil {
2486 return templ_7745c5c3_Err2496 return templ_7745c5c3_Err
2487 }2497 }
2488- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 221, "</a></dd><dt>ahead</dt><dd>")2498+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 222, "</a></dd><dt>ahead</dt><dd>")
2489 if templ_7745c5c3_Err != nil {2499 if templ_7745c5c3_Err != nil {
2490 return templ_7745c5c3_Err2500 return templ_7745c5c3_Err
2491 }2501 }
2492 var templ_7745c5c3_Var124 string2502 var templ_7745c5c3_Var124 string
2493 templ_7745c5c3_Var124, templ_7745c5c3_Err = templ.JoinStringErrs(p.AheadText)2503 templ_7745c5c3_Var124, templ_7745c5c3_Err = templ.JoinStringErrs(p.AheadText)
2494 if templ_7745c5c3_Err != nil {2504 if templ_7745c5c3_Err != nil {
2495- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 469, Col: 21}2505+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 472, Col: 21}
2496 }2506 }
2497 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var124))2507 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var124))
2498 if templ_7745c5c3_Err != nil {2508 if templ_7745c5c3_Err != nil {
2499 return templ_7745c5c3_Err2509 return templ_7745c5c3_Err
2500 }2510 }
2501- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 222, "</dd></dl></header>")2511+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 223, "</dd></dl></header>")
2502 if templ_7745c5c3_Err != nil {2512 if templ_7745c5c3_Err != nil {
2503 return templ_7745c5c3_Err2513 return templ_7745c5c3_Err
2504 }2514 }
2505 if p.Note != "" {2515 if p.Note != "" {
2506- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 223, "<p class=\"notice\">")2516+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 224, "<p class=\"notice\">")
2507 if templ_7745c5c3_Err != nil {2517 if templ_7745c5c3_Err != nil {
2508 return templ_7745c5c3_Err2518 return templ_7745c5c3_Err
2509 }2519 }
2510 var templ_7745c5c3_Var125 string2520 var templ_7745c5c3_Var125 string
2511 templ_7745c5c3_Var125, templ_7745c5c3_Err = templ.JoinStringErrs(p.Note)2521 templ_7745c5c3_Var125, templ_7745c5c3_Err = templ.JoinStringErrs(p.Note)
2512 if templ_7745c5c3_Err != nil {2522 if templ_7745c5c3_Err != nil {
2513- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 473, Col: 29}2523+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 476, Col: 29}
2514 }2524 }
2515 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var125))2525 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var125))
2516 if templ_7745c5c3_Err != nil {2526 if templ_7745c5c3_Err != nil {
2517 return templ_7745c5c3_Err2527 return templ_7745c5c3_Err
2518 }2528 }
2519- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 224, "</p>")2529+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 225, "</p>")
2520 if templ_7745c5c3_Err != nil {2530 if templ_7745c5c3_Err != nil {
2521 return templ_7745c5c3_Err2531 return templ_7745c5c3_Err
2522 }2532 }
2523 }2533 }
2524- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 225, " ")2534+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 226, " ")
2525 if templ_7745c5c3_Err != nil {2535 if templ_7745c5c3_Err != nil {
2526 return templ_7745c5c3_Err2536 return templ_7745c5c3_Err
2527 }2537 }
2528 if p.Existing != nil {2538 if p.Existing != nil {
2529- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 226, "<p class=\"notice\">an open merge request already covers these branches: <a href=\"")2539+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 227, "<p class=\"notice\">an open merge request already covers these branches: <a href=\"")
2530 if templ_7745c5c3_Err != nil {2540 if templ_7745c5c3_Err != nil {
2531 return templ_7745c5c3_Err2541 return templ_7745c5c3_Err
2532 }2542 }
2533 var templ_7745c5c3_Var126 templ.SafeURL2543 var templ_7745c5c3_Var126 templ.SafeURL
2534 templ_7745c5c3_Var126, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.Existing.Href))2544 templ_7745c5c3_Var126, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.Existing.Href))
2535 if templ_7745c5c3_Err != nil {2545 if templ_7745c5c3_Err != nil {
2536- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 476, Col: 114}2546+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 479, Col: 114}
2537 }2547 }
2538 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var126))2548 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var126))
2539 if templ_7745c5c3_Err != nil {2549 if templ_7745c5c3_Err != nil {
2540 return templ_7745c5c3_Err2550 return templ_7745c5c3_Err
2541 }2551 }
2542- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 227, "\">")2552+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 228, "\">")
2543 if templ_7745c5c3_Err != nil {2553 if templ_7745c5c3_Err != nil {
2544 return templ_7745c5c3_Err2554 return templ_7745c5c3_Err
2545 }2555 }
2546 var templ_7745c5c3_Var127 string2556 var templ_7745c5c3_Var127 string
2547 templ_7745c5c3_Var127, templ_7745c5c3_Err = templ.JoinStringErrs(p.Existing.Label)2557 templ_7745c5c3_Var127, templ_7745c5c3_Err = templ.JoinStringErrs(p.Existing.Label)
2548 if templ_7745c5c3_Err != nil {2558 if templ_7745c5c3_Err != nil {
2549- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 476, Col: 135}2559+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 479, Col: 135}
2550 }2560 }
2551 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var127))2561 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var127))
2552 if templ_7745c5c3_Err != nil {2562 if templ_7745c5c3_Err != nil {
2553 return templ_7745c5c3_Err2563 return templ_7745c5c3_Err
2554 }2564 }
2555- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 228, "</a></p>")2565+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 229, "</a></p>")
2556 if templ_7745c5c3_Err != nil {2566 if templ_7745c5c3_Err != nil {
2557 return templ_7745c5c3_Err2567 return templ_7745c5c3_Err
2558 }2568 }
2559 }2569 }
2560- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 229, " ")2570+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 230, " ")
2561 if templ_7745c5c3_Err != nil {2571 if templ_7745c5c3_Err != nil {
2562 return templ_7745c5c3_Err2572 return templ_7745c5c3_Err
2563 }2573 }
2564 if p.Create != nil {2574 if p.Create != nil {
2565- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 230, "<form class=\"cform create\" method=\"post\" action=\"")2575+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 231, "<form class=\"cform create\" method=\"post\" action=\"")
2566 if templ_7745c5c3_Err != nil {2576 if templ_7745c5c3_Err != nil {
2567 return templ_7745c5c3_Err2577 return templ_7745c5c3_Err
2568 }2578 }
2569 var templ_7745c5c3_Var128 templ.SafeURL2579 var templ_7745c5c3_Var128 templ.SafeURL
2570 templ_7745c5c3_Var128, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.Create.Action))2580 templ_7745c5c3_Var128, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(p.Create.Action))
2571 if templ_7745c5c3_Err != nil {2581 if templ_7745c5c3_Err != nil {
2572- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 479, Col: 83}2582+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 482, Col: 83}
2573 }2583 }
2574 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var128))2584 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var128))
2575 if templ_7745c5c3_Err != nil {2585 if templ_7745c5c3_Err != nil {
2576 return templ_7745c5c3_Err2586 return templ_7745c5c3_Err
2577 }2587 }
2578- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 231, "\"><input type=\"hidden\" name=\"source\" value=\"")2588+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 232, "\"><input type=\"hidden\" name=\"source\" value=\"")
2579 if templ_7745c5c3_Err != nil {2589 if templ_7745c5c3_Err != nil {
2580 return templ_7745c5c3_Err2590 return templ_7745c5c3_Err
2581 }2591 }
2582 var templ_7745c5c3_Var129 string2592 var templ_7745c5c3_Var129 string
2583 templ_7745c5c3_Var129, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.Create.Source)2593 templ_7745c5c3_Var129, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.Create.Source)
2584 if templ_7745c5c3_Err != nil {2594 if templ_7745c5c3_Err != nil {
2585- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 480, Col: 62}2595+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 483, Col: 62}
2586 }2596 }
2587 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var129)2597 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var129)
2588 if templ_7745c5c3_Err != nil {2598 if templ_7745c5c3_Err != nil {
2589 return templ_7745c5c3_Err2599 return templ_7745c5c3_Err
2590 }2600 }
2591- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 232, "\"> <input type=\"hidden\" name=\"target\" value=\"")2601+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 233, "\"> <input type=\"hidden\" name=\"target\" value=\"")
2592 if templ_7745c5c3_Err != nil {2602 if templ_7745c5c3_Err != nil {
2593 return templ_7745c5c3_Err2603 return templ_7745c5c3_Err
2594 }2604 }
2595 var templ_7745c5c3_Var130 string2605 var templ_7745c5c3_Var130 string
2596 templ_7745c5c3_Var130, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.Create.Target)2606 templ_7745c5c3_Var130, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.Create.Target)
2597 if templ_7745c5c3_Err != nil {2607 if templ_7745c5c3_Err != nil {
2598- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 481, Col: 62}2608+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 484, Col: 62}
2599 }2609 }
2600 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var130)2610 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var130)
2601 if templ_7745c5c3_Err != nil {2611 if templ_7745c5c3_Err != nil {
2602 return templ_7745c5c3_Err2612 return templ_7745c5c3_Err
2603 }2613 }
2604- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 233, "\"> <label for=\"mr-title\">title</label> <input id=\"mr-title\" name=\"title\" type=\"text\" maxlength=\"120\" required value=\"")2614+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 234, "\"> <label for=\"mr-title\">title</label> <input id=\"mr-title\" name=\"title\" type=\"text\" maxlength=\"120\" required value=\"")
2605 if templ_7745c5c3_Err != nil {2615 if templ_7745c5c3_Err != nil {
2606 return templ_7745c5c3_Err2616 return templ_7745c5c3_Err
2607 }2617 }
2608 var templ_7745c5c3_Var131 string2618 var templ_7745c5c3_Var131 string
2609 templ_7745c5c3_Var131, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.Create.Title)2619 templ_7745c5c3_Var131, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.Create.Title)
2610 if templ_7745c5c3_Err != nil {2620 if templ_7745c5c3_Err != nil {
2611- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 483, Col: 97}2621+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 486, Col: 97}
2612 }2622 }
2613 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var131)2623 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var131)
2614 if templ_7745c5c3_Err != nil {2624 if templ_7745c5c3_Err != nil {
2615 return templ_7745c5c3_Err2625 return templ_7745c5c3_Err
2616 }2626 }
2617- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 234, "\" autocomplete=\"off\"> <label for=\"mr-desc\">description</label> <textarea id=\"mr-desc\" name=\"description\" rows=\"4\" maxlength=\"8000\" placeholder=\"Markdown, optional\"></textarea><div class=\"f-btns\"><button type=\"submit\" class=\"btn primary\">Create merge request</button></div></form>")2627+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 235, "\" autocomplete=\"off\"> <label for=\"mr-desc\">description</label> <textarea id=\"mr-desc\" name=\"description\" rows=\"4\" maxlength=\"8000\" placeholder=\"Markdown, optional\"></textarea><div class=\"f-btns\"><button type=\"submit\" class=\"btn primary\">Create merge request</button></div></form>")
2618 if templ_7745c5c3_Err != nil {2628 if templ_7745c5c3_Err != nil {
2619 return templ_7745c5c3_Err2629 return templ_7745c5c3_Err
2620 }2630 }
2621 }2631 }
2622- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 235, " ")2632+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 236, " ")
2623 if templ_7745c5c3_Err != nil {2633 if templ_7745c5c3_Err != nil {
2624 return templ_7745c5c3_Err2634 return templ_7745c5c3_Err
2625 }2635 }
2626 if p.HasDiff {2636 if p.HasDiff {
2627- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 236, "<div class=\"diff-tools\" role=\"group\" aria-label=\"Diff view\"><span class=\"dim\">")2637+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 237, "<div class=\"diff-tools\" role=\"group\" aria-label=\"Diff view\"><span class=\"dim\">")
2628 if templ_7745c5c3_Err != nil {2638 if templ_7745c5c3_Err != nil {
2629 return templ_7745c5c3_Err2639 return templ_7745c5c3_Err
2630 }2640 }
2631 var templ_7745c5c3_Var132 string2641 var templ_7745c5c3_Var132 string
2632 templ_7745c5c3_Var132, templ_7745c5c3_Err = templ.JoinStringErrs(plural(p.NFiles, "file", "files"))2642 templ_7745c5c3_Var132, templ_7745c5c3_Err = templ.JoinStringErrs(plural(p.NFiles, "file", "files"))
2633 if templ_7745c5c3_Err != nil {2643 if templ_7745c5c3_Err != nil {
2634- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 493, Col: 57}2644+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 496, Col: 57}
2635 }2645 }
2636 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var132))2646 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var132))
2637 if templ_7745c5c3_Err != nil {2647 if templ_7745c5c3_Err != nil {
2638 return templ_7745c5c3_Err2648 return templ_7745c5c3_Err
2639 }2649 }
2640- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 237, " · <span class=\"plus\">+")2650+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 238, " · <span class=\"plus\">+")
2641 if templ_7745c5c3_Err != nil {2651 if templ_7745c5c3_Err != nil {
2642 return templ_7745c5c3_Err2652 return templ_7745c5c3_Err
2643 }2653 }
2644 var templ_7745c5c3_Var133 string2654 var templ_7745c5c3_Var133 string
2645 templ_7745c5c3_Var133, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.Adds))2655 templ_7745c5c3_Var133, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.Adds))
2646 if templ_7745c5c3_Err != nil {2656 if templ_7745c5c3_Err != nil {
2647- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 493, Col: 97}2657+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 496, Col: 97}
2648 }2658 }
2649 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var133))2659 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var133))
2650 if templ_7745c5c3_Err != nil {2660 if templ_7745c5c3_Err != nil {
2651 return templ_7745c5c3_Err2661 return templ_7745c5c3_Err
2652 }2662 }
2653- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 238, "</span> <span class=\"minus\">-")2663+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 239, "</span> <span class=\"minus\">-")
2654 if templ_7745c5c3_Err != nil {2664 if templ_7745c5c3_Err != nil {
2655 return templ_7745c5c3_Err2665 return templ_7745c5c3_Err
2656 }2666 }
2657 var templ_7745c5c3_Var134 string2667 var templ_7745c5c3_Var134 string
2658 templ_7745c5c3_Var134, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.Dels))2668 templ_7745c5c3_Var134, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(p.Dels))
2659 if templ_7745c5c3_Err != nil {2669 if templ_7745c5c3_Err != nil {
2660- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 493, Col: 142}2670+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 496, Col: 142}
2661 }2671 }
2662 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var134))2672 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var134))
2663 if templ_7745c5c3_Err != nil {2673 if templ_7745c5c3_Err != nil {
2664 return templ_7745c5c3_Err2674 return templ_7745c5c3_Err
2665 }2675 }
2666- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 239, "</span></span> <span class=\"grow\"></span>")2676+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 240, "</span></span> <span class=\"grow\"></span>")
2667 if templ_7745c5c3_Err != nil {2677 if templ_7745c5c3_Err != nil {
2668 return templ_7745c5c3_Err2678 return templ_7745c5c3_Err
2669 }2679 }
@@ -2679,64 +2689,64 @@ func Compare(l Layout, p ComparePage) templ.Component {
2679 if templ_7745c5c3_Err != nil {2689 if templ_7745c5c3_Err != nil {
2680 return templ_7745c5c3_Err2690 return templ_7745c5c3_Err
2681 }2691 }
2682- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 240, "</div>")2692+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 241, "</div>")
2683 if templ_7745c5c3_Err != nil {2693 if templ_7745c5c3_Err != nil {
2684 return templ_7745c5c3_Err2694 return templ_7745c5c3_Err
2685 }2695 }
2686 if p.Invisible {2696 if p.Invisible {
2687- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 241, "<p class=\"notice\">this diff holds invisible characters (direction controls, zero-width characters). They are shown as <span class=\"inv\">&lt;U+XXXX&gt;</span> markers, never applied.</p>")2697+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 242, "<p class=\"notice\">this diff holds invisible characters (direction controls, zero-width characters). They are shown as <span class=\"inv\">&lt;U+XXXX&gt;</span> markers, never applied.</p>")
2688 if templ_7745c5c3_Err != nil {2698 if templ_7745c5c3_Err != nil {
2689 return templ_7745c5c3_Err2699 return templ_7745c5c3_Err
2690 }2700 }
2691 }2701 }
2692- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 242, " <div id=\"diffs\"")2702+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 243, " <div id=\"diffs\"")
2693 if templ_7745c5c3_Err != nil {2703 if templ_7745c5c3_Err != nil {
2694 return templ_7745c5c3_Err2704 return templ_7745c5c3_Err
2695 }2705 }
2696 if p.Both {2706 if p.Both {
2697- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 243, " data-diff=\"")2707+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 244, " data-diff=\"")
2698 if templ_7745c5c3_Err != nil {2708 if templ_7745c5c3_Err != nil {
2699 return templ_7745c5c3_Err2709 return templ_7745c5c3_Err
2700 }2710 }
2701 var templ_7745c5c3_Var135 string2711 var templ_7745c5c3_Var135 string
2702 templ_7745c5c3_Var135, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.View)2712 templ_7745c5c3_Var135, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.View)
2703 if templ_7745c5c3_Err != nil {2713 if templ_7745c5c3_Err != nil {
2704- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 508, Col: 23}2714+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 511, Col: 23}
2705 }2715 }
2706 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var135)2716 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var135)
2707 if templ_7745c5c3_Err != nil {2717 if templ_7745c5c3_Err != nil {
2708 return templ_7745c5c3_Err2718 return templ_7745c5c3_Err
2709 }2719 }
2710- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 244, "\"")2720+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 245, "\"")
2711 if templ_7745c5c3_Err != nil {2721 if templ_7745c5c3_Err != nil {
2712 return templ_7745c5c3_Err2722 return templ_7745c5c3_Err
2713 }2723 }
2714 } else {2724 } else {
2715- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 245, " data-view=\"")2725+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 246, " data-view=\"")
2716 if templ_7745c5c3_Err != nil {2726 if templ_7745c5c3_Err != nil {
2717 return templ_7745c5c3_Err2727 return templ_7745c5c3_Err
2718 }2728 }
2719 var templ_7745c5c3_Var136 string2729 var templ_7745c5c3_Var136 string
2720 templ_7745c5c3_Var136, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.View)2730 templ_7745c5c3_Var136, templ_7745c5c3_Err = templ.ResolveAttributeValue(p.View)
2721 if templ_7745c5c3_Err != nil {2731 if templ_7745c5c3_Err != nil {
2722- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 510, Col: 23}2732+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 513, Col: 23}
2723 }2733 }
2724 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var136)2734 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var136)
2725 if templ_7745c5c3_Err != nil {2735 if templ_7745c5c3_Err != nil {
2726 return templ_7745c5c3_Err2736 return templ_7745c5c3_Err
2727 }2737 }
2728- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 246, "\"")2738+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 247, "\"")
2729 if templ_7745c5c3_Err != nil {2739 if templ_7745c5c3_Err != nil {
2730 return templ_7745c5c3_Err2740 return templ_7745c5c3_Err
2731 }2741 }
2732 }2742 }
2733 if p.Both && !p.Pinned {2743 if p.Both && !p.Pinned {
2734- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 247, " hx-live=\"this.dataset.diff = sessionStorage.getItem('diff') || this.dataset.diff\"")2744+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 248, " hx-live=\"this.dataset.diff = sessionStorage.getItem('diff') || this.dataset.diff\"")
2735 if templ_7745c5c3_Err != nil {2745 if templ_7745c5c3_Err != nil {
2736 return templ_7745c5c3_Err2746 return templ_7745c5c3_Err
2737 }2747 }
2738 }2748 }
2739- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 248, ">")2749+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 249, ">")
2740 if templ_7745c5c3_Err != nil {2750 if templ_7745c5c3_Err != nil {
2741 return templ_7745c5c3_Err2751 return templ_7745c5c3_Err
2742 }2752 }
@@ -2746,7 +2756,7 @@ func Compare(l Layout, p ComparePage) templ.Component {
2746 return templ_7745c5c3_Err2756 return templ_7745c5c3_Err
2747 }2757 }
2748 }2758 }
2749- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 249, "</div>")2759+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 250, "</div>")
2750 if templ_7745c5c3_Err != nil {2760 if templ_7745c5c3_Err != nil {
2751 return templ_7745c5c3_Err2761 return templ_7745c5c3_Err
2752 }2762 }
@@ -2782,77 +2792,77 @@ func compareRail(p ComparePage) templ.Component {
2782 templ_7745c5c3_Var137 = templ.NopComponent2792 templ_7745c5c3_Var137 = templ.NopComponent
2783 }2793 }
2784 ctx = templ.ClearChildren(ctx)2794 ctx = templ.ClearChildren(ctx)
2785- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 250, "<section aria-labelledby=\"r-ahead\"><h2 id=\"r-ahead\">Commits <span class=\"count\">")2795+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 251, "<section aria-labelledby=\"r-ahead\"><h2 id=\"r-ahead\">Commits <span class=\"count\">")
2786 if templ_7745c5c3_Err != nil {2796 if templ_7745c5c3_Err != nil {
2787 return templ_7745c5c3_Err2797 return templ_7745c5c3_Err
2788 }2798 }
2789 var templ_7745c5c3_Var138 string2799 var templ_7745c5c3_Var138 string
2790 templ_7745c5c3_Var138, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(len(p.Ahead)))2800 templ_7745c5c3_Var138, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(len(p.Ahead)))
2791 if templ_7745c5c3_Err != nil {2801 if templ_7745c5c3_Err != nil {
2792- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 526, Col: 67}2802+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 529, Col: 67}
2793 }2803 }
2794 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var138))2804 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var138))
2795 if templ_7745c5c3_Err != nil {2805 if templ_7745c5c3_Err != nil {
2796 return templ_7745c5c3_Err2806 return templ_7745c5c3_Err
2797 }2807 }
2798- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 251, "</span></h2><ul class=\"pcommits\">")2808+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 252, "</span></h2><ul class=\"pcommits\">")
2799 if templ_7745c5c3_Err != nil {2809 if templ_7745c5c3_Err != nil {
2800 return templ_7745c5c3_Err2810 return templ_7745c5c3_Err
2801 }2811 }
2802 for _, c := range p.Ahead {2812 for _, c := range p.Ahead {
2803- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 252, "<li><a href=\"")2813+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 253, "<li><a href=\"")
2804 if templ_7745c5c3_Err != nil {2814 if templ_7745c5c3_Err != nil {
2805 return templ_7745c5c3_Err2815 return templ_7745c5c3_Err
2806 }2816 }
2807 var templ_7745c5c3_Var139 templ.SafeURL2817 var templ_7745c5c3_Var139 templ.SafeURL
2808 templ_7745c5c3_Var139, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(c.CHref))2818 templ_7745c5c3_Var139, templ_7745c5c3_Err = templ.JoinURLErrs(templ.SafeURL(c.CHref))
2809 if templ_7745c5c3_Err != nil {2819 if templ_7745c5c3_Err != nil {
2810- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 530, Col: 37}2820+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 533, Col: 37}
2811 }2821 }
2812 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var139))2822 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var139))
2813 if templ_7745c5c3_Err != nil {2823 if templ_7745c5c3_Err != nil {
2814 return templ_7745c5c3_Err2824 return templ_7745c5c3_Err
2815 }2825 }
2816- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 253, "\">")2826+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 254, "\">")
2817 if templ_7745c5c3_Err != nil {2827 if templ_7745c5c3_Err != nil {
2818 return templ_7745c5c3_Err2828 return templ_7745c5c3_Err
2819 }2829 }
2820 var templ_7745c5c3_Var140 string2830 var templ_7745c5c3_Var140 string
2821 templ_7745c5c3_Var140, templ_7745c5c3_Err = templ.JoinStringErrs(c.Short)2831 templ_7745c5c3_Var140, templ_7745c5c3_Err = templ.JoinStringErrs(c.Short)
2822 if templ_7745c5c3_Err != nil {2832 if templ_7745c5c3_Err != nil {
2823- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 530, Col: 49}2833+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 533, Col: 49}
2824 }2834 }
2825 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var140))2835 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var140))
2826 if templ_7745c5c3_Err != nil {2836 if templ_7745c5c3_Err != nil {
2827 return templ_7745c5c3_Err2837 return templ_7745c5c3_Err
2828 }2838 }
2829- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 254, "</a> <span class=\"s\">")2839+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 255, "</a> <span class=\"s\">")
2830 if templ_7745c5c3_Err != nil {2840 if templ_7745c5c3_Err != nil {
2831 return templ_7745c5c3_Err2841 return templ_7745c5c3_Err
2832 }2842 }
2833 var templ_7745c5c3_Var141 string2843 var templ_7745c5c3_Var141 string
2834 templ_7745c5c3_Var141, templ_7745c5c3_Err = templ.JoinStringErrs(c.Subject)2844 templ_7745c5c3_Var141, templ_7745c5c3_Err = templ.JoinStringErrs(c.Subject)
2835 if templ_7745c5c3_Err != nil {2845 if templ_7745c5c3_Err != nil {
2836- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 531, Col: 32}2846+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 534, Col: 32}
2837 }2847 }
2838 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var141))2848 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var141))
2839 if templ_7745c5c3_Err != nil {2849 if templ_7745c5c3_Err != nil {
2840 return templ_7745c5c3_Err2850 return templ_7745c5c3_Err
2841 }2851 }
2842- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 255, "</span> <span class=\"mute\">")2852+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 256, "</span> <span class=\"mute\">")
2843 if templ_7745c5c3_Err != nil {2853 if templ_7745c5c3_Err != nil {
2844 return templ_7745c5c3_Err2854 return templ_7745c5c3_Err
2845 }2855 }
2846 var templ_7745c5c3_Var142 string2856 var templ_7745c5c3_Var142 string
2847 templ_7745c5c3_Var142, templ_7745c5c3_Err = templ.JoinStringErrs(c.Author)2857 templ_7745c5c3_Var142, templ_7745c5c3_Err = templ.JoinStringErrs(c.Author)
2848 if templ_7745c5c3_Err != nil {2858 if templ_7745c5c3_Err != nil {
2849- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 533, Col: 16}2859+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 536, Col: 16}
2850 }2860 }
2851 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var142))2861 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var142))
2852 if templ_7745c5c3_Err != nil {2862 if templ_7745c5c3_Err != nil {
2853 return templ_7745c5c3_Err2863 return templ_7745c5c3_Err
2854 }2864 }
2855- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 256, " ")2865+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 257, " ")
2856 if templ_7745c5c3_Err != nil {2866 if templ_7745c5c3_Err != nil {
2857 return templ_7745c5c3_Err2867 return templ_7745c5c3_Err
2858 }2868 }
@@ -2860,90 +2870,90 @@ func compareRail(p ComparePage) templ.Component {
2860 var templ_7745c5c3_Var143 string2870 var templ_7745c5c3_Var143 string
2861 templ_7745c5c3_Var143, templ_7745c5c3_Err = templ.JoinStringErrs(" · ")2871 templ_7745c5c3_Var143, templ_7745c5c3_Err = templ.JoinStringErrs(" · ")
2862 if templ_7745c5c3_Err != nil {2872 if templ_7745c5c3_Err != nil {
2863- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 535, Col: 15}2873+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 538, Col: 15}
2864 }2874 }
2865 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var143))2875 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var143))
2866 if templ_7745c5c3_Err != nil {2876 if templ_7745c5c3_Err != nil {
2867 return templ_7745c5c3_Err2877 return templ_7745c5c3_Err
2868 }2878 }
2869- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 257, "<time datetime=\"")2879+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 258, "<time datetime=\"")
2870 if templ_7745c5c3_Err != nil {2880 if templ_7745c5c3_Err != nil {
2871 return templ_7745c5c3_Err2881 return templ_7745c5c3_Err
2872 }2882 }
2873 var templ_7745c5c3_Var144 string2883 var templ_7745c5c3_Var144 string
2874 templ_7745c5c3_Var144, templ_7745c5c3_Err = templ.ResolveAttributeValue(c.WhenAt)2884 templ_7745c5c3_Var144, templ_7745c5c3_Err = templ.ResolveAttributeValue(c.WhenAt)
2875 if templ_7745c5c3_Err != nil {2885 if templ_7745c5c3_Err != nil {
2876- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 535, Col: 42}2886+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 538, Col: 42}
2877 }2887 }
2878 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var144)2888 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var144)
2879 if templ_7745c5c3_Err != nil {2889 if templ_7745c5c3_Err != nil {
2880 return templ_7745c5c3_Err2890 return templ_7745c5c3_Err
2881 }2891 }
2882- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 258, "\">")2892+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 259, "\">")
2883 if templ_7745c5c3_Err != nil {2893 if templ_7745c5c3_Err != nil {
2884 return templ_7745c5c3_Err2894 return templ_7745c5c3_Err
2885 }2895 }
2886 var templ_7745c5c3_Var145 string2896 var templ_7745c5c3_Var145 string
2887 templ_7745c5c3_Var145, templ_7745c5c3_Err = templ.JoinStringErrs(c.When)2897 templ_7745c5c3_Var145, templ_7745c5c3_Err = templ.JoinStringErrs(c.When)
2888 if templ_7745c5c3_Err != nil {2898 if templ_7745c5c3_Err != nil {
2889- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 535, Col: 53}2899+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 538, Col: 53}
2890 }2900 }
2891 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var145))2901 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var145))
2892 if templ_7745c5c3_Err != nil {2902 if templ_7745c5c3_Err != nil {
2893 return templ_7745c5c3_Err2903 return templ_7745c5c3_Err
2894 }2904 }
2895- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 259, "</time>")2905+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 260, "</time>")
2896 if templ_7745c5c3_Err != nil {2906 if templ_7745c5c3_Err != nil {
2897 return templ_7745c5c3_Err2907 return templ_7745c5c3_Err
2898 }2908 }
2899 }2909 }
2900- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 260, "</span></li>")2910+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 261, "</span></li>")
2901 if templ_7745c5c3_Err != nil {2911 if templ_7745c5c3_Err != nil {
2902 return templ_7745c5c3_Err2912 return templ_7745c5c3_Err
2903 }2913 }
2904 }2914 }
2905- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 261, "</ul>")2915+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 262, "</ul>")
2906 if templ_7745c5c3_Err != nil {2916 if templ_7745c5c3_Err != nil {
2907 return templ_7745c5c3_Err2917 return templ_7745c5c3_Err
2908 }2918 }
2909 if len(p.Ahead) == 0 {2919 if len(p.Ahead) == 0 {
2910- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 262, "<p class=\"dim\">no commit ahead of ")2920+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 263, "<p class=\"dim\">no commit ahead of ")
2911 if templ_7745c5c3_Err != nil {2921 if templ_7745c5c3_Err != nil {
2912 return templ_7745c5c3_Err2922 return templ_7745c5c3_Err
2913 }2923 }
2914 var templ_7745c5c3_Var146 string2924 var templ_7745c5c3_Var146 string
2915 templ_7745c5c3_Var146, templ_7745c5c3_Err = templ.JoinStringErrs(p.Target)2925 templ_7745c5c3_Var146, templ_7745c5c3_Err = templ.JoinStringErrs(p.Target)
2916 if templ_7745c5c3_Err != nil {2926 if templ_7745c5c3_Err != nil {
2917- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 542, Col: 47}2927+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 545, Col: 47}
2918 }2928 }
2919 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var146))2929 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var146))
2920 if templ_7745c5c3_Err != nil {2930 if templ_7745c5c3_Err != nil {
2921 return templ_7745c5c3_Err2931 return templ_7745c5c3_Err
2922 }2932 }
2923- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 263, ".</p>")2933+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 264, ".</p>")
2924 if templ_7745c5c3_Err != nil {2934 if templ_7745c5c3_Err != nil {
2925 return templ_7745c5c3_Err2935 return templ_7745c5c3_Err
2926 }2936 }
2927 }2937 }
2928- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 264, "</section>")2938+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 265, "</section>")
2929 if templ_7745c5c3_Err != nil {2939 if templ_7745c5c3_Err != nil {
2930 return templ_7745c5c3_Err2940 return templ_7745c5c3_Err
2931 }2941 }
2932 if p.HasDiff {2942 if p.HasDiff {
2933- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 265, "<section aria-labelledby=\"r-files\"><h2 id=\"r-files\">Files <span class=\"count\">")2943+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 266, "<section aria-labelledby=\"r-files\"><h2 id=\"r-files\">Files <span class=\"count\">")
2934 if templ_7745c5c3_Err != nil {2944 if templ_7745c5c3_Err != nil {
2935 return templ_7745c5c3_Err2945 return templ_7745c5c3_Err
2936 }2946 }
2937 var templ_7745c5c3_Var147 string2947 var templ_7745c5c3_Var147 string
2938 templ_7745c5c3_Var147, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(len(p.Files)))2948 templ_7745c5c3_Var147, templ_7745c5c3_Err = templ.JoinStringErrs(itoa(len(p.Files)))
2939 if templ_7745c5c3_Err != nil {2949 if templ_7745c5c3_Err != nil {
2940- return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 547, Col: 66}2950+ return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/adapters/web/mr.templ`, Line: 550, Col: 66}
2941 }2951 }
2942 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var147))2952 _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var147))
2943 if templ_7745c5c3_Err != nil {2953 if templ_7745c5c3_Err != nil {
2944 return templ_7745c5c3_Err2954 return templ_7745c5c3_Err
2945 }2955 }
2946- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 266, "</span></h2>")2956+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 267, "</span></h2>")
2947 if templ_7745c5c3_Err != nil {2957 if templ_7745c5c3_Err != nil {
2948 return templ_7745c5c3_Err2958 return templ_7745c5c3_Err
2949 }2959 }
@@ -2951,12 +2961,12 @@ func compareRail(p ComparePage) templ.Component {
2951 if templ_7745c5c3_Err != nil {2961 if templ_7745c5c3_Err != nil {
2952 return templ_7745c5c3_Err2962 return templ_7745c5c3_Err
2953 }2963 }
2954- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 267, "</section>")2964+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 268, "</section>")
2955 if templ_7745c5c3_Err != nil {2965 if templ_7745c5c3_Err != nil {
2956 return templ_7745c5c3_Err2966 return templ_7745c5c3_Err
2957 }2967 }
2958 }2968 }
2959- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 268, "<section aria-labelledby=\"r-cli\"><h2 id=\"r-cli\">From a terminal</h2>")2969+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 269, "<section aria-labelledby=\"r-cli\"><h2 id=\"r-cli\">From a terminal</h2>")
2960 if templ_7745c5c3_Err != nil {2970 if templ_7745c5c3_Err != nil {
2961 return templ_7745c5c3_Err2971 return templ_7745c5c3_Err
2962 }2972 }
@@ -2964,7 +2974,7 @@ func compareRail(p ComparePage) templ.Component {
2964 if templ_7745c5c3_Err != nil {2974 if templ_7745c5c3_Err != nil {
2965 return templ_7745c5c3_Err2975 return templ_7745c5c3_Err
2966 }2976 }
2967- templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 269, "</section>")2977+ templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 270, "</section>")
2968 if templ_7745c5c3_Err != nil {2978 if templ_7745c5c3_Err != nil {
2969 return templ_7745c5c3_Err2979 return templ_7745c5c3_Err
2970 }2980 }
M internal/adapters/web/signature_test.go +12 -0
@@ -3,6 +3,7 @@
33 package web
44
55 import (
6+ "strings"
67 "testing"
78 "time"
89
@@ -139,3 +140,14 @@ func TestCommitPageShowsTheSignature(t *testing.T) {
139140 got = page(domain.CommitVerification{})
140141 assert.NotContains(t, got, "signature")
141142 }
143+
144+func TestMergeRequestCommitsShowTheSignatureBadge(t *testing.T) {
145+ t.Parallel()
146+ signed := signatureBadge(verification(domain.FormatGPG, domain.StatusVerified, gpgFP, ""), false)
147+ got := renderToString(t, mrRail(MRPage{Commits: []MRCommit{
148+ {Short: "aaaaaaa", Href: "/r/commit/a", Subject: "signed", Sig: signed},
149+ {Short: "bbbbbbb", Href: "/r/commit/b", Subject: "unsigned"},
150+ }}))
151+ assert.Equal(t, 1, strings.Count(got, `class="pill sig sig-ok"`), "only the signed commit has a pill")
152+ assert.Contains(t, got, `<span class="sig-proto">GPG</span> Verified`)
153+}
@@ -3,6 +3,7 @@
3 package web3 package web
4 4
5 import (5 import (
6+ "strings"
6 "testing"7 "testing"
7 "time"8 "time"
8 9
@@ -139,3 +140,14 @@ func TestCommitPageShowsTheSignature(t *testing.T) {
139 got = page(domain.CommitVerification{})140 got = page(domain.CommitVerification{})
140 assert.NotContains(t, got, "signature")141 assert.NotContains(t, got, "signature")
141 }142 }
143+
144+func TestMergeRequestCommitsShowTheSignatureBadge(t *testing.T) {
145+ t.Parallel()
146+ signed := signatureBadge(verification(domain.FormatGPG, domain.StatusVerified, gpgFP, ""), false)
147+ got := renderToString(t, mrRail(MRPage{Commits: []MRCommit{
148+ {Short: "aaaaaaa", Href: "/r/commit/a", Subject: "signed", Sig: signed},
149+ {Short: "bbbbbbb", Href: "/r/commit/b", Subject: "unsigned"},
150+ }}))
151+ assert.Equal(t, 1, strings.Count(got, `class="pill sig sig-ok"`), "only the signed commit has a pill")
152+ assert.Contains(t, got, `<span class="sig-proto">GPG</span> Verified`)
153+}
M internal/app/forge.go +1 -0
@@ -314,6 +314,7 @@ func newForge(ctx context.Context, cfg config.Config, opts options) (_ *forge, e
314314 Committer: committer, Bus: f.Bus, Clock: clock, Maint: f.maint,
315315 CI: f.CI, Checks: f.CI, PullRequests: f.CI, RefTips: store.CI(),
316316 })
317+ f.MergeRequests.WithVerifier(f.Signatures)
317318 f.CI.SetPullGate(f.MergeRequests)
318319 log.Info().Str("fingerprint", signer.PublicKey().Fingerprint).Msg("commit signing key ready")
319320
@@ -314,6 +314,7 @@ func newForge(ctx context.Context, cfg config.Config, opts options) (_ *forge, e
314 Committer: committer, Bus: f.Bus, Clock: clock, Maint: f.maint,314 Committer: committer, Bus: f.Bus, Clock: clock, Maint: f.maint,
315 CI: f.CI, Checks: f.CI, PullRequests: f.CI, RefTips: store.CI(),315 CI: f.CI, Checks: f.CI, PullRequests: f.CI, RefTips: store.CI(),
316 })316 })
317+ f.MergeRequests.WithVerifier(f.Signatures)
317 f.CI.SetPullGate(f.MergeRequests)318 f.CI.SetPullGate(f.MergeRequests)
318 log.Info().Str("fingerprint", signer.PublicKey().Fingerprint).Msg("commit signing key ready")319 log.Info().Str("fingerprint", signer.PublicKey().Fingerprint).Msg("commit signing key ready")
319 320
M internal/app/signatures_e2e_test.go +18 -0
@@ -135,6 +135,24 @@ func TestCommitSignaturesEndToEnd(t *testing.T) {
135135 assert.Contains(t, body, "GPG")
136136 assert.Contains(t, body, "sig-ok")
137137
138+ // A merge request lists its commits with their signature state, over the
139+ // API and on its page.
140+ h.mustGit(wt, "checkout", "-q", "-b", "feat")
141+ h.writeFile(wt, "d.txt", []byte("d\n"))
142+ h.mustGit(wt, "-c", "gpg.format=ssh", "-c", "user.signingkey="+sshKey+".pub", "commit", "-q", "--amend", "-S", "--no-edit")
143+ feat := strings.TrimSpace(h.mustGit(wt, "rev-parse", "HEAD"))
144+ h.mustGit(wt, "push", "-q", h.urlAuth(adminToken, "/sig.git"), "feat")
145+ _, err = root.mr.CreateMergeRequest(ctx, connect.NewRequest(&pb.CreateMergeRequestRequest{Repo: "sig", Title: "d", SourceBranch: "feat"}))
146+ require.NoError(t, err)
147+ mr, err := root.mr.GetMergeRequest(ctx, connect.NewRequest(&pb.GetMergeRequestRequest{Repo: "sig", Number: 1}))
148+ require.NoError(t, err)
149+ require.Len(t, mr.Msg.GetCommits(), 1)
150+ assert.Equal(t, feat, mr.Msg.GetCommits()[0].GetId())
151+ assert.Equal(t, pb.SignatureStatus_SIGNATURE_STATUS_VERIFIED, mr.Msg.GetCommits()[0].GetVerification().GetStatus())
152+ code, _, body = h.get("/sig/merge-requests/1")
153+ require.Equal(t, http.StatusOK, code)
154+ assert.Contains(t, body, `<span class="pill sig sig-ok"`)
155+
138156 // Removing the key turns the commit unknown again.
139157 _, err = trust.RemoveTrustedKey(ctx, connect.NewRequest(&pb.RemoveTrustedKeyRequest{Id: list.Msg.GetKeys()[1].GetId()}))
140158 require.NoError(t, err)
@@ -135,6 +135,24 @@ func TestCommitSignaturesEndToEnd(t *testing.T) {
135 assert.Contains(t, body, "GPG")135 assert.Contains(t, body, "GPG")
136 assert.Contains(t, body, "sig-ok")136 assert.Contains(t, body, "sig-ok")
137 137
138+ // A merge request lists its commits with their signature state, over the
139+ // API and on its page.
140+ h.mustGit(wt, "checkout", "-q", "-b", "feat")
141+ h.writeFile(wt, "d.txt", []byte("d\n"))
142+ h.mustGit(wt, "-c", "gpg.format=ssh", "-c", "user.signingkey="+sshKey+".pub", "commit", "-q", "--amend", "-S", "--no-edit")
143+ feat := strings.TrimSpace(h.mustGit(wt, "rev-parse", "HEAD"))
144+ h.mustGit(wt, "push", "-q", h.urlAuth(adminToken, "/sig.git"), "feat")
145+ _, err = root.mr.CreateMergeRequest(ctx, connect.NewRequest(&pb.CreateMergeRequestRequest{Repo: "sig", Title: "d", SourceBranch: "feat"}))
146+ require.NoError(t, err)
147+ mr, err := root.mr.GetMergeRequest(ctx, connect.NewRequest(&pb.GetMergeRequestRequest{Repo: "sig", Number: 1}))
148+ require.NoError(t, err)
149+ require.Len(t, mr.Msg.GetCommits(), 1)
150+ assert.Equal(t, feat, mr.Msg.GetCommits()[0].GetId())
151+ assert.Equal(t, pb.SignatureStatus_SIGNATURE_STATUS_VERIFIED, mr.Msg.GetCommits()[0].GetVerification().GetStatus())
152+ code, _, body = h.get("/sig/merge-requests/1")
153+ require.Equal(t, http.StatusOK, code)
154+ assert.Contains(t, body, `<span class="pill sig sig-ok"`)
155+
138 // Removing the key turns the commit unknown again.156 // Removing the key turns the commit unknown again.
139 _, err = trust.RemoveTrustedKey(ctx, connect.NewRequest(&pb.RemoveTrustedKeyRequest{Id: list.Msg.GetKeys()[1].GetId()}))157 _, err = trust.RemoveTrustedKey(ctx, connect.NewRequest(&pb.RemoveTrustedKeyRequest{Id: list.Msg.GetKeys()[1].GetId()}))
140 require.NoError(t, err)158 require.NoError(t, err)
M internal/usecase/browse.go +8 -2
@@ -67,10 +67,16 @@ func (b *Browse) WithVerifier(v ports.CommitVerifier) *Browse {
6767 // verify fills the Verification of the commits, in place, with one call. The
6868 // slice must not be shared with a cache.
6969 func (b *Browse) verify(ctx context.Context, repo domain.RepoName, commits []domain.Commit) {
70- if b.verifier == nil || len(commits) == 0 {
70+ verifyCommits(ctx, b.verifier, repo, commits)
71+}
72+
73+// verifyCommits fills the Verification of the commits in place, with one call
74+// to v; a nil v leaves them unchecked.
75+func verifyCommits(ctx context.Context, v ports.CommitVerifier, repo domain.RepoName, commits []domain.Commit) {
76+ if v == nil || len(commits) == 0 {
7177 return
7278 }
73- res := b.verifier.VerifyCommits(ctx, repo, commits)
79+ res := v.VerifyCommits(ctx, repo, commits)
7480 for i := range commits {
7581 if v, ok := res[commits[i].ID]; ok {
7682 commits[i].Verification = v
@@ -67,10 +67,16 @@ func (b *Browse) WithVerifier(v ports.CommitVerifier) *Browse {
67 // verify fills the Verification of the commits, in place, with one call. The67 // verify fills the Verification of the commits, in place, with one call. The
68 // slice must not be shared with a cache.68 // slice must not be shared with a cache.
69 func (b *Browse) verify(ctx context.Context, repo domain.RepoName, commits []domain.Commit) {69 func (b *Browse) verify(ctx context.Context, repo domain.RepoName, commits []domain.Commit) {
70- if b.verifier == nil || len(commits) == 0 {70+ verifyCommits(ctx, b.verifier, repo, commits)
71+}
72+
73+// verifyCommits fills the Verification of the commits in place, with one call
74+// to v; a nil v leaves them unchecked.
75+func verifyCommits(ctx context.Context, v ports.CommitVerifier, repo domain.RepoName, commits []domain.Commit) {
76+ if v == nil || len(commits) == 0 {
71 return77 return
72 }78 }
73- res := b.verifier.VerifyCommits(ctx, repo, commits)79+ res := v.VerifyCommits(ctx, repo, commits)
74 for i := range commits {80 for i := range commits {
75 if v, ok := res[commits[i].ID]; ok {81 if v, ok := res[commits[i].ID]; ok {
76 commits[i].Verification = v82 commits[i].Verification = v
M internal/usecase/mergerequests.go +9 -0
@@ -55,6 +55,7 @@ type MergeRequests struct {
5555 checks ports.CIChecksReader // nil: no CI, so no check blocks a merge
5656 pulls ports.PullRequestTrigger // nil: no pull_request workflows
5757 tips ports.CIRefTipStore // nil: who merges is not recorded
58+ verifier ports.CommitVerifier // nil: commits are not checked (ADR 0030)
5859
5960 mu sync.Mutex
6061 locks map[domain.RepoName]chan struct{}
@@ -105,6 +106,13 @@ func NewMergeRequests(cfg MergeRequestsConfig) *MergeRequests {
105106 }
106107 }
107108
109+// WithVerifier makes GetMergeRequest fill the signature state of the commits
110+// it lists (ADR 0030).
111+func (m *MergeRequests) WithVerifier(v ports.CommitVerifier) *MergeRequests {
112+ m.verifier = v
113+ return m
114+}
115+
108116 // lockRepo takes the merge lock of a repository, waiting until ctx ends. The
109117 // merges of one repository, and the creation of its merge requests, run one at
110118 // a time. The returned function releases the lock.
@@ -490,6 +498,7 @@ func (m *MergeRequests) Get(ctx context.Context, p domain.Principal, name domain
490498 if d.Commits, d.CommitsTruncated, err = m.git.ListRange(ctx, name, exclude, head, MaxMergeRequestCommits); err != nil {
491499 return ports.MergeRequestDetail{}, err
492500 }
501+ verifyCommits(ctx, m.verifier, name, d.Commits)
493502 }
494503 if opts.SinceLastRead && !d.LastReadID.IsZero() {
495504 switch ok, err := m.git.HasCommit(ctx, name, d.LastReadID); {
@@ -55,6 +55,7 @@ type MergeRequests struct {
55 checks ports.CIChecksReader // nil: no CI, so no check blocks a merge55 checks ports.CIChecksReader // nil: no CI, so no check blocks a merge
56 pulls ports.PullRequestTrigger // nil: no pull_request workflows56 pulls ports.PullRequestTrigger // nil: no pull_request workflows
57 tips ports.CIRefTipStore // nil: who merges is not recorded57 tips ports.CIRefTipStore // nil: who merges is not recorded
58+ verifier ports.CommitVerifier // nil: commits are not checked (ADR 0030)
58 59
59 mu sync.Mutex60 mu sync.Mutex
60 locks map[domain.RepoName]chan struct{}61 locks map[domain.RepoName]chan struct{}
@@ -105,6 +106,13 @@ func NewMergeRequests(cfg MergeRequestsConfig) *MergeRequests {
105 }106 }
106 }107 }
107 108
109+// WithVerifier makes GetMergeRequest fill the signature state of the commits
110+// it lists (ADR 0030).
111+func (m *MergeRequests) WithVerifier(v ports.CommitVerifier) *MergeRequests {
112+ m.verifier = v
113+ return m
114+}
115+
108 // lockRepo takes the merge lock of a repository, waiting until ctx ends. The116 // lockRepo takes the merge lock of a repository, waiting until ctx ends. The
109 // merges of one repository, and the creation of its merge requests, run one at117 // merges of one repository, and the creation of its merge requests, run one at
110 // a time. The returned function releases the lock.118 // a time. The returned function releases the lock.
@@ -490,6 +498,7 @@ func (m *MergeRequests) Get(ctx context.Context, p domain.Principal, name domain
490 if d.Commits, d.CommitsTruncated, err = m.git.ListRange(ctx, name, exclude, head, MaxMergeRequestCommits); err != nil {498 if d.Commits, d.CommitsTruncated, err = m.git.ListRange(ctx, name, exclude, head, MaxMergeRequestCommits); err != nil {
491 return ports.MergeRequestDetail{}, err499 return ports.MergeRequestDetail{}, err
492 }500 }
501+ verifyCommits(ctx, m.verifier, name, d.Commits)
493 }502 }
494 if opts.SinceLastRead && !d.LastReadID.IsZero() {503 if opts.SinceLastRead && !d.LastReadID.IsZero() {
495 switch ok, err := m.git.HasCommit(ctx, name, d.LastReadID); {504 switch ok, err := m.git.HasCommit(ctx, name, d.LastReadID); {
A internal/usecase/mergerequests_signatures_test.go +46 -0
@@ -0,0 +1,46 @@
1+// SPDX-License-Identifier: AGPL-3.0-or-later
2+
3+package usecase_test
4+
5+import (
6+ "testing"
7+
8+ "github.com/stretchr/testify/assert"
9+ "github.com/stretchr/testify/mock"
10+ "github.com/stretchr/testify/require"
11+
12+ "bnema.dev/ermite/internal/domain"
13+ "bnema.dev/ermite/internal/ports"
14+ "bnema.dev/ermite/internal/ports/mocks"
15+)
16+
17+// ADR 0030: the commits of a merge request carry their signature state when a
18+// verifier is set, in one call; without one they stay unchecked.
19+func TestGetMergeRequestVerifiesItsCommits(t *testing.T) {
20+ t.Parallel()
21+ r := newMRRig(t)
22+ r.seed()
23+ head := r.feature("feat")
24+ mr := r.open("feat")
25+
26+ d, err := r.mrs.Get(r.ctx, reader, r.repo, mr.Number, ports.GetMergeRequestOptions{})
27+ require.NoError(t, err)
28+ require.NotEmpty(t, d.Commits)
29+ assert.Equal(t, domain.StatusUnchecked, d.Commits[0].Verification.Status, "no verifier: unchecked")
30+
31+ v := mocks.NewCommitVerifier(t)
32+ want := domain.CommitVerification{Format: domain.FormatSSH, Status: domain.StatusVerified, KeyTitle: "laptop"}
33+ v.EXPECT().VerifyCommits(mock.Anything, r.repo, mock.MatchedBy(func(cs []domain.Commit) bool {
34+ return len(cs) == len(d.Commits) && cs[0].ID == head
35+ })).Return(map[domain.ObjectID]domain.CommitVerification{head: want}).Once()
36+ r.mrs.WithVerifier(v)
37+
38+ d, err = r.mrs.Get(r.ctx, reader, r.repo, mr.Number, ports.GetMergeRequestOptions{})
39+ require.NoError(t, err)
40+ assert.Equal(t, want, d.Commits[0].Verification)
41+
42+ // A diff-only read lists no commits and checks nothing.
43+ d, err = r.mrs.Get(r.ctx, reader, r.repo, mr.Number, ports.GetMergeRequestOptions{DiffOnly: true})
44+ require.NoError(t, err)
45+ assert.Empty(t, d.Commits)
46+}
@@ -0,0 +1,46 @@
1+// SPDX-License-Identifier: AGPL-3.0-or-later
2+
3+package usecase_test
4+
5+import (
6+ "testing"
7+
8+ "github.com/stretchr/testify/assert"
9+ "github.com/stretchr/testify/mock"
10+ "github.com/stretchr/testify/require"
11+
12+ "bnema.dev/ermite/internal/domain"
13+ "bnema.dev/ermite/internal/ports"
14+ "bnema.dev/ermite/internal/ports/mocks"
15+)
16+
17+// ADR 0030: the commits of a merge request carry their signature state when a
18+// verifier is set, in one call; without one they stay unchecked.
19+func TestGetMergeRequestVerifiesItsCommits(t *testing.T) {
20+ t.Parallel()
21+ r := newMRRig(t)
22+ r.seed()
23+ head := r.feature("feat")
24+ mr := r.open("feat")
25+
26+ d, err := r.mrs.Get(r.ctx, reader, r.repo, mr.Number, ports.GetMergeRequestOptions{})
27+ require.NoError(t, err)
28+ require.NotEmpty(t, d.Commits)
29+ assert.Equal(t, domain.StatusUnchecked, d.Commits[0].Verification.Status, "no verifier: unchecked")
30+
31+ v := mocks.NewCommitVerifier(t)
32+ want := domain.CommitVerification{Format: domain.FormatSSH, Status: domain.StatusVerified, KeyTitle: "laptop"}
33+ v.EXPECT().VerifyCommits(mock.Anything, r.repo, mock.MatchedBy(func(cs []domain.Commit) bool {
34+ return len(cs) == len(d.Commits) && cs[0].ID == head
35+ })).Return(map[domain.ObjectID]domain.CommitVerification{head: want}).Once()
36+ r.mrs.WithVerifier(v)
37+
38+ d, err = r.mrs.Get(r.ctx, reader, r.repo, mr.Number, ports.GetMergeRequestOptions{})
39+ require.NoError(t, err)
40+ assert.Equal(t, want, d.Commits[0].Verification)
41+
42+ // A diff-only read lists no commits and checks nothing.
43+ d, err = r.mrs.Get(r.ctx, reader, r.repo, mr.Number, ports.GetMergeRequestOptions{DiffOnly: true})
44+ require.NoError(t, err)
45+ assert.Empty(t, d.Commits)
46+}

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 42

↑↓ moveenter openesc close