Skip to content

Commit 354218d

Browse files
lollipopmanlhchavez
authored andcommitted
Add support for parsing git trailers (#614)
Adds a wrapper for git_message_trailers which returns a slice of trailer structs. (cherry picked from commit 5241c72)
1 parent 7b83382 commit 354218d

File tree

2 files changed

+84
-0
lines changed

2 files changed

+84
-0
lines changed

message.go

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package git
2+
3+
/*
4+
#include <git2.h>
5+
*/
6+
import "C"
7+
import (
8+
"runtime"
9+
"unsafe"
10+
)
11+
12+
// Trailer represents a single git message trailer.
13+
type Trailer struct {
14+
Key string
15+
Value string
16+
}
17+
18+
// MessageTrailers parses trailers out of a message, returning a slice of
19+
// Trailer structs. Trailers are key/value pairs in the last paragraph of a
20+
// message, not including any patches or conflicts that may be present.
21+
func MessageTrailers(message string) ([]Trailer, error) {
22+
var trailersC C.git_message_trailer_array
23+
24+
messageC := C.CString(message)
25+
defer C.free(unsafe.Pointer(messageC))
26+
27+
runtime.LockOSThread()
28+
defer runtime.UnlockOSThread()
29+
30+
ecode := C.git_message_trailers(&trailersC, messageC)
31+
if ecode < 0 {
32+
return nil, MakeGitError(ecode)
33+
}
34+
defer C.git_message_trailer_array_free(&trailersC)
35+
trailers := make([]Trailer, trailersC.count)
36+
var trailer *C.git_message_trailer
37+
for i, p := 0, uintptr(unsafe.Pointer(trailersC.trailers)); i < int(trailersC.count); i, p = i+1, p+unsafe.Sizeof(C.git_message_trailer{}) {
38+
trailer = (*C.git_message_trailer)(unsafe.Pointer(p))
39+
trailers[i] = Trailer{Key: C.GoString(trailer.key), Value: C.GoString(trailer.value)}
40+
}
41+
return trailers, nil
42+
}

message_test.go

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package git
2+
3+
import (
4+
"fmt"
5+
"reflect"
6+
"testing"
7+
)
8+
9+
func TestTrailers(t *testing.T) {
10+
t.Parallel()
11+
tests := []struct {
12+
input string
13+
expected []Trailer
14+
}{
15+
{
16+
"commit with zero trailers\n",
17+
[]Trailer{},
18+
},
19+
{
20+
"commit with one trailer\n\nCo-authored-by: Alice <[email protected]>\n",
21+
[]Trailer{
22+
Trailer{Key: "Co-authored-by", Value: "Alice <[email protected]>"},
23+
},
24+
},
25+
{
26+
"commit with two trailers\n\nCo-authored-by: Alice <[email protected]>\nSigned-off-by: Bob <[email protected]>\n",
27+
[]Trailer{
28+
Trailer{Key: "Co-authored-by", Value: "Alice <[email protected]>"},
29+
Trailer{Key: "Signed-off-by", Value: "Bob <[email protected]>"}},
30+
},
31+
}
32+
for _, test := range tests {
33+
fmt.Printf("%s", test.input)
34+
actual, err := MessageTrailers(test.input)
35+
if err != nil {
36+
t.Errorf("Trailers returned an unexpected error: %v", err)
37+
}
38+
if !reflect.DeepEqual(test.expected, actual) {
39+
t.Errorf("expecting %#v\ngot %#v", test.expected, actual)
40+
}
41+
}
42+
}

0 commit comments

Comments
 (0)