Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit 808076a

Browse files
authored
Merge pull request #56 from vmarkovtsev/master
Wrap more objects with CGo
2 parents e305c47 + da07dca commit 808076a

File tree

10 files changed

+498
-9
lines changed

10 files changed

+498
-9
lines changed

cshared/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ and it is the responsibility of the other side to `free()` it or it will leak
7272
otherwise.
7373

7474
Another tricky part is in `c_std_map_get_str_str` and similar places
75-
where you need to return `*C.char` from an unaddressed array accessed under
75+
where you need to return `*C.char` from an unaddressable array accessed under
7676
a pseudonym type through reflection. The only way I've found working
77-
is using `reflect.Copy` to byte slice (copy) and then conversion to
78-
`string` (copy), then `C.CString` (copy) and finally another (copy) on the
79-
receiving side because the latter must be `free()`-d. Extremely efficient.
77+
is using `reflect.Copy` to byte slice (copy), then `CBytes` (copy) and
78+
finally another (copy) on the receiving side because the latter must be
79+
`free()`-d.

cshared/blame_cshared.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// +build ignore
2+
package main
3+
4+
import (
5+
"C"
6+
7+
"gopkg.in/src-d/go-git.v3"
8+
)
9+
10+
//export c_Blame_get_Path
11+
func c_Blame_get_Path(b uint64) *C.char {
12+
obj, ok := GetObject(Handle(b))
13+
if !ok {
14+
return nil
15+
}
16+
blame := obj.(*git.Blame)
17+
return C.CString(blame.Path)
18+
}
19+
20+
//export c_Blame_get_Rev
21+
func c_Blame_get_Rev(b uint64) *C.char {
22+
obj, ok := GetObject(Handle(b))
23+
if !ok {
24+
return nil
25+
}
26+
blame := obj.(*git.Blame)
27+
return CBytes(blame.Rev[:])
28+
}
29+
30+
31+
//export c_Blame_get_Lines_len
32+
func c_Blame_get_Lines_len(b uint64) int {
33+
obj, ok := GetObject(Handle(b))
34+
if !ok {
35+
return 0
36+
}
37+
blame := obj.(*git.Blame)
38+
return len(blame.Lines)
39+
}
40+
41+
//export c_Blame_get_Lines_item
42+
func c_Blame_get_Lines_item(b uint64, i int) {
43+
obj, ok := GetObject(Handle(b))
44+
if !ok {
45+
return
46+
}
47+
blame := obj.(*git.Blame)
48+
line := blame.Lines[i]
49+
_ = line
50+
}
51+

cshared/commit_cshared.go

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ package main
44
import (
55
"C"
66
"io"
7+
"reflect"
8+
"unsafe"
79

810
"gopkg.in/src-d/go-git.v3"
911
"gopkg.in/src-d/go-git.v3/core"
@@ -16,7 +18,7 @@ func c_Commit_get_Hash(c uint64) *C.char {
1618
return nil
1719
}
1820
commit := obj.(*git.Commit)
19-
return C.CString(string(commit.Hash[:]))
21+
return CBytes(commit.Hash[:])
2022
}
2123

2224
//export c_Commit_get_Author
@@ -142,6 +144,43 @@ func c_Commit_String(c uint64) *C.char {
142144
return C.CString(commit.String())
143145
}
144146

