| // Copyright 2020 Google Inc. All Rights Reserved. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| package changelog | |
| import ( | |
| "errors" | |
| "regexp" | |
| "strings" | |
| "go.chromium.org/luci/common/proto/git" | |
| ) | |
| const ( | |
| bugLinePrefix string = "BUG=" | |
| releaseNoteLinePrefix string = "RELEASE_NOTE=" | |
| ) | |
| // Commit is a simplified struct of git.Commit | |
| // Useful for interfaces | |
| type Commit struct { | |
| SHA string | |
| AuthorName string | |
| CommitterName string | |
| Subject string | |
| Bugs []string | |
| ReleaseNote string | |
| CommitTime string | |
| } | |
| // All bug patterns need to be added here to recognize whether a bug entry | |
| // should be ignored or not | |
| var bugPatternToReplacement = map[*regexp.Regexp]string{ | |
| regexp.MustCompile("^b/"): "b/", | |
| regexp.MustCompile("^b:"): "b/", | |
| regexp.MustCompile("^chromium.*:"): "crbug/", | |
| regexp.MustCompile("^chrome.*:"): "crbug/", | |
| } | |
| func author(commit *git.Commit) string { | |
| if commit.Author != nil { | |
| return commit.Author.Name | |
| } | |
| return "None" | |
| } | |
| func committer(commit *git.Commit) string { | |
| if commit.Committer != nil { | |
| return commit.Committer.Name | |
| } | |
| return "None" | |
| } | |
| func subject(commit *git.Commit) string { | |
| return strings.Split(commit.Message, "\n")[0] | |
| } | |
| func bugs(commit *git.Commit) []string { | |
| output := []string{} | |
| msgSplit := strings.Split(commit.Message, "\n") | |
| bugLine := "" | |
| for _, line := range msgSplit { | |
| line = strings.TrimSpace(line) | |
| if strings.HasPrefix(line, bugLinePrefix) { | |
| bugLine = line | |
| break | |
| } | |
| } | |
| if len(bugLine) <= len(bugLinePrefix) { | |
| return output | |
| } | |
| bugList := strings.Split(bugLine[len(bugLinePrefix):], ",") | |
| for _, bug := range bugList { | |
| bug := strings.TrimSpace(bug) | |
| for prefix, replacement := range bugPatternToReplacement { | |
| if match := prefix.FindString(bug); match != "" { | |
| output = append(output, replacement+bug[len(match):]) | |
| } | |
| } | |
| } | |
| return output | |
| } | |
| func releaseNote(commit *git.Commit) string { | |
| msgSplit := strings.Split(commit.Message, "\n") | |
| for _, line := range msgSplit { | |
| line = strings.TrimSpace(line) | |
| if strings.HasPrefix(line, releaseNoteLinePrefix) { | |
| return line[len(releaseNoteLinePrefix):] | |
| } | |
| } | |
| return "" | |
| } | |
| func commitTime(commit *git.Commit) string { | |
| if commit.Committer != nil { | |
| return commit.Committer.Time.AsTime().Format("Mon, 2 Jan 2006") | |
| } | |
| return "None" | |
| } | |
| // ParseGitCommit converts a git.Commit object into a | |
| // Commit object with processed fields | |
| func parseGitCommit(commit *git.Commit) (*Commit, error) { | |
| if commit == nil { | |
| return nil, errors.New("parseCommit: Input should not be nil") | |
| } | |
| return &Commit{ | |
| SHA: commit.Id, | |
| AuthorName: author(commit), | |
| CommitterName: committer(commit), | |
| Subject: subject(commit), | |
| Bugs: bugs(commit), | |
| ReleaseNote: releaseNote(commit), | |
| CommitTime: commitTime(commit), | |
| }, nil | |
| } | |
| // ParseGitCommitLog converts a slice of git.Commit objects | |
| // into a slice of Commit objects with processed fields | |
| func ParseGitCommitLog(commits []*git.Commit) ([]*Commit, error) { | |
| if commits == nil { | |
| return nil, errors.New("parseCommitLog: Input should not be nil") | |
| } | |
| output := make([]*Commit, len(commits)) | |
| for i, commit := range commits { | |
| parsedCommit, err := parseGitCommit(commit) | |
| if err != nil { | |
| return nil, errors.New("parseCommitLog: Input slice contains nil pointer") | |
| } | |
| output[i] = parsedCommit | |
| } | |
| return output, nil | |
| } |