fix: Invalid UTF-8 commit messages in JSON API responses (#37542)

This commit is contained in:
Nicolas
2026-05-07 16:19:45 +02:00
committed by GitHub
parent 2200ed7499
commit c9b9e376fb
54 changed files with 221 additions and 215 deletions
+3 -4
View File
@@ -4,7 +4,6 @@
package feed
import (
"strings"
"time"
"code.gitea.io/gitea/models/repo"
@@ -39,14 +38,14 @@ func ShowBranchFeed(ctx *context.Context, repo *repo.Repository, formatType stri
for _, commit := range commits {
feed.Items = append(feed.Items, &feeds.Item{
Id: commit.ID.String(),
Title: strings.TrimSpace(strings.Split(commit.Message(), "\n")[0]),
Title: commit.MessageTitle(),
Link: &feeds.Link{Href: repo.HTMLURL() + "/commit/" + commit.ID.String()},
Author: &feeds.Author{
Name: commit.Author.Name,
Email: commit.Author.Email,
},
Description: commit.Message(),
Content: commit.Message(),
Description: commit.MessageUTF8(), // TODO: description can be shorten content
Content: commit.MessageUTF8(),
Created: commit.Committer.When,
})
}
+3 -4
View File
@@ -4,7 +4,6 @@
package feed
import (
"strings"
"time"
"code.gitea.io/gitea/models/repo"
@@ -46,14 +45,14 @@ func ShowFileFeed(ctx *context.Context, repo *repo.Repository, formatType string
for _, commit := range commits {
feed.Items = append(feed.Items, &feeds.Item{
Id: commit.ID.String(),
Title: strings.TrimSpace(strings.Split(commit.Message(), "\n")[0]),
Title: commit.MessageTitle(),
Link: &feeds.Link{Href: repo.HTMLURL() + "/commit/" + commit.ID.String()},
Author: &feeds.Author{
Name: commit.Author.Name,
Email: commit.Author.Email,
},
Description: commit.Message(),
Content: commit.Message(),
Description: commit.MessageUTF8(), // TODO: description can be shorten content
Content: commit.MessageUTF8(),
Created: commit.Committer.When,
})
}
+1 -1
View File
@@ -231,7 +231,7 @@ func renderBlameFillFirstBlameRow(repoLink string, avatarUtils *templates.Avatar
br.PreviousSha = part.PreviousSha
br.PreviousShaURL = fmt.Sprintf("%s/blame/commit/%s/%s", repoLink, url.PathEscape(part.PreviousSha), util.PathEscapeSegments(part.PreviousPath))
br.CommitURL = fmt.Sprintf("%s/commit/%s", repoLink, url.PathEscape(part.Sha))
br.CommitMessage = commit.CommitMessage
br.CommitMessage = commit.MessageUTF8()
br.CommitSince = templates.TimeSince(commit.Author.When)
}
+1 -1
View File
@@ -349,7 +349,7 @@ func Diff(ctx *context.Context) {
parentCommitID = parentCommit.ID.String()
}
setCompareContext(ctx, parentCommit, commit, userName, repoName)
ctx.Data["Title"] = commit.Summary() + " · " + base.ShortSha(commitID)
ctx.Data["Title"] = commit.MessageTitle() + " · " + base.ShortSha(commitID)
ctx.Data["Commit"] = commit
ctx.Data["Diff"] = diff
ctx.Data["DiffBlobExcerptData"] = diffBlobExcerptData
+2 -5
View File
@@ -391,17 +391,14 @@ func prepareNewPullRequestTitleContent(ci *git_service.CompareInfo, commits []*g
if useFirstCommitAsTitle {
// the "commits" are from "ShowPrettyFormatLogToList", which is ordered from newest to oldest, here take the oldest one
c := commits[len(commits)-1]
title = strings.TrimSpace(c.UserCommit.Summary())
title = c.UserCommit.MessageTitle()
} else {
title = autoTitleFromBranchName(ci.HeadRef.ShortName())
}
if len(commits) == 1 {
// FIXME: GIT-COMMIT-MESSAGE-ENCODING: try to convert the encoding for commit message explicitly, ideally it should be done by a git commit struct method
c := commits[0]
_, content, _ = strings.Cut(strings.TrimSpace(c.UserCommit.CommitMessage), "\n")
content = strings.TrimSpace(content)
content = string(charset.ToUTF8([]byte(content), charset.ConvertOpts{}))
content = c.MessageBody()
}
var titleTrailer string
+4 -5
View File
@@ -6,7 +6,6 @@ package repo
import (
"strings"
"testing"
"unicode/utf8"
asymkey_model "code.gitea.io/gitea/models/asymkey"
git_model "code.gitea.io/gitea/models/git"
@@ -55,7 +54,7 @@ func TestNewPullRequestTitleContent(t *testing.T) {
SignCommit: &asymkey_model.SignCommit{
UserCommit: &user_model.UserCommit{
Commit: &git.Commit{
CommitMessage: msg,
CommitMessage: git.CommitMessage{MessageRaw: msg},
},
},
},
@@ -99,9 +98,9 @@ func TestNewPullRequestTitleContent(t *testing.T) {
assert.Equal(t, "title-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa…", title)
assert.Equal(t, "…aaaaaaaaa\n", content)
title, content = prepareNewPullRequestTitleContent(ci, []*git_model.SignCommitWithStatuses{mockCommit("a\xf0\xf0\xf0\nb\xf0\xf0\xf0")}, setting.RepoPRTitleSourceFirstCommit)
assert.Equal(t, "a?", title) // FIXME: GIT-COMMIT-MESSAGE-ENCODING: "title" doesn't use the same charset converting logic as "content"
assert.Equal(t, "b"+string(utf8.RuneError)+string(utf8.RuneError), content)
title, content = prepareNewPullRequestTitleContent(ci, []*git_model.SignCommitWithStatuses{mockCommit("title \xf0\nbody \xf0")}, setting.RepoPRTitleSourceFirstCommit)
assert.Equal(t, "title ð", title)
assert.Equal(t, "body ð", content)
}
func TestAutoTitleFromBranchName(t *testing.T) {
+2 -3
View File
@@ -6,7 +6,6 @@ package repo
import (
"bytes"
"net/http"
"strings"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
@@ -33,10 +32,10 @@ func CherryPick(ctx *context.Context) {
if ctx.FormString("cherry-pick-type") == "revert" {
ctx.Data["CherryPickType"] = "revert"
ctx.Data["commit_summary"] = "revert " + ctx.PathParam("sha")
ctx.Data["commit_message"] = "revert " + cherryPickCommit.Message()
ctx.Data["commit_message"] = "revert " + cherryPickCommit.MessageUTF8()
} else {
ctx.Data["CherryPickType"] = "cherry-pick"
ctx.Data["commit_summary"], ctx.Data["commit_message"], _ = strings.Cut(cherryPickCommit.Message(), "\n")
ctx.Data["commit_summary"], ctx.Data["commit_message"] = cherryPickCommit.MessageTitle(), cherryPickCommit.MessageBody()
}
ctx.HTML(http.StatusOK, tplCherryPick)
+2 -2
View File
@@ -675,7 +675,7 @@ func TestWebhook(ctx *context.Context) {
ID: objectFormat.EmptyObjectID(),
Author: ghost.NewGitSig(),
Committer: ghost.NewGitSig(),
CommitMessage: "This is a fake commit",
CommitMessage: git.CommitMessage{MessageRaw: "This is a fake commit"},
}
}
@@ -683,7 +683,7 @@ func TestWebhook(ctx *context.Context) {
apiCommit := &api.PayloadCommit{
ID: commit.ID.String(),
Message: commit.Message(),
Message: commit.MessageUTF8(),
URL: ctx.Repo.Repository.HTMLURL() + "/commit/" + url.PathEscape(commit.ID.String()),
Author: &api.PayloadUser{
Name: commit.Author.Name,