147+
//export c_Commit_References
148+
func c_Commit_References(c uint64, path string) (*C.char, int, int, *C.char) {
149+
obj, ok := GetObject(Handle(c))
150+
if !ok {
151+
return nil, 0, ErrorCodeNotFound, C.CString(MessageNotFound)
152+
}
153+
commit := obj.(*git.Commit)
154+
refs, err := commit.References(CopyString(path))
155+
if err != nil {
156+
return nil, 0, ErrorCodeInternal, C.CString(err.Error())
157+
}
158+
handles := make([]uint64, len(refs))
159+
for i, c := range(refs) {
160+
handles[i] = uint64(RegisterObject(c))
161+
}
162+
size := 8 * len(handles)
163+
dest := C.malloc(C.size_t(size))
164+
header := (*reflect.SliceHeader)(unsafe.Pointer(&handles))
165+
header.Len *= 8
166+
copy((*[1<<30]byte)(dest)[:], *(*[]byte)(unsafe.Pointer(header)))
167+
return (*C.char)(dest), size / 8, ErrorCodeSuccess, nil
168+
}
169+
170+
//export c_Commit_Blame
171+
func c_Commit_Blame(c uint64, path string) (uint64, int, *C.char) {
172+
obj, ok := GetObject(Handle(c))
173+
if !ok {
174+
return IH, ErrorCodeNotFound, C.CString(MessageNotFound)
175+
}
176+
commit := obj.(*git.Commit)
177+
blame, err := commit.Blame(CopyString(path))
178+
if err != nil {
179+
return IH, ErrorCodeInternal, C.CString(err.Error())
180+
}
181+
return uint64(RegisterObject(blame)), ErrorCodeSuccess, nil
182+
}
183+
145184
//export c_NewCommitIter
146185
func c_NewCommitIter(r uint64, iter uint64) uint64 {
147186
obj, ok := GetObject(Handle(r))

cshared/file_cshared.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package main
2+
3+
import (
4+
"C"
5+
6+
"gopkg.in/src-d/go-git.v3"
7+
)
8+
9+
//export c_File_get_Name
10+
func c_File_get_Name(f uint64) *C.char {
11+
obj, ok := GetObject(Handle(f))
12+
if !ok {
13+
return nil
14+
}
15+
file := obj.(*git.File)
16+
return C.CString(file.Name)
17+
}
18+
19+
//export c_File_get_Mode
20+
func c_File_get_Mode(f uint64) uint32 {
21+
obj, ok := GetObject(Handle(f))
22+
if !ok {
23+
return 0
24+
}
25+
file := obj.(*git.File)
26+
return uint32(file.Mode)
27+
}
28+
29+
//export c_NewFileIter
30+
func c_NewFileIter(r uint64, t uint64) uint64 {
31+
obj, ok := GetObject(Handle(r))
32+
if !ok {
33+
return IH
34+
}
35+
repo := obj.(*git.Repository)
36+
obj, ok = GetObject(Handle(t))
37+
if !ok {
38+
return IH
39+
}
40+
tree := obj.(*git.Tree)
41+
iter := git.NewFileIter(repo, tree)
42+
return uint64(RegisterObject(iter))
43+
}
44+
45+
//export c_FileIter_Next
46+
func c_FileIter_Next(i uint64) (uint64, int, *C.char) {
47+
obj, ok := GetObject(Handle(i))
48+
if !ok {
49+
return IH, ErrorCodeNotFound, C.CString(MessageNotFound)
50+
}
51+
iter := obj.(*git.FileIter)
52+
file, err := iter.Next()
53+
if err != nil {
54+
return IH, ErrorCodeInternal, C.CString(err.Error())
55+
}
56+
return uint64(RegisterObject(file)), ErrorCodeSuccess, nil
57+
}
58+
59+
//export c_FileIter_Close
60+
func c_FileIter_Close(i uint64) {
61+
obj, ok := GetObject(Handle(i))
62+
if !ok {
63+
return
64+
}
65+
iter := obj.(*git.FileIter)
66+
iter.Close()
67+
}

cshared/objects.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,13 @@ func CopyString(str string) string {
140140
return string(buf)
141141
}
142142

143+
// https://github.com/golang/go/issues/14838
144+
func CBytes(bytes []byte) *C.char {
145+
ptr := C.malloc(C.size_t(len(bytes)))
146+
copy((*[1<<30]byte)(ptr)[:], bytes)
147+
return (*C.char)(ptr)
148+
}
149+
143150
func SafeIsNil(v reflect.Value) bool {
144151
defer func() { recover() }()
145152
return v.IsNil()

cshared/objects_cshared.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func c_Blob_get_Hash(b uint64) *C.char {
5454
return nil
5555
}
5656
blob := obj.(*git.Blob)
57-
return C.CString(string(blob.Hash[:]))
57+
return CBytes(blob.Hash[:])
5858
}
5959

6060
//export c_Blob_Size

cshared/remote_cshared.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ func c_Remote_Head(r uint64) (*C.char, int, *C.char) {
130130
if err != nil {
131131
return nil, ErrorCodeInternal, C.CString(err.Error())
132132
}
133-
return C.CString(string(hash[:])), ErrorCodeSuccess, nil
133+
return CBytes(hash[:]), ErrorCodeSuccess, nil
134134
}
135135

136136
//export c_Remote_Fetch
@@ -177,7 +177,7 @@ func c_Remote_Ref(r uint64, refName string) (*C.char, int, *C.char) {
177177
if err != nil {
178178
return nil, ErrorCodeInternal, C.CString(err.Error())
179179
}
180-
return C.CString(string(hash[:])), ErrorCodeSuccess, nil
180+
return CBytes(hash[:]), ErrorCodeSuccess, nil
181181
}
182182

183183
//export c_Remote_Refs

cshared/std_cshared.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func c_std_map_get_str_str(m uint64, key string) *C.char {
2828
val.Type().Elem().Kind() == reflect.Uint8 {
2929
arr := make([]byte, val.Len(), val.Len())
3030
reflect.Copy(reflect.ValueOf(arr), val)
31-
return C.CString(string(arr))
31+
return CBytes(arr)
3232
}
3333
return C.CString(val.String())
3434
}

0 commit comments

Comments
 (0)