mirror of
https://github.com/go-gitea/gitea.git
synced 2026-05-13 17:04:36 +00:00
fix: Invalid UTF-8 commit messages in JSON API responses (#37542)
This commit is contained in:
@@ -261,7 +261,7 @@ func UpdateBranch(ctx context.Context, repoID, pusherID int64, branchName string
|
||||
Cols("commit_id, commit_message, pusher_id, commit_time, is_deleted, updated_unix").
|
||||
Update(&Branch{
|
||||
CommitID: commit.ID.String(),
|
||||
CommitMessage: commit.Summary(),
|
||||
CommitMessage: commit.MessageTitle(),
|
||||
PusherID: pusherID,
|
||||
CommitTime: timeutil.TimeStamp(commit.Committer.When.Unix()),
|
||||
IsDeleted: false,
|
||||
|
||||
@@ -36,7 +36,7 @@ func TestAddDeletedBranch(t *testing.T) {
|
||||
|
||||
commit := &git.Commit{
|
||||
ID: git.MustIDFromString(secondBranch.CommitID),
|
||||
CommitMessage: secondBranch.CommitMessage,
|
||||
CommitMessage: git.CommitMessage{MessageRaw: secondBranch.CommitMessage},
|
||||
Committer: &git.Signature{
|
||||
When: secondBranch.CommitTime.AsLocalTime(),
|
||||
},
|
||||
|
||||
@@ -89,7 +89,10 @@ func ToUTF8(content []byte, opts ConvertOpts) []byte {
|
||||
encoding, _ := charset.Lookup(charsetLabel)
|
||||
if encoding == nil {
|
||||
setting.PanicInDevOrTesting("unsupported detected charset %q, it shouldn't happen", charsetLabel)
|
||||
return content
|
||||
if opts.ErrorReturnOrigin {
|
||||
return content
|
||||
}
|
||||
return bytes.ToValidUTF8(content, opts.ErrorReplacement)
|
||||
}
|
||||
|
||||
var decoded []byte
|
||||
|
||||
@@ -11,19 +11,28 @@ import (
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/charset"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
type CommitMessage struct {
|
||||
MessageRaw string
|
||||
messageUTF8 *string
|
||||
messageTitle *string
|
||||
messageBody *string
|
||||
}
|
||||
|
||||
// Commit represents a git commit.
|
||||
type Commit struct {
|
||||
Tree // FIXME: bad design, this field can be nil if the commit is from "last commit cache"
|
||||
|
||||
ID ObjectID
|
||||
Author *Signature // never nil
|
||||
Committer *Signature // never nil
|
||||
CommitMessage string
|
||||
Signature *CommitSignature
|
||||
CommitMessage
|
||||
|
||||
ID ObjectID
|
||||
Author *Signature // never nil
|
||||
Committer *Signature // never nil
|
||||
Signature *CommitSignature
|
||||
|
||||
Parents []ObjectID // ID strings
|
||||
submoduleCache *ObjectCache[*SubModule]
|
||||
@@ -35,19 +44,28 @@ type CommitSignature struct {
|
||||
Payload string
|
||||
}
|
||||
|
||||
// Message returns the commit message. Same as retrieving CommitMessage directly.
|
||||
func (c *Commit) Message() string {
|
||||
// FIXME: GIT-COMMIT-MESSAGE-ENCODING: this logic is not right
|
||||
// * When need to use commit message in templates/database, it should be valid UTF-8
|
||||
// * When need to get the original commit message, it should just use "c.CommitMessage"
|
||||
// It's not easy to refactor at the moment, many templates need to be updated and tested
|
||||
return c.CommitMessage
|
||||
func (c *CommitMessage) MessageUTF8() string {
|
||||
if c.messageUTF8 == nil {
|
||||
bs := charset.ToUTF8(util.UnsafeStringToBytes(c.MessageRaw), charset.ConvertOpts{ErrorReplacement: []byte{'?'}})
|
||||
c.messageUTF8 = new(util.UnsafeBytesToString(bs))
|
||||
}
|
||||
return *c.messageUTF8
|
||||
}
|
||||
|
||||
// Summary returns first line of commit message.
|
||||
// The string is forced to be valid UTF8
|
||||
func (c *Commit) Summary() string {
|
||||
return strings.ToValidUTF8(strings.Split(strings.TrimSpace(c.CommitMessage), "\n")[0], "?")
|
||||
func (c *CommitMessage) MessageTitle() string {
|
||||
if c.messageTitle == nil {
|
||||
s, _, _ := strings.Cut(strings.TrimSpace(c.MessageUTF8()), "\n")
|
||||
c.messageTitle = new(strings.TrimSpace(s))
|
||||
}
|
||||
return *c.messageTitle
|
||||
}
|
||||
|
||||
func (c *CommitMessage) MessageBody() string {
|
||||
if c.messageBody == nil {
|
||||
_, s, _ := strings.Cut(strings.TrimSpace(c.MessageUTF8()), "\n")
|
||||
c.messageBody = new(strings.TrimSpace(s))
|
||||
}
|
||||
return *c.messageBody
|
||||
}
|
||||
|
||||
// ParentID returns oid of n-th parent (0-based index).
|
||||
|
||||
@@ -66,7 +66,7 @@ func convertPGPSignature(c *object.Commit) *CommitSignature {
|
||||
func convertCommit(c *object.Commit) *Commit {
|
||||
return &Commit{
|
||||
ID: ParseGogitHash(c.Hash),
|
||||
CommitMessage: c.Message,
|
||||
CommitMessage: CommitMessage{MessageRaw: c.Message},
|
||||
Committer: &c.Committer,
|
||||
Author: &c.Author,
|
||||
Signature: convertPGPSignature(c),
|
||||
|
||||
@@ -92,7 +92,7 @@ func CommitFromReader(gitRepo *Repository, objectID ObjectID, reader io.Reader)
|
||||
}
|
||||
}
|
||||
|
||||
commit.CommitMessage = messageSB.String()
|
||||
commit.MessageRaw = messageSB.String()
|
||||
if commit.Signature != nil {
|
||||
commit.Signature.Payload = payloadSB.String()
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ signed commit`, commitFromReader.Signature.Payload)
|
||||
|
||||
commitFromReader2, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString+"\n\n"))
|
||||
assert.NoError(t, err)
|
||||
commitFromReader.CommitMessage += "\n\n"
|
||||
commitFromReader.CommitMessage.MessageRaw += "\n\n"
|
||||
commitFromReader.Signature.Payload += "\n\n"
|
||||
assert.Equal(t, commitFromReader, commitFromReader2)
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ empty commit`, commitFromReader.Signature.Payload)
|
||||
|
||||
commitFromReader2, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString+"\n\n"))
|
||||
assert.NoError(t, err)
|
||||
commitFromReader.CommitMessage += "\n\n"
|
||||
commitFromReader.CommitMessage.MessageRaw += "\n\n"
|
||||
commitFromReader.Signature.Payload += "\n\n"
|
||||
assert.Equal(t, commitFromReader, commitFromReader2)
|
||||
}
|
||||
@@ -154,11 +154,20 @@ ISO-8859-1`, commitFromReader.Signature.Payload)
|
||||
|
||||
commitFromReader2, err := CommitFromReader(gitRepo, sha, strings.NewReader(commitString+"\n\n"))
|
||||
assert.NoError(t, err)
|
||||
commitFromReader.CommitMessage += "\n\n"
|
||||
commitFromReader.CommitMessage.MessageRaw += "\n\n"
|
||||
commitFromReader.Signature.Payload += "\n\n"
|
||||
assert.Equal(t, commitFromReader, commitFromReader2)
|
||||
}
|
||||
|
||||
func TestCommitMessageSanitizesInvalidUTF8(t *testing.T) {
|
||||
commit := &Commit{
|
||||
CommitMessage: CommitMessage{MessageRaw: "title \xff\n\n\n\nbody \xff\n\n\n"},
|
||||
}
|
||||
assert.Equal(t, "title ÿ", commit.MessageTitle())
|
||||
assert.Equal(t, "body ÿ", commit.MessageBody())
|
||||
assert.Equal(t, "title ÿ\n\n\n\nbody ÿ\n\n\n", commit.MessageUTF8())
|
||||
}
|
||||
|
||||
func TestHasPreviousCommit(t *testing.T) {
|
||||
bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
|
||||
|
||||
|
||||
@@ -111,8 +111,6 @@ func (p *Parser) parseRef(refBlock string) (map[string]string, error) {
|
||||
len(fields), len(p.format.fieldNames))
|
||||
}
|
||||
for i, field := range fields {
|
||||
field = strings.TrimSpace(field)
|
||||
|
||||
var fieldKey string
|
||||
var fieldVal string
|
||||
before, after, ok := strings.Cut(field, " ")
|
||||
|
||||
@@ -116,12 +116,12 @@ func TestParser(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"refname:short": "v0.0.2",
|
||||
"contents": "Update CI config (#651)",
|
||||
"contents": "Update CI config (#651)\n\n",
|
||||
"author": "John Doe <john.doe@foo.com> 1521643174 +0000",
|
||||
},
|
||||
{
|
||||
"refname:short": "v0.0.3",
|
||||
"contents": "Fixed code sample for bash completion (#687)",
|
||||
"contents": "Fixed code sample for bash completion (#687)\n\n",
|
||||
"author": "Foo Baz <foo@baz.com> 1524836750 +0200",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"bytes"
|
||||
"io"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/git/gitcmd"
|
||||
@@ -97,7 +96,7 @@ func findLFSFileFunc(repo *git.Repository, objectID git.ObjectID, revListReader
|
||||
result := LFSResult{
|
||||
Name: curPath + fname,
|
||||
SHA: curCommit.ID.String(),
|
||||
Summary: strings.Split(strings.TrimSpace(curCommit.CommitMessage), "\n")[0],
|
||||
Summary: curCommit.MessageTitle(),
|
||||
When: curCommit.Author.When,
|
||||
ParentHashes: curCommit.Parents,
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ func TestGetTagCommitWithSignature(t *testing.T) {
|
||||
assert.NotNil(t, commit)
|
||||
assert.NotNil(t, commit.Signature)
|
||||
// test that signature is not in message
|
||||
assert.Equal(t, "signed-commit\n", commit.CommitMessage)
|
||||
assert.Equal(t, "signed-commit\n", commit.CommitMessage.MessageRaw)
|
||||
}
|
||||
|
||||
func TestGetCommitWithBadCommitID(t *testing.T) {
|
||||
|
||||
@@ -176,15 +176,14 @@ func parseTagRef(ref map[string]string) (tag *Tag, err error) {
|
||||
}
|
||||
|
||||
tag.Tagger = parseSignatureFromCommitLine(ref["creator"])
|
||||
tag.Message = ref["contents"]
|
||||
tag.MessageRaw = ref["contents"]
|
||||
|
||||
// strip any signature if present in contents field
|
||||
_, tag.Message, _ = parsePayloadSignature(util.UnsafeStringToBytes(tag.Message), 0)
|
||||
_, tag.MessageRaw, _ = parsePayloadSignature(util.UnsafeStringToBytes(tag.MessageRaw), 0)
|
||||
|
||||
// annotated tag with GPG signature
|
||||
if tag.Type == "tag" && ref["contents:signature"] != "" {
|
||||
payload := fmt.Sprintf("object %s\ntype commit\ntag %s\ntagger %s\n\n%s\n",
|
||||
tag.Object, tag.Name, ref["creator"], strings.TrimSpace(tag.Message))
|
||||
payload := fmt.Sprintf("object %s\ntype commit\ntag %s\ntagger %s\n\n%s", tag.Object, tag.Name, ref["creator"], tag.MessageRaw)
|
||||
tag.Signature = &CommitSignature{
|
||||
Signature: ref["contents:signature"],
|
||||
Payload: payload,
|
||||
|
||||
@@ -64,12 +64,12 @@ func (repo *Repository) getTag(tagID ObjectID, name string) (*Tag, error) {
|
||||
return nil, err
|
||||
}
|
||||
tag := &Tag{
|
||||
Name: name,
|
||||
ID: tagID,
|
||||
Object: commitID,
|
||||
Type: tp,
|
||||
Tagger: commit.Committer,
|
||||
Message: commit.Message(),
|
||||
Name: name,
|
||||
ID: tagID,
|
||||
Object: commitID,
|
||||
Type: tp,
|
||||
Tagger: commit.Committer,
|
||||
CommitMessage: CommitMessage{MessageRaw: commit.CommitMessage.MessageRaw},
|
||||
}
|
||||
|
||||
repo.tagCache.Set(tagID.String(), tag)
|
||||
@@ -86,12 +86,12 @@ func (repo *Repository) getTag(tagID ObjectID, name string) (*Tag, error) {
|
||||
}
|
||||
|
||||
tag := &Tag{
|
||||
Name: name,
|
||||
ID: tagID,
|
||||
Object: commitID.Type().MustID(gogitTag.Target[:]),
|
||||
Type: tp,
|
||||
Tagger: &gogitTag.Tagger,
|
||||
Message: gogitTag.Message,
|
||||
Name: name,
|
||||
ID: tagID,
|
||||
Object: commitID.Type().MustID(gogitTag.Target[:]),
|
||||
Type: tp,
|
||||
Tagger: &gogitTag.Tagger,
|
||||
CommitMessage: CommitMessage{MessageRaw: gogitTag.Message},
|
||||
}
|
||||
|
||||
repo.tagCache.Set(tagID.String(), tag)
|
||||
|
||||
@@ -71,12 +71,12 @@ func (repo *Repository) getTag(tagID ObjectID, name string) (*Tag, error) {
|
||||
return nil, err
|
||||
}
|
||||
tag := &Tag{
|
||||
Name: name,
|
||||
ID: tagID,
|
||||
Object: commitID,
|
||||
Type: tp,
|
||||
Tagger: commit.Committer,
|
||||
Message: commit.Message(),
|
||||
Name: name,
|
||||
ID: tagID,
|
||||
Object: commitID,
|
||||
Type: tp,
|
||||
Tagger: commit.Committer,
|
||||
CommitMessage: commit.CommitMessage,
|
||||
}
|
||||
|
||||
repo.tagCache.Set(tagID.String(), tag)
|
||||
|
||||
@@ -211,13 +211,13 @@ func TestRepository_parseTagRef(t *testing.T) {
|
||||
},
|
||||
|
||||
want: &Tag{
|
||||
Name: "v1.9.1",
|
||||
ID: MustIDFromString("ab23e4b7f4cd0caafe0174c0e7ef6d651ba72889"),
|
||||
Object: MustIDFromString("ab23e4b7f4cd0caafe0174c0e7ef6d651ba72889"),
|
||||
Type: "commit",
|
||||
Tagger: parseSignatureFromCommitLine("Foo Bar <foo@bar.com> 1565789218 +0300"),
|
||||
Message: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md\n",
|
||||
Signature: nil,
|
||||
Name: "v1.9.1",
|
||||
ID: MustIDFromString("ab23e4b7f4cd0caafe0174c0e7ef6d651ba72889"),
|
||||
Object: MustIDFromString("ab23e4b7f4cd0caafe0174c0e7ef6d651ba72889"),
|
||||
Type: "commit",
|
||||
Tagger: parseSignatureFromCommitLine("Foo Bar <foo@bar.com> 1565789218 +0300"),
|
||||
CommitMessage: CommitMessage{MessageRaw: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md\n"},
|
||||
Signature: nil,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -240,13 +240,13 @@ func TestRepository_parseTagRef(t *testing.T) {
|
||||
},
|
||||
|
||||
want: &Tag{
|
||||
Name: "v0.0.1",
|
||||
ID: MustIDFromString("8c68a1f06fc59c655b7e3905b159d761e91c53c9"),
|
||||
Object: MustIDFromString("3325fd8a973321fd59455492976c042dde3fd1ca"),
|
||||
Type: "tag",
|
||||
Tagger: parseSignatureFromCommitLine("Foo Bar <foo@bar.com> 1565789218 +0300"),
|
||||
Message: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md\n",
|
||||
Signature: nil,
|
||||
Name: "v0.0.1",
|
||||
ID: MustIDFromString("8c68a1f06fc59c655b7e3905b159d761e91c53c9"),
|
||||
Object: MustIDFromString("3325fd8a973321fd59455492976c042dde3fd1ca"),
|
||||
Type: "tag",
|
||||
Tagger: parseSignatureFromCommitLine("Foo Bar <foo@bar.com> 1565789218 +0300"),
|
||||
CommitMessage: CommitMessage{MessageRaw: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md\n"},
|
||||
Signature: nil,
|
||||
},
|
||||
},
|
||||
|
||||
@@ -263,6 +263,7 @@ func TestRepository_parseTagRef(t *testing.T) {
|
||||
|
||||
* add changelog of v1.9.1
|
||||
* Update CHANGELOG.md
|
||||
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
aBCGzBAABCgAdFiEEyWRwv/q1Q6IjSv+D4IPOwzt33PoFAmI8jbIACgkQ4IPOwzt3
|
||||
@@ -298,12 +299,12 @@ qbHDASXl
|
||||
},
|
||||
|
||||
want: &Tag{
|
||||
Name: "v0.0.1",
|
||||
ID: MustIDFromString("8c68a1f06fc59c655b7e3905b159d761e91c53c9"),
|
||||
Object: MustIDFromString("3325fd8a973321fd59455492976c042dde3fd1ca"),
|
||||
Type: "tag",
|
||||
Tagger: parseSignatureFromCommitLine("Foo Bar <foo@bar.com> 1565789218 +0300"),
|
||||
Message: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md",
|
||||
Name: "v0.0.1",
|
||||
ID: MustIDFromString("8c68a1f06fc59c655b7e3905b159d761e91c53c9"),
|
||||
Object: MustIDFromString("3325fd8a973321fd59455492976c042dde3fd1ca"),
|
||||
Type: "tag",
|
||||
Tagger: parseSignatureFromCommitLine("Foo Bar <foo@bar.com> 1565789218 +0300"),
|
||||
CommitMessage: CommitMessage{MessageRaw: "Add changelog of v1.9.1 (#7859)\n\n* add changelog of v1.9.1\n* Update CHANGELOG.md\n"},
|
||||
Signature: &CommitSignature{
|
||||
Signature: `-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
|
||||
@@ -12,12 +12,13 @@ import (
|
||||
|
||||
// Tag represents a Git tag.
|
||||
type Tag struct {
|
||||
CommitMessage
|
||||
|
||||
Name string
|
||||
ID ObjectID
|
||||
Object ObjectID // The id of this commit object
|
||||
Type string
|
||||
Tagger *Signature
|
||||
Message string
|
||||
Signature *CommitSignature
|
||||
}
|
||||
|
||||
@@ -87,7 +88,7 @@ func parseTagData(objectFormat ObjectFormat, data []byte) (*Tag, error) {
|
||||
pos += eol + 1
|
||||
}
|
||||
payload, msg, sign := parsePayloadSignature(data, pos)
|
||||
tag.Message = msg
|
||||
tag.MessageRaw = msg
|
||||
if len(sign) > 0 {
|
||||
tag.Signature = &CommitSignature{Signature: sign, Payload: payload}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ tagger Lucas Michot <lucas@semalead.com> 1484491741 +0100
|
||||
Object: MustIDFromString("3b114ab800c6432ad42387ccf6bc8d4388a2885a"),
|
||||
Type: "commit",
|
||||
Tagger: &Signature{Name: "Lucas Michot", Email: "lucas@semalead.com", When: time.Unix(1484491741, 0).In(time.FixedZone("", 3600))},
|
||||
Message: "",
|
||||
Signature: nil,
|
||||
},
|
||||
},
|
||||
@@ -43,13 +42,13 @@ o
|
||||
|
||||
ono`,
|
||||
expected: Tag{
|
||||
Name: "",
|
||||
ID: Sha1ObjectFormat.EmptyObjectID(),
|
||||
Object: MustIDFromString("7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc"),
|
||||
Type: "commit",
|
||||
Tagger: &Signature{Name: "Lucas Michot", Email: "lucas@semalead.com", When: time.Unix(1484553735, 0).In(time.FixedZone("", 3600))},
|
||||
Message: "test message\no\n\nono",
|
||||
Signature: nil,
|
||||
Name: "",
|
||||
ID: Sha1ObjectFormat.EmptyObjectID(),
|
||||
Object: MustIDFromString("7cdf42c0b1cc763ab7e4c33c47a24e27c66bfccc"),
|
||||
Type: "commit",
|
||||
Tagger: &Signature{Name: "Lucas Michot", Email: "lucas@semalead.com", When: time.Unix(1484553735, 0).In(time.FixedZone("", 3600))},
|
||||
CommitMessage: CommitMessage{MessageRaw: "test message\no\n\nono"},
|
||||
Signature: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -64,12 +63,12 @@ dummy signature
|
||||
-----END SSH SIGNATURE-----
|
||||
`,
|
||||
expected: Tag{
|
||||
Name: "",
|
||||
ID: Sha1ObjectFormat.EmptyObjectID(),
|
||||
Object: MustIDFromString("7cdf42c0b1cc763ab7e4c33c47a24e27c66bfaaa"),
|
||||
Type: "commit",
|
||||
Tagger: &Signature{Name: "dummy user", Email: "dummy-email@example.com", When: time.Unix(1484491741, 0).In(time.FixedZone("", 3600))},
|
||||
Message: "dummy message",
|
||||
Name: "",
|
||||
ID: Sha1ObjectFormat.EmptyObjectID(),
|
||||
Object: MustIDFromString("7cdf42c0b1cc763ab7e4c33c47a24e27c66bfaaa"),
|
||||
Type: "commit",
|
||||
Tagger: &Signature{Name: "dummy user", Email: "dummy-email@example.com", When: time.Unix(1484491741, 0).In(time.FixedZone("", 3600))},
|
||||
CommitMessage: CommitMessage{MessageRaw: "dummy message"},
|
||||
Signature: &CommitSignature{
|
||||
Signature: `-----BEGIN SSH SIGNATURE-----
|
||||
dummy signature
|
||||
@@ -93,5 +92,5 @@ dummy message`,
|
||||
|
||||
tag, err := parseTagData(Sha1ObjectFormat, []byte("type commit\n\nfoo\n-----BEGIN SSH SIGNATURE-----\ncorrupted..."))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "foo\n-----BEGIN SSH SIGNATURE-----\ncorrupted...", tag.Message)
|
||||
assert.Equal(t, "foo\n-----BEGIN SSH SIGNATURE-----\ncorrupted...", tag.CommitMessage.MessageRaw)
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ func SyncRepoBranchesWithRepo(ctx context.Context, repo *repo_model.Repository,
|
||||
RepoID: repo.ID,
|
||||
Name: branch,
|
||||
CommitID: commit.ID.String(),
|
||||
CommitMessage: commit.Summary(),
|
||||
CommitMessage: commit.MessageTitle(),
|
||||
PusherID: doerID,
|
||||
CommitTime: timeutil.TimeStamp(commit.Committer.When.Unix()),
|
||||
})
|
||||
@@ -112,7 +112,7 @@ func SyncRepoBranchesWithRepo(ctx context.Context, repo *repo_model.Repository,
|
||||
RepoID: repo.ID,
|
||||
Name: branch,
|
||||
CommitID: commit.ID.String(),
|
||||
CommitMessage: commit.Summary(),
|
||||
CommitMessage: commit.MessageTitle(),
|
||||
PusherID: doerID,
|
||||
CommitTime: timeutil.TimeStamp(commit.Committer.When.Unix()),
|
||||
})
|
||||
|
||||
@@ -152,7 +152,7 @@ func (pc *PushCommits) AvatarLink(ctx context.Context, email string) string {
|
||||
func CommitToPushCommit(commit *git.Commit) *PushCommit {
|
||||
return &PushCommit{
|
||||
Sha1: commit.ID.String(),
|
||||
Message: commit.Message(),
|
||||
Message: commit.MessageUTF8(),
|
||||
AuthorEmail: commit.Author.Email,
|
||||
AuthorName: commit.Author.Name,
|
||||
CommitterEmail: commit.Committer.Email,
|
||||
|
||||
@@ -145,7 +145,7 @@ func TestCommitToPushCommit(t *testing.T) {
|
||||
ID: sha1,
|
||||
Author: sig,
|
||||
Committer: sig,
|
||||
CommitMessage: "Commit Message",
|
||||
CommitMessage: git.CommitMessage{MessageRaw: "Commit Message"},
|
||||
})
|
||||
assert.Equal(t, hexString, pushCommit.Sha1)
|
||||
assert.Equal(t, "Commit Message", pushCommit.Message)
|
||||
@@ -176,13 +176,13 @@ func TestListToPushCommits(t *testing.T) {
|
||||
ID: hash1,
|
||||
Author: sig,
|
||||
Committer: sig,
|
||||
CommitMessage: "Message1",
|
||||
CommitMessage: git.CommitMessage{MessageRaw: "Message1"},
|
||||
},
|
||||
{
|
||||
ID: hash2,
|
||||
Author: sig,
|
||||
Committer: sig,
|
||||
CommitMessage: "Message2",
|
||||
CommitMessage: git.CommitMessage{MessageRaw: "Message2"},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -132,10 +132,9 @@ func newFuncMapWebPage() template.FuncMap {
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// misc (TODO: move them to MiscUtils to avoid bloating the main func map)
|
||||
"ActionContent2Commits": ActionContent2Commits,
|
||||
"IsMultilineCommitMessage": isMultilineCommitMessage,
|
||||
"CommentMustAsDiff": gitdiff.CommentMustAsDiff,
|
||||
"MirrorRemoteAddress": mirrorRemoteAddress,
|
||||
"ActionContent2Commits": ActionContent2Commits,
|
||||
"CommentMustAsDiff": gitdiff.CommentMustAsDiff,
|
||||
"MirrorRemoteAddress": mirrorRemoteAddress,
|
||||
|
||||
"FilenameIsImage": filenameIsImage,
|
||||
"TabSizeClass": tabSizeClass,
|
||||
|
||||
@@ -52,11 +52,6 @@ func sortArrow(normSort, revSort, urlSort string, isDefault bool) template.HTML
|
||||
return ""
|
||||
}
|
||||
|
||||
// isMultilineCommitMessage checks to see if a commit message contains multiple lines.
|
||||
func isMultilineCommitMessage(msg string) bool {
|
||||
return strings.Count(strings.TrimSpace(msg), "\n") >= 1
|
||||
}
|
||||
|
||||
// Actioner describes an action
|
||||
type Actioner interface {
|
||||
GetOpType() activities_model.ActionType
|
||||
|
||||
@@ -79,20 +79,14 @@ func (ut *RenderUtils) RenderCommitMessageLinkSubject(msg, urlDefault string, re
|
||||
|
||||
// RenderCommitBody extracts the body of a commit message without its title.
|
||||
func (ut *RenderUtils) RenderCommitBody(msg string, repo *repo.Repository) template.HTML {
|
||||
msgLine := strings.TrimSpace(msg)
|
||||
lineEnd := strings.IndexByte(msgLine, '\n')
|
||||
if lineEnd > 0 {
|
||||
msgLine = msgLine[lineEnd+1:]
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
msgLine = strings.TrimLeftFunc(msgLine, unicode.IsSpace)
|
||||
if len(msgLine) == 0 {
|
||||
_, body, _ := strings.Cut(strings.TrimSpace(msg), "\n")
|
||||
body = strings.TrimFunc(body, unicode.IsSpace)
|
||||
if body == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
rctx := renderhelper.NewRenderContextRepoComment(ut.ctx, repo)
|
||||
htmlContent := template.HTML(template.HTMLEscapeString(msgLine))
|
||||
htmlContent := template.HTML(template.HTMLEscapeString(body))
|
||||
renderedMessage, err := markup.PostProcessCommitMessage(rctx, htmlContent)
|
||||
if err != nil {
|
||||
log.Error("PostProcessCommitMessage: %v", err)
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -256,7 +256,7 @@ func skipWorkflows(ctx context.Context, input *notifyInput, commit *git.Commit)
|
||||
log.Debug("repo %s: skipped run for pr %v because of %s string", input.Repo.RelativePath(), input.PullRequest.Issue.ID, s)
|
||||
return true
|
||||
}
|
||||
if strings.Contains(commit.CommitMessage, s) {
|
||||
if strings.Contains(commit.MessageRaw, s) {
|
||||
log.Debug("repo %s with commit %s: skipped run because of %s string", input.Repo.RelativePath(), commit.ID, s)
|
||||
return true
|
||||
}
|
||||
@@ -320,7 +320,7 @@ func handleWorkflows(
|
||||
|
||||
for _, dwf := range detectedWorkflows {
|
||||
run := &actions_model.ActionRun{
|
||||
Title: strings.SplitN(commit.CommitMessage, "\n", 2)[0],
|
||||
Title: commit.MessageTitle(),
|
||||
RepoID: input.Repo.ID,
|
||||
Repo: input.Repo,
|
||||
OwnerID: input.Repo.OwnerID,
|
||||
@@ -483,7 +483,7 @@ func handleSchedules(
|
||||
}
|
||||
|
||||
run := &actions_model.ActionSchedule{
|
||||
Title: strings.SplitN(commit.CommitMessage, "\n", 2)[0],
|
||||
Title: commit.MessageTitle(),
|
||||
RepoID: input.Repo.ID,
|
||||
Repo: input.Repo,
|
||||
OwnerID: input.Repo.OwnerID,
|
||||
|
||||
@@ -5,7 +5,6 @@ package actions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
@@ -98,7 +97,7 @@ func DispatchActionWorkflow(ctx reqctx.RequestContext, doer *user_model.User, re
|
||||
var entry *git.TreeEntry
|
||||
|
||||
run := &actions_model.ActionRun{
|
||||
Title: strings.SplitN(runTargetCommit.CommitMessage, "\n", 2)[0],
|
||||
Title: runTargetCommit.MessageTitle(),
|
||||
RepoID: repo.ID,
|
||||
Repo: repo,
|
||||
OwnerID: repo.OwnerID,
|
||||
|
||||
@@ -150,17 +150,13 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get commit %s in repository: %s Error: %w", opts.NewCommitIDs[i], repo.FullName(), err)
|
||||
}
|
||||
}
|
||||
|
||||
// create a new pull request
|
||||
if title == "" {
|
||||
title = strings.Split(commit.CommitMessage, "\n")[0]
|
||||
}
|
||||
if description == "" {
|
||||
_, description, _ = strings.Cut(commit.CommitMessage, "\n\n")
|
||||
}
|
||||
if description == "" {
|
||||
description = title
|
||||
// create a new pull request
|
||||
if title == "" {
|
||||
title = commit.MessageTitle()
|
||||
}
|
||||
if description == "" {
|
||||
description = commit.MessageBody()
|
||||
}
|
||||
}
|
||||
|
||||
prIssue := &issues_model.Issue{
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"net/url"
|
||||
"path"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
@@ -215,7 +214,7 @@ func ToTag(repo *repo_model.Repository, t *git.Tag) *api.Tag {
|
||||
|
||||
return &api.Tag{
|
||||
Name: t.Name,
|
||||
Message: strings.TrimSpace(t.Message),
|
||||
Message: t.MessageUTF8(),
|
||||
ID: t.ID.String(),
|
||||
Commit: ToCommitMeta(repo, t),
|
||||
ZipballURL: zipballURL,
|
||||
@@ -769,7 +768,7 @@ func ToAnnotatedTag(ctx context.Context, repo *repo_model.Repository, t *git.Tag
|
||||
Tag: t.Name,
|
||||
SHA: t.ID.String(),
|
||||
Object: ToAnnotatedTagObject(repo, c),
|
||||
Message: t.Message,
|
||||
Message: t.MessageUTF8(),
|
||||
URL: repo.APIURL() + "/git/tags/" + t.ID.String(),
|
||||
Tagger: ToCommitUser(t.Tagger),
|
||||
Verification: ToVerification(ctx, c),
|
||||
|
||||
@@ -56,7 +56,7 @@ func ToPayloadCommit(ctx context.Context, repo *repo_model.Repository, c *git.Co
|
||||
|
||||
return &api.PayloadCommit{
|
||||
ID: c.ID.String(),
|
||||
Message: c.Message(),
|
||||
Message: c.MessageUTF8(),
|
||||
URL: repo.HTMLURL() + "/commit/" + c.ID.String(),
|
||||
Author: &api.PayloadUser{
|
||||
Name: c.Author.Name,
|
||||
@@ -171,7 +171,7 @@ func ToCommit(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Rep
|
||||
},
|
||||
Date: commit.Committer.When.Format(time.RFC3339),
|
||||
},
|
||||
Message: commit.Message(),
|
||||
Message: commit.MessageUTF8(),
|
||||
Tree: &api.CommitMeta{
|
||||
URL: repo.APIURL() + "/git/trees/" + url.PathEscape(commit.ID.String()),
|
||||
SHA: commit.ID.String(),
|
||||
|
||||
@@ -21,12 +21,12 @@ func TestToCommitMeta(t *testing.T) {
|
||||
sha1 := git.Sha1ObjectFormat
|
||||
signature := &git.Signature{Name: "Test Signature", Email: "test@email.com", When: time.Unix(0, 0)}
|
||||
tag := &git.Tag{
|
||||
Name: "Test Tag",
|
||||
ID: sha1.EmptyObjectID(),
|
||||
Object: sha1.EmptyObjectID(),
|
||||
Type: "Test Type",
|
||||
Tagger: signature,
|
||||
Message: "Test Message",
|
||||
Name: "Test Tag",
|
||||
ID: sha1.EmptyObjectID(),
|
||||
Object: sha1.EmptyObjectID(),
|
||||
Type: "Test Type",
|
||||
Tagger: signature,
|
||||
CommitMessage: git.CommitMessage{MessageRaw: "Test Message"},
|
||||
}
|
||||
|
||||
commitMeta := ToCommitMeta(headRepo, tag)
|
||||
|
||||
@@ -28,7 +28,7 @@ func ToWikiCommit(commit *git.Commit) *api.WikiCommit {
|
||||
},
|
||||
Date: commit.Committer.When.UTC().Format(time.RFC3339),
|
||||
},
|
||||
Message: commit.CommitMessage,
|
||||
Message: commit.MessageUTF8(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -847,7 +847,7 @@ func GetSquashMergeCommitMessages(ctx context.Context, pr *issues_model.PullRequ
|
||||
maxMsgSize := setting.Repository.PullRequest.DefaultMergeMessageSize
|
||||
for i := len(commits) - 1; i >= 0; i-- {
|
||||
commit := commits[i]
|
||||
msg := strings.TrimSpace(commit.CommitMessage)
|
||||
msg := strings.TrimSpace(commit.MessageUTF8())
|
||||
if msg == "" {
|
||||
continue
|
||||
}
|
||||
@@ -1074,7 +1074,7 @@ func GetPullCommits(ctx context.Context, baseGitRepo *git.Repository, doer *user
|
||||
}
|
||||
|
||||
commits = append(commits, CommitInfo{
|
||||
Summary: commit.Summary(),
|
||||
Summary: commit.MessageTitle(),
|
||||
CommitterOrAuthorName: committerOrAuthorName,
|
||||
ID: commit.ID.String(),
|
||||
ShortSha: base.ShortSha(commit.ID.String()),
|
||||
|
||||
@@ -359,7 +359,7 @@ func SyncBranchesToDB(ctx context.Context, repoID, pusherID int64, branchNames,
|
||||
RepoID: repoID,
|
||||
Name: branchName,
|
||||
CommitID: commit.ID.String(),
|
||||
CommitMessage: commit.Summary(),
|
||||
CommitMessage: commit.MessageTitle(),
|
||||
PusherID: pusherID,
|
||||
CommitTime: timeutil.TimeStamp(commit.Committer.When.Unix()),
|
||||
})
|
||||
|
||||
@@ -179,7 +179,7 @@ func getFileContentsByEntryInternal(ctx context.Context, repo *repo_model.Reposi
|
||||
}
|
||||
}
|
||||
if opts.IncludeCommitMessage {
|
||||
contentsResponse.LastCommitMessage = new(lastCommit.Message())
|
||||
contentsResponse.LastCommitMessage = new(lastCommit.MessageUTF8())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ func GetFileCommitResponse(repo *repo_model.Repository, commit *git.Commit) (*ap
|
||||
},
|
||||
Date: commit.Committer.When.UTC().Format(time.RFC3339),
|
||||
},
|
||||
Message: commit.Message(),
|
||||
Message: commit.MessageUTF8(),
|
||||
Tree: &api.CommitMeta{
|
||||
URL: commitTreeURL.String(),
|
||||
SHA: commit.Tree.ID.String(),
|
||||
|
||||
@@ -402,7 +402,7 @@ func pushUpdateAddTags(ctx context.Context, repo *repo_model.Repository, gitRepo
|
||||
}
|
||||
|
||||
rel, has := relMap[lowerTag]
|
||||
title, note := git.SplitCommitTitleBody(tag.Message, 255)
|
||||
title, note := git.SplitCommitTitleBody(tag.MessageUTF8(), 255)
|
||||
if !has {
|
||||
rel = &repo_model.Release{
|
||||
RepoID: repo.ID,
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
<meta property="og:title" content="{{.Title}}">
|
||||
<meta property="og:url" content="{{ctx.AppFullLink $.Link}}">
|
||||
{{if and .PageIsDiff .Commit}}
|
||||
{{- $commitMessageParts := StringUtils.Cut .Commit.Message "\n" -}}
|
||||
{{- $commitMessageBody := index $commitMessageParts 1 -}}
|
||||
{{- $commitMessageBody := .Commit.MessageBody -}}
|
||||
{{- if $commitMessageBody -}}
|
||||
<meta property="og:description" content="{{StringUtils.EllipsisString $commitMessageBody 300}}">
|
||||
{{- end -}}
|
||||
|
||||
@@ -65,11 +65,12 @@
|
||||
{{end -}}
|
||||
{{if eq .ActionName "push"}}
|
||||
<ul>
|
||||
{{range .Comment.Commits}}
|
||||
{{$repoURL := $.Comment.Issue.PullRequest.BaseRepo.HTMLURL}}
|
||||
{{range $commit := $.Comment.Commits}}
|
||||
<li>
|
||||
<a href="{{$.Comment.Issue.PullRequest.BaseRepo.HTMLURL}}/commit/{{.ID}}">
|
||||
{{ShortSha .ID.String}}
|
||||
</a> - {{.Summary}}
|
||||
<a href="{{$repoURL}}/commit/{{$commit.ID}}">
|
||||
{{ShortSha $commit.ID.String}}
|
||||
</a> - {{$commit.MessageTitle}}
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<div class="ui container fluid padded">
|
||||
<div class="ui top attached header clearing segment tw-relative commit-header">
|
||||
<div class="tw-flex tw-mb-4 tw-gap-1">
|
||||
<h3 class="tw-mb-0 tw-flex-1"><span class="commit-summary" title="{{.Commit.Summary}}">{{ctx.RenderUtils.RenderCommitMessage .Commit.Message $.Repository}}</span>{{template "repo/commit_statuses" dict "Status" .CommitStatus "Statuses" .CommitStatuses "AdditionalClasses" "tw-inline"}}</h3>
|
||||
<h3 class="tw-mb-0 tw-flex-1"><span class="commit-summary" title="{{.Commit.MessageTitle}}">{{ctx.RenderUtils.RenderCommitMessage .Commit.MessageUTF8 $.Repository}}</span>{{template "repo/commit_statuses" dict "Status" .CommitStatus "Statuses" .CommitStatuses "AdditionalClasses" "tw-inline"}}</h3>
|
||||
{{if not $.PageIsWiki}}
|
||||
<div class="commit-header-buttons">
|
||||
<a class="ui primary tiny button" href="{{.SourcePath}}">
|
||||
@@ -119,8 +119,8 @@
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{if IsMultilineCommitMessage .Commit.Message}}
|
||||
<pre class="commit-body">{{ctx.RenderUtils.RenderCommitBody .Commit.Message $.Repository}}</pre>
|
||||
{{if .Commit.MessageBody}}
|
||||
<pre class="commit-body">{{ctx.RenderUtils.RenderCommitBody .Commit.MessageUTF8 $.Repository}}</pre>
|
||||
{{end}}
|
||||
{{template "repo/commit_load_branches_and_tags" .}}
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
</thead>
|
||||
<tbody class="commit-list">
|
||||
{{$commitRepoLink := $.RepoLink}}{{if $.CommitRepoLink}}{{$commitRepoLink = $.CommitRepoLink}}{{end}}
|
||||
{{range .Commits}}
|
||||
{{range $commit := .Commits}}
|
||||
<tr>
|
||||
<td class="author">
|
||||
<span class="author-wrapper">
|
||||
@@ -38,18 +38,22 @@
|
||||
<td class="message">
|
||||
<span class="message-wrapper">
|
||||
{{if $.PageIsWiki}}
|
||||
<span class="commit-summary {{if gt .ParentCount 1}} grey text{{end}}" title="{{.Summary}}">{{.Summary | ctx.RenderUtils.RenderEmoji}}</span>
|
||||
<span class="commit-summary {{if gt $commit.ParentCount 1}} grey text{{end}}" title="{{$commit.MessageTitle}}">
|
||||
{{$commit.MessageTitle | ctx.RenderUtils.RenderEmoji}}
|
||||
</span>
|
||||
{{else}}
|
||||
{{$commitLink:= printf "%s/commit/%s" $commitRepoLink (PathEscape .ID.String)}}
|
||||
<span class="commit-summary {{if gt .ParentCount 1}} grey text{{end}}" title="{{.Summary}}">{{ctx.RenderUtils.RenderCommitMessageLinkSubject .Message $commitLink $.Repository}}</span>
|
||||
{{$commitLink:= printf "%s/commit/%s" $commitRepoLink (PathEscape $commit.ID.String)}}
|
||||
<span class="commit-summary {{if gt $commit.ParentCount 1}} grey text{{end}}" title="{{$commit.MessageTitle}}">
|
||||
{{ctx.RenderUtils.RenderCommitMessageLinkSubject $commit.MessageUTF8 $commitLink $.Repository}}
|
||||
</span>
|
||||
{{end}}
|
||||
</span>
|
||||
{{if IsMultilineCommitMessage .Message}}
|
||||
{{if $commit.MessageBody}}
|
||||
<button class="ui button ellipsis-button" aria-expanded="false" data-global-click="onRepoEllipsisButtonClick">...</button>
|
||||
{{end}}
|
||||
{{template "repo/commit_statuses" dict "Status" .Status "Statuses" .Statuses}}
|
||||
{{if IsMultilineCommitMessage .Message}}
|
||||
<pre class="commit-body tw-hidden">{{ctx.RenderUtils.RenderCommitBody .Message $.Repository}}</pre>
|
||||
{{if $commit.MessageBody}}
|
||||
<pre class="commit-body tw-hidden">{{ctx.RenderUtils.RenderCommitBody $commit.MessageUTF8 $.Repository}}</pre>
|
||||
{{end}}
|
||||
{{if $.CommitsTagsMap}}
|
||||
{{range (index $.CommitsTagsMap .ID.String)}}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{{$index := 0}}
|
||||
<div class="timeline-item commits-list">
|
||||
{{range .comment.Commits}}
|
||||
{{range $commit := .comment.Commits}}
|
||||
{{$tag := printf "%s-%d" $.comment.HashTag $index}}
|
||||
{{$index = Eval $index "+" 1}}
|
||||
<div class="flex-text-block" id="{{$tag}}">{{/*singular-commit*/}}
|
||||
@@ -14,11 +14,11 @@
|
||||
{{$commitBaseLink := printf "%s/commit" $.comment.Issue.PullRequest.BaseRepo.Link}}
|
||||
{{$commitLink:= printf "%s/%s" $commitBaseLink (PathEscape .ID.String)}}
|
||||
|
||||
<span class="tw-flex-1 tw-font-mono gt-ellipsis" title="{{.Summary}}">
|
||||
{{- ctx.RenderUtils.RenderCommitMessageLinkSubject .Message $commitLink $.comment.Issue.PullRequest.BaseRepo -}}
|
||||
<span class="tw-flex-1 tw-font-mono gt-ellipsis" title="{{$commit.MessageTitle}}">
|
||||
{{- ctx.RenderUtils.RenderCommitMessageLinkSubject $commit.MessageUTF8 $commitLink $.comment.Issue.PullRequest.BaseRepo -}}
|
||||
</span>
|
||||
|
||||
{{if IsMultilineCommitMessage .Message}}
|
||||
{{if $commit.MessageBody}}
|
||||
<button class="ui button ellipsis-button show-panel toggle" data-panel="[data-singular-commit-body-for='{{$tag}}']">...</button>
|
||||
{{end}}
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
{{template "repo/commit_sign_badge" dict "Commit" . "CommitBaseLink" $commitBaseLink "CommitSignVerification" .Verification}}
|
||||
</span>
|
||||
</div>
|
||||
{{if IsMultilineCommitMessage .Message}}
|
||||
{{if $commit.MessageBody}}
|
||||
<pre class="commit-body tw-ml-[33px] tw-hidden" data-singular-commit-body-for="{{$tag}}">
|
||||
{{- ctx.RenderUtils.RenderCommitBody .Message $.comment.Issue.PullRequest.BaseRepo -}}
|
||||
{{- ctx.RenderUtils.RenderCommitBody $commit.MessageUTF8 $.comment.Issue.PullRequest.BaseRepo -}}
|
||||
</pre>
|
||||
{{end}}
|
||||
{{end}}
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
{{template "repo/commit_statuses" dict "Status" .LatestCommitStatus "Statuses" .LatestCommitStatuses}}
|
||||
|
||||
{{$commitLink:= printf "%s/commit/%s" .RepoLink (PathEscape .LatestCommit.ID.String)}}
|
||||
<span class="grey commit-summary" title="{{.LatestCommit.Summary}}"><span class="message-wrapper">{{ctx.RenderUtils.RenderCommitMessageLinkSubject .LatestCommit.Message $commitLink $.Repository}}</span>
|
||||
{{if IsMultilineCommitMessage .LatestCommit.Message}}
|
||||
<span class="grey commit-summary" title="{{.LatestCommit.MessageTitle}}">
|
||||
<span class="message-wrapper">{{ctx.RenderUtils.RenderCommitMessageLinkSubject .LatestCommit.MessageUTF8 $commitLink $.Repository}}</span>
|
||||
{{if .LatestCommit.MessageBody}}
|
||||
<button class="ui button ellipsis-button" aria-expanded="false" data-global-click="onRepoEllipsisButtonClick">...</button>
|
||||
<pre class="commit-body tw-hidden">{{ctx.RenderUtils.RenderCommitBody .LatestCommit.Message $.Repository}}</pre>
|
||||
<pre class="commit-body tw-hidden">{{ctx.RenderUtils.RenderCommitBody .LatestCommit.MessageUTF8 $.Repository}}</pre>
|
||||
{{end}}
|
||||
</span>
|
||||
{{end}}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</h4>
|
||||
<table id="lfs-files-find-table" class="ui attached segment single line table">
|
||||
<tbody>
|
||||
{{range .Results}}
|
||||
{{range $lfsItem := .Results}}
|
||||
<tr>
|
||||
<td>
|
||||
{{svg "octicon-file"}}
|
||||
@@ -14,8 +14,8 @@
|
||||
</td>
|
||||
<td class="message">
|
||||
<span class="truncate">
|
||||
<a href="{{$.RepoLink}}/commit/{{.SHA}}" title="{{.Summary}}">
|
||||
{{.Summary | ctx.RenderUtils.RenderEmoji}}
|
||||
<a href="{{$.RepoLink}}/commit/{{.SHA}}" title="{{$lfsItem.Summary}}">
|
||||
{{$lfsItem.Summary | ctx.RenderUtils.RenderEmoji}}
|
||||
</a>
|
||||
</span>
|
||||
</td>
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
<div class="repo-file-cell message commit-summary {{if not $commit}}notready{{end}}">
|
||||
{{if $commit}}
|
||||
{{$commitLink := printf "%s/commit/%s" $.RepoLink (PathEscape $commit.ID.String)}}
|
||||
{{ctx.RenderUtils.RenderCommitMessageLinkSubject $commit.Message $commitLink $.Repository}}
|
||||
{{ctx.RenderUtils.RenderCommitMessageLinkSubject $commit.MessageUTF8 $commitLink $.Repository}}
|
||||
{{else}}
|
||||
… {{/* will be loaded again by LastCommitLoaderURL */}}
|
||||
{{end}}
|
||||
|
||||
@@ -88,13 +88,13 @@
|
||||
{{$repoLink := (.GetRepoLink ctx)}}
|
||||
{{$repo := .Repo}}
|
||||
<div class="tw-flex tw-flex-col tw-gap-1">
|
||||
{{range $push.Commits}}
|
||||
{{range $pushCommit := $push.Commits}}
|
||||
{{$commitLink := printf "%s/commit/%s" $repoLink .Sha1}}
|
||||
<div class="flex-text-block">
|
||||
<img loading="lazy" alt class="ui avatar" src="{{$push.AvatarLink ctx .AuthorEmail}}" title="{{.AuthorName}}" width="16" height="16">
|
||||
<a class="ui sha label" href="{{$commitLink}}">{{ShortSha .Sha1}}</a>
|
||||
<span class="tw-inline-block tw-truncate">
|
||||
{{ctx.RenderUtils.RenderCommitMessage .Message $repo}}
|
||||
{{ctx.RenderUtils.RenderCommitMessage $pushCommit.Message $repo}}
|
||||
</span>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAPIRepoTags(t *testing.T) {
|
||||
@@ -35,24 +36,22 @@ func TestAPIRepoTags(t *testing.T) {
|
||||
|
||||
assert.Len(t, tags, 1)
|
||||
assert.Equal(t, "v1.1", tags[0].Name)
|
||||
assert.Equal(t, "Initial commit", tags[0].Message)
|
||||
assert.Equal(t, "Initial commit\n", tags[0].Message)
|
||||
assert.Equal(t, "65f1bf27bc3bf70f64657658635e66094edbcb4d", tags[0].Commit.SHA)
|
||||
assert.Equal(t, setting.AppURL+"api/v1/repos/user2/repo1/git/commits/65f1bf27bc3bf70f64657658635e66094edbcb4d", tags[0].Commit.URL)
|
||||
assert.Equal(t, setting.AppURL+"user2/repo1/archive/v1.1.zip", tags[0].ZipballURL)
|
||||
assert.Equal(t, setting.AppURL+"user2/repo1/archive/v1.1.tar.gz", tags[0].TarballURL)
|
||||
|
||||
newTag := createNewTagUsingAPI(t, token, user.Name, repoName, "gitea/22", "", "nice!\nand some text")
|
||||
assert.Equal(t, "nice!\nand some text\n", newTag.Message) // git message standard: there will always be a newline at the end of the message
|
||||
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
tags = DecodeJSON(t, resp, []*api.Tag{})
|
||||
assert.Len(t, tags, 2)
|
||||
for _, tag := range tags {
|
||||
if tag.Name != "v1.1" {
|
||||
assert.Equal(t, newTag.Name, tag.Name)
|
||||
assert.Equal(t, newTag.Message, tag.Message)
|
||||
assert.Equal(t, "nice!\nand some text", tag.Message)
|
||||
assert.Equal(t, newTag.Commit.SHA, tag.Commit.SHA)
|
||||
}
|
||||
}
|
||||
require.Len(t, tags, 2)
|
||||
respTag := tags[0]
|
||||
assert.Equal(t, newTag.Name, respTag.Name)
|
||||
assert.Equal(t, newTag.Message, respTag.Message)
|
||||
assert.Equal(t, newTag.Commit.SHA, respTag.Commit.SHA)
|
||||
|
||||
// get created tag
|
||||
req = NewRequestf(t, "GET", "/api/v1/repos/%s/%s/tags/%s", user.Name, repoName, newTag.Name).
|
||||
|
||||
Reference in New Issue
Block a user