Skip to content

Commit f5f1b5c

Browse files
committed
fix: use empty line as title-body separator
1 parent da69195 commit f5f1b5c

File tree

1 file changed

+32
-20
lines changed

1 file changed

+32
-20
lines changed

internal/conventionalcommits/conventional_commits.go

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const (
3232
endNestedCommit = "END_NESTED_COMMIT"
3333
breakingChangeKey = "BREAKING CHANGE"
3434
sourceLinkKey = "Source-Link"
35+
empty = ""
3536
)
3637

3738
var (
@@ -90,7 +91,7 @@ type parsedHeader struct {
9091
func (header *parsedHeader) extractLibraryID() string {
9192
matches := libraryIDRegex.FindStringSubmatch(header.Description)
9293
if len(matches) == 0 {
93-
return ""
94+
return empty
9495
}
9596
return matches[1]
9697
}
@@ -127,7 +128,7 @@ func (c *ConventionalCommit) MarshalJSON() ([]byte, error) {
127128
// conventional commit is logged and skipped.
128129
func ParseCommits(commit *gitrepo.Commit, libraryID string) ([]*ConventionalCommit, error) {
129130
message := commit.Message
130-
if strings.TrimSpace(message) == "" {
131+
if strings.TrimSpace(message) == empty {
131132
return nil, fmt.Errorf("empty commit message")
132133
}
133134
message = extractCommitMessageOverride(message)
@@ -167,7 +168,7 @@ func extractCommitParts(message string) []commitPart {
167168
var commitParts []commitPart
168169

169170
// The first part is the primary commit.
170-
if len(parts) > 0 && strings.TrimSpace(parts[0]) != "" {
171+
if len(parts) > 0 && strings.TrimSpace(parts[0]) != empty {
171172
commitParts = append(commitParts, commitPart{
172173
message: strings.TrimSpace(parts[0]),
173174
isNested: false,
@@ -198,7 +199,7 @@ func extractCommitParts(message string) []commitPart {
198199
// A simple commit message is commit that does not include override or nested commits.
199200
func parseSimpleCommit(commitPart commitPart, commit *gitrepo.Commit, libraryID string) ([]*ConventionalCommit, error) {
200201
trimmedMessage := strings.TrimSpace(commitPart.message)
201-
if trimmedMessage == "" {
202+
if trimmedMessage == empty {
202203
return nil, fmt.Errorf("empty commit message")
203204
}
204205

@@ -210,6 +211,10 @@ func parseSimpleCommit(commitPart commitPart, commit *gitrepo.Commit, libraryID
210211
var commits []*ConventionalCommit
211212
// Hold the subjects of each commit.
212213
var subjects [][]string
214+
// Hold the body of each commit.
215+
var body [][]string
216+
// Whether it has seen an empty line.
217+
seenSeparator := false
213218
// If the body lines have multiple headers, separate them into different conventional commit, all associated with
214219
// the same commit sha.
215220
for _, bodyLine := range bodyLines {
@@ -221,12 +226,26 @@ func parseSimpleCommit(commitPart commitPart, commit *gitrepo.Commit, libraryID
221226
continue
222227
}
223228

224-
// This might be a multi-line header, append the line to the subject of the last commit.
225-
subjects[len(subjects)-1] = append(subjects[len(subjects)-1], strings.TrimSpace(bodyLine))
229+
bodyLine = strings.TrimSpace(bodyLine)
230+
if bodyLine == empty {
231+
seenSeparator = true
232+
continue
233+
}
234+
235+
if seenSeparator {
236+
// Since we have seen a separator, the rest of the lines are body lines of the commit.
237+
body[len(body)-1] = append(body[len(body)-1], bodyLine)
238+
} else {
239+
// We haven't seen a separator, this line is the continuation of the title.
240+
subjects[len(subjects)-1] = append(subjects[len(subjects)-1], bodyLine)
241+
}
242+
226243
continue
227244
}
228245

229246
subjects = append(subjects, []string{})
247+
body = append(body, []string{})
248+
seenSeparator = false
230249
// If there is an association for the commit (i.e. the commit has '[LIBRARY_ID]' in the
231250
// description), then use that libraryID. Otherwise, use the libraryID passed as the default.
232251
headerLibraryID := header.extractLibraryID()
@@ -248,17 +267,10 @@ func parseSimpleCommit(commitPart commitPart, commit *gitrepo.Commit, libraryID
248267
})
249268
}
250269

251-
if len(commits) == 1 {
252-
// If only one conventional commit is found, i.e., only one header line is
253-
// in the commit message, assign the body field.
254-
commits[0].Body = strings.TrimSpace(strings.Join(bodyLines[1:], "\n"))
255-
} else {
256-
// Otherwise, concatenate all lines as the subject of the corresponding commit.
257-
// This is a workaround when GitHub inserts line breaks in the middle of a long line after squash and merge.
258-
for i, commit := range commits {
259-
sub := fmt.Sprintf("%s %s", commit.Subject, strings.Join(subjects[i], " "))
260-
commit.Subject = strings.TrimSpace(sub)
261-
}
270+
for i, commit := range commits {
271+
sub := fmt.Sprintf("%s %s", commit.Subject, strings.Join(subjects[i], " "))
272+
commit.Subject = strings.TrimSpace(sub)
273+
commit.Body = strings.Join(body[i], "\n")
262274
}
263275

264276
return commits, nil
@@ -294,11 +306,11 @@ func separateBodyAndFooters(lines []string) (bodyLines, footerLines []string) {
294306
footerLines = append(footerLines, line)
295307
continue
296308
}
297-
if strings.TrimSpace(line) == "" {
309+
if strings.TrimSpace(line) == empty {
298310
isSeparator := false
299311
// Look ahead at the next non-blank line.
300312
for j := i + 1; j < len(lines); j++ {
301-
if strings.TrimSpace(lines[j]) != "" {
313+
if strings.TrimSpace(lines[j]) != empty {
302314
if footerRegex.MatchString(lines[j]) {
303315
isSeparator = true
304316
}
@@ -326,7 +338,7 @@ func parseFooters(footerLines []string) (footers map[string]string, isBreaking b
326338
if len(footerMatches) == 0 {
327339
// Not a new footer. If we have a previous key and the line is not
328340
// empty, append it to the last value.
329-
if lastKey != "" && strings.TrimSpace(line) != "" {
341+
if lastKey != empty && strings.TrimSpace(line) != empty {
330342
footers[lastKey] += "\n" + line
331343
}
332344
continue

0 commit comments

Comments
 (0)