|
|
|
|
@ -13,6 +13,7 @@ import (
|
|
|
|
|
"regexp"
|
|
|
|
|
"strings"
|
|
|
|
|
"time"
|
|
|
|
|
"unicode/utf8"
|
|
|
|
|
|
|
|
|
|
"code.gitea.io/gitea/models/db"
|
|
|
|
|
git_model "code.gitea.io/gitea/models/git"
|
|
|
|
|
@ -838,51 +839,53 @@ func GetSquashMergeCommitMessages(ctx context.Context, pr *issues_model.PullRequ
|
|
|
|
|
stringBuilder := strings.Builder{}
|
|
|
|
|
|
|
|
|
|
if !setting.Repository.PullRequest.PopulateSquashCommentWithCommitMessages {
|
|
|
|
|
// use PR's title and description as squash commit message
|
|
|
|
|
message := strings.TrimSpace(pr.Issue.Content)
|
|
|
|
|
stringBuilder.WriteString(message)
|
|
|
|
|
if stringBuilder.Len() > 0 {
|
|
|
|
|
stringBuilder.WriteRune('\n')
|
|
|
|
|
if !commitMessageTrailersPattern.MatchString(message) {
|
|
|
|
|
// TODO: this trailer check doesn't work with the separator line added below for the co-authors
|
|
|
|
|
stringBuilder.WriteRune('\n')
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// commits list is in reverse chronological order
|
|
|
|
|
first := true
|
|
|
|
|
for i := len(commits) - 1; i >= 0; i-- {
|
|
|
|
|
commit := commits[i]
|
|
|
|
|
|
|
|
|
|
if setting.Repository.PullRequest.PopulateSquashCommentWithCommitMessages {
|
|
|
|
|
maxSize := setting.Repository.PullRequest.DefaultMergeMessageSize
|
|
|
|
|
if maxSize < 0 || stringBuilder.Len() < maxSize {
|
|
|
|
|
var toWrite []byte
|
|
|
|
|
if first {
|
|
|
|
|
first = false
|
|
|
|
|
toWrite = []byte(strings.TrimPrefix(commit.CommitMessage, pr.Issue.Title))
|
|
|
|
|
} else {
|
|
|
|
|
toWrite = []byte(commit.CommitMessage)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(toWrite) > maxSize-stringBuilder.Len() && maxSize > -1 {
|
|
|
|
|
toWrite = append(toWrite[:maxSize-stringBuilder.Len()], "..."...)
|
|
|
|
|
}
|
|
|
|
|
if _, err := stringBuilder.Write(toWrite); err != nil {
|
|
|
|
|
log.Error("Unable to write commit message Error: %v", err)
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// use PR's commit messages as squash commit message
|
|
|
|
|
// commits list is in reverse chronological order
|
|
|
|
|
maxMsgSize := setting.Repository.PullRequest.DefaultMergeMessageSize
|
|
|
|
|
for i := len(commits) - 1; i >= 0; i-- {
|
|
|
|
|
commit := commits[i]
|
|
|
|
|
msg := strings.TrimSpace(commit.CommitMessage)
|
|
|
|
|
if msg == "" {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if _, err := stringBuilder.WriteRune('\n'); err != nil {
|
|
|
|
|
log.Error("Unable to write commit message Error: %v", err)
|
|
|
|
|
return ""
|
|
|
|
|
// This format follows GitHub's squash commit message style,
|
|
|
|
|
// even if there are other "* " in the commit message body, they are written as-is.
|
|
|
|
|
// Maybe, ideally, we should indent those lines too.
|
|
|
|
|
_, _ = fmt.Fprintf(&stringBuilder, "* %s\n\n", msg)
|
|
|
|
|
if maxMsgSize > 0 && stringBuilder.Len() >= maxMsgSize {
|
|
|
|
|
tmp := stringBuilder.String()
|
|
|
|
|
wasValidUtf8 := utf8.ValidString(tmp)
|
|
|
|
|
tmp = tmp[:maxMsgSize] + "..."
|
|
|
|
|
if wasValidUtf8 {
|
|
|
|
|
// If the message was valid UTF-8 before truncation, ensure it remains valid after truncation
|
|
|
|
|
// For non-utf8 messages, we can't do much about it, end users should use utf-8 as much as possible
|
|
|
|
|
tmp = strings.ToValidUTF8(tmp, "")
|
|
|
|
|
}
|
|
|
|
|
stringBuilder.Reset()
|
|
|
|
|
stringBuilder.WriteString(tmp)
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// collect co-authors
|
|
|
|
|
for _, commit := range commits {
|
|
|
|
|
authorString := commit.Author.String()
|
|
|
|
|
if uniqueAuthors.Add(authorString) && authorString != posterSig {
|
|
|
|
|
// Compare use account as well to avoid adding the same author multiple times
|
|
|
|
|
// times when email addresses are private or multiple emails are used.
|
|
|
|
|
// when email addresses are private or multiple emails are used.
|
|
|
|
|
commitUser, _ := user_model.GetUserByEmail(ctx, commit.Author.Email)
|
|
|
|
|
if commitUser == nil || commitUser.ID != pr.Issue.Poster.ID {
|
|
|
|
|
authors = append(authors, authorString)
|
|
|
|
|
@ -890,12 +893,12 @@ func GetSquashMergeCommitMessages(ctx context.Context, pr *issues_model.PullRequ
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Consider collecting the remaining authors
|
|
|
|
|
// collect the remaining authors
|
|
|
|
|
if limit >= 0 && setting.Repository.PullRequest.DefaultMergeMessageAllAuthors {
|
|
|
|
|
skip := limit
|
|
|
|
|
limit = 30
|
|
|
|
|
for {
|
|
|
|
|
commits, err := gitRepo.CommitsBetweenLimit(headCommit, mergeBase, limit, skip)
|
|
|
|
|
commits, err = gitRepo.CommitsBetweenLimit(headCommit, mergeBase, limit, skip)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Error("Unable to get commits between: %s %s Error: %v", pr.HeadBranch, pr.MergeBase, err)
|
|
|
|
|
return ""
|
|
|
|
|
@ -916,19 +919,15 @@ func GetSquashMergeCommitMessages(ctx context.Context, pr *issues_model.PullRequ
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if stringBuilder.Len() > 0 && len(authors) > 0 {
|
|
|
|
|
// TODO: this separator line doesn't work with the trailer check (commitMessageTrailersPattern) above
|
|
|
|
|
stringBuilder.WriteString("---------\n\n")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, author := range authors {
|
|
|
|
|
if _, err := stringBuilder.WriteString("Co-authored-by: "); err != nil {
|
|
|
|
|
log.Error("Unable to write to string builder Error: %v", err)
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
if _, err := stringBuilder.WriteString(author); err != nil {
|
|
|
|
|
log.Error("Unable to write to string builder Error: %v", err)
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
if _, err := stringBuilder.WriteRune('\n'); err != nil {
|
|
|
|
|
log.Error("Unable to write to string builder Error: %v", err)
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
stringBuilder.WriteString("Co-authored-by: ")
|
|
|
|
|
stringBuilder.WriteString(author)
|
|
|
|
|
stringBuilder.WriteRune('\n')
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return stringBuilder.String()
|
|
|
|
|
|