mirror of
https://github.com/go-gitea/gitea.git
synced 2026-09-24 21:53:39 +09:00
fix(repo): commit page fails to render unsigned commits with a different committer (#39381)
Since #39229 the commit page header dereferences `.Verification.CommittingUser` when the committer is not the author. `Verification` is `nil` for unsigned commits (see `repo.Diff`), so opening such a commit — a rebased or cherry-picked one, for example — logs a template error and the page comes out truncated: ``` Render failed: failed to render template: repo/commit_page, error: template error: builtin(bindata):repo/commit_page:138:22 : executing "repo/commit_page" at <.Verification.CommittingUser>: nil pointer evaluating interface {}.CommittingUser ``` This guards the access and adds an integration test that creates a commit with distinct author and committer identities and checks the page renders completely (the status stays 200 on a mid-render failure, so the test looks at the body). _The fix was worked out with help from an AI assistant; I reviewed and tested it myself._ --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
@@ -29,6 +29,8 @@ type FastImportCommit struct {
|
||||
Ref string
|
||||
Message string
|
||||
Files []FastImportFile
|
||||
|
||||
Author, Committer *Signature
|
||||
}
|
||||
|
||||
// ForceFastImportWithInit is for mainly for testing purpose
|
||||
@@ -48,15 +50,32 @@ func ForceFastImportWithInit(ctx context.Context, repoLocalPath string, commits
|
||||
|
||||
// ForceFastImport is for mainly for testing purpose
|
||||
func ForceFastImport(ctx context.Context, repo RepositoryFacade, commits []FastImportCommit) error {
|
||||
var buf bytes.Buffer
|
||||
buf := &bytes.Buffer{}
|
||||
for i, c := range commits {
|
||||
msg := util.IfZero(c.Message, fmt.Sprintf("commit %d", i+1))
|
||||
_, _ = fmt.Fprintf(&buf, "reset %s\n", c.Ref)
|
||||
_, _ = fmt.Fprintf(&buf, "commit %s\nmark :%d\ncommitter Gitea <gitea@example.com> 1500000000 +0000\n", c.Ref, i+1)
|
||||
_, _ = fmt.Fprintf(&buf, "data %d\n%s\n", len(msg), msg)
|
||||
_, _ = fmt.Fprintf(buf, "reset %s\n", c.Ref)
|
||||
_, _ = fmt.Fprintf(buf, "commit %s\n", c.Ref)
|
||||
_, _ = fmt.Fprintf(buf, "mark :%d\n", i+1)
|
||||
|
||||
if c.Author != nil {
|
||||
buf.WriteString("author ")
|
||||
_ = c.Author.Encode(buf)
|
||||
buf.WriteByte('\n')
|
||||
}
|
||||
if c.Committer != nil {
|
||||
buf.WriteString("committer ")
|
||||
_ = c.Committer.Encode(buf)
|
||||
buf.WriteByte('\n')
|
||||
} else {
|
||||
// "committer" is required, so we use a default one if not provided
|
||||
buf.WriteString("committer Gitea <gitea@example.com> 1500000000 +0000\n")
|
||||
}
|
||||
|
||||
msg := util.IfZero(c.Message, fmt.Sprintf("test commit %d", i+1))
|
||||
_, _ = fmt.Fprintf(buf, "data %d\n%s\n", len(msg), msg)
|
||||
|
||||
for _, f := range c.Files {
|
||||
mode := util.IfZero(f.Mode, EntryModeBlob)
|
||||
_, _ = fmt.Fprintf(&buf, "M %s inline %s\ndata %d\n%s\n", mode.String(), f.Path, len(f.Content), f.Content)
|
||||
_, _ = fmt.Fprintf(buf, "M %s inline %s\ndata %d\n%s\n", mode.String(), f.Path, len(f.Content), f.Content)
|
||||
}
|
||||
}
|
||||
buf.WriteString("done\n")
|
||||
|
||||
@@ -8,6 +8,7 @@ package git
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"gitea.dev/modules/util"
|
||||
@@ -24,7 +25,13 @@ func (s *Signature) String() string {
|
||||
return fmt.Sprintf("%s <%s>", s.Name, s.Email)
|
||||
}
|
||||
|
||||
// Decode decodes a byte array representing a signature to signature
|
||||
// Encode writes the signature for git commit object (same as gogit's object.Signature Encode method)
|
||||
func (s *Signature) Encode(w io.Writer) error {
|
||||
_, err := fmt.Fprintf(w, "%s <%s> %d %s", s.Name, s.Email, max(0, s.When.Unix()), s.When.Format("-0700"))
|
||||
return err
|
||||
}
|
||||
|
||||
// Decode parses the signature for git commit object (same as gogit's object.Signature Decode method)
|
||||
func (s *Signature) Decode(b []byte) {
|
||||
*s = *parseSignatureFromCommitLine(util.UnsafeBytesToString(b))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user