aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/git
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/git')
-rw-r--r--pkg/git/git.go55
-rw-r--r--pkg/git/git_test.go65
2 files changed, 111 insertions, 9 deletions
diff --git a/pkg/git/git.go b/pkg/git/git.go
index 59715ed07..899930bff 100644
--- a/pkg/git/git.go
+++ b/pkg/git/git.go
@@ -131,9 +131,11 @@ func initRepo(dir string) error {
}
type Commit struct {
- Hash string
- Title string
- Date time.Time
+ Hash string
+ Title string
+ Author string
+ CC []string
+ Date time.Time
}
// HeadCommit returns info about the HEAD commit of the current branch of git repository in dir.
@@ -142,22 +144,49 @@ func HeadCommit(dir string) (*Commit, error) {
}
func GetCommit(dir, commit string) (*Commit, error) {
- output, err := runSandboxed(dir, "git", "log", "--pretty=format:%H%n%s%n%ad", "-n", "1", commit)
+ output, err := runSandboxed(dir, "git", "log", "--format=%H%n%s%n%ae%n%ad%n%b", "-n", "1", commit)
if err != nil {
return nil, err
}
+ return parseCommit(output)
+}
+
+func parseCommit(output []byte) (*Commit, error) {
lines := bytes.Split(output, []byte{'\n'})
- if len(lines) != 3 || len(lines[0]) != 40 {
+ if len(lines) < 4 || len(lines[0]) != 40 {
return nil, fmt.Errorf("unexpected git log output: %q", output)
}
- date, err := time.Parse(DateFormat, string(lines[2]))
+ date, err := time.Parse(DateFormat, string(lines[3]))
if err != nil {
return nil, fmt.Errorf("failed to parse date in git log output: %v\n%q", err, output)
}
+ cc := make(map[string]bool)
+ cc[strings.ToLower(string(lines[2]))] = true
+ for _, line := range lines[4:] {
+ for _, re := range ccRes {
+ matches := re.FindSubmatchIndex(line)
+ if matches == nil {
+ continue
+ }
+ addr, err := mail.ParseAddress(string(line[matches[2]:matches[3]]))
+ if err != nil {
+ break
+ }
+ cc[strings.ToLower(addr.Address)] = true
+ break
+ }
+ }
+ sortedCC := make([]string, 0, len(cc))
+ for addr := range cc {
+ sortedCC = append(sortedCC, addr)
+ }
+ sort.Strings(sortedCC)
com := &Commit{
- Hash: string(lines[0]),
- Title: string(lines[1]),
- Date: date,
+ Hash: string(lines[0]),
+ Title: string(lines[1]),
+ Author: string(lines[2]),
+ CC: sortedCC,
+ Date: date,
}
return com, nil
}
@@ -456,4 +485,12 @@ var (
gitBranchRe = regexp.MustCompile("^[a-zA-Z0-9-_/.]{2,200}$")
gitHashRe = regexp.MustCompile("^[a-f0-9]+$")
releaseTagRe = regexp.MustCompile(`^v([0-9]+).([0-9]+)(?:\.([0-9]+))?$`)
+ ccRes = []*regexp.Regexp{
+ regexp.MustCompile(`^Reviewed\-.*: (.*)$`),
+ regexp.MustCompile(`^[A-Za-z-]+\-and\-[Rr]eviewed\-.*: (.*)$`),
+ regexp.MustCompile(`^Acked\-.*: (.*)$`),
+ regexp.MustCompile(`^[A-Za-z-]+\-and\-[Aa]cked\-.*: (.*)$`),
+ regexp.MustCompile(`^Tested\-.*: (.*)$`),
+ regexp.MustCompile(`^[A-Za-z-]+\-and\-[Tt]ested\-.*: (.*)$`),
+ }
)
diff --git a/pkg/git/git_test.go b/pkg/git/git_test.go
index 66159107f..86f033acf 100644
--- a/pkg/git/git_test.go
+++ b/pkg/git/git_test.go
@@ -7,8 +7,73 @@ import (
"reflect"
"strings"
"testing"
+ "time"
)
+func TestParseCommit(t *testing.T) {
+ tests := map[string]*Commit{
+ `2075b16e32c26e4031b9fd3cbe26c54676a8fcb5
+rbtree: include rcu.h
+foobar@foobar.de
+Fri May 11 16:02:14 2018 -0700
+Since commit c1adf20052d8 ("Introduce rb_replace_node_rcu()")
+rbtree_augmented.h uses RCU related data structures but does not include
+the header file. It works as long as it gets somehow included before
+that and fails otherwise.
+
+Link: http://lkml.kernel.org/r/20180504103159.19938-1-bigeasy@linutronix.de
+Signed-off-by: Foo Bad Baz <another@email.de>
+Reviewed-by: <yetanother@email.org>
+Cc: Unrelated Guy <somewhere@email.com>
+Acked-by: Subsystem reviewer <Subsystem@reviewer.com>
+Reported-and-tested-by: and@me.com
+Reported-and-Tested-by: Name-name <name@name.com>
+Tested-by: Must be correct <mustbe@correct.com>
+Signed-off-by: Linux Master <linux@linux-foundation.org>
+`: &Commit{
+ Hash: "2075b16e32c26e4031b9fd3cbe26c54676a8fcb5",
+ Title: "rbtree: include rcu.h",
+ Author: "foobar@foobar.de",
+ CC: []string{
+ "and@me.com",
+ "foobar@foobar.de",
+ "mustbe@correct.com",
+ "name@name.com",
+ "subsystem@reviewer.com",
+ "yetanother@email.org",
+ },
+ Date: time.Date(2018, 5, 11, 16, 02, 14, 0, time.FixedZone("", -7*60*60)),
+ },
+ }
+ for input, com := range tests {
+ res, err := parseCommit([]byte(input))
+ if err != nil && com != nil {
+ t.Fatalf("want %+v, got error: %v", com, err)
+ }
+ if err == nil && com == nil {
+ t.Fatalf("want error, got commit %+v", res)
+ }
+ if com == nil {
+ continue
+ }
+ if com.Hash != res.Hash {
+ t.Fatalf("want hash %q, got %q", com.Hash, res.Hash)
+ }
+ if com.Title != res.Title {
+ t.Fatalf("want title %q, got %q", com.Title, res.Title)
+ }
+ if com.Author != res.Author {
+ t.Fatalf("want author %q, got %q", com.Author, res.Author)
+ }
+ if !reflect.DeepEqual(com.CC, res.CC) {
+ t.Fatalf("want CC %q, got %q", com.CC, res.CC)
+ }
+ if !com.Date.Equal(res.Date) {
+ t.Fatalf("want date %v, got %v", com.Date, res.Date)
+ }
+ }
+}
+
func TestCanonicalizeCommit(t *testing.T) {
tests := map[string]string{
"foo bar": "foo bar",