Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 9 additions & 11 deletions handles.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,22 @@ type HandleList struct {
sync.RWMutex
// stores the Go pointers
handles []interface{}
// Indicates which indices are in use, and keeps a pointer to slot int variable (the handle)
// in the Go world, so that the Go garbage collector does not free it.
set map[int]*int
// Indicates which indices are in use.
set map[int]bool
}

func NewHandleList() *HandleList {
return &HandleList{
handles: make([]interface{}, 5),
set: make(map[int]*int),
set: make(map[int]bool),
}
}

// findUnusedSlot finds the smallest-index empty space in our
// list. You must only run this function while holding a write lock.
func (v *HandleList) findUnusedSlot() int {
for i := 1; i < len(v.handles); i++ {
_, isUsed := v.set[i]
if !isUsed {
if !v.set[i] {
return i
}
}
Expand All @@ -48,16 +46,16 @@ func (v *HandleList) Track(pointer interface{}) unsafe.Pointer {

slot := v.findUnusedSlot()
v.handles[slot] = pointer
v.set[slot] = &slot // Keep a pointer to slot in Go world, so it's not freed by GC.
v.set[slot] = true

v.Unlock()

return unsafe.Pointer(&slot)
return unsafe.Pointer(uintptr(slot))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes what we're doing, doesn't it? We were taking its address and making it a unsafe.Pointer. In the new code we're taking the slot value and casting it a few times. Should this still work?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I see why we have to do this. But this means that the set map is now not really keeping the pointers alive. It should then move to map[int]bool since we only need it to be set.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}

// Untrack stops tracking the pointer given by the handle
func (v *HandleList) Untrack(handle unsafe.Pointer) {
slot := *(*int)(handle)
slot := int(uintptr(handle))

v.Lock()

Expand All @@ -69,11 +67,11 @@ func (v *HandleList) Untrack(handle unsafe.Pointer) {

// Get retrieves the pointer from the given handle
func (v *HandleList) Get(handle unsafe.Pointer) interface{} {
slot := *(*int)(handle)
slot := int(uintptr(handle))

v.RLock()

if _, ok := v.set[slot]; !ok {
if !v.set[slot] {
panic(fmt.Sprintf("invalid pointer handle: %p", handle))
}

Expand Down
49 changes: 25 additions & 24 deletions merge.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package git
extern git_annotated_commit** _go_git_make_merge_head_array(size_t len);
extern void _go_git_annotated_commit_array_set(git_annotated_commit** array, git_annotated_commit* ptr, size_t n);
extern git_annotated_commit* _go_git_annotated_commit_array_get(git_annotated_commit** array, size_t n);
extern int _go_git_merge_file(git_merge_file_result*, char*, size_t, char*, unsigned int, char*, size_t, char*, unsigned int, char*, size_t, char*, unsigned int, git_merge_file_options*);

*/
import "C"
Expand Down Expand Up @@ -320,20 +321,6 @@ type MergeFileInput struct {
Contents []byte
}

// populate a C struct with merge file input, make sure to use freeMergeFileInput to clean up allocs
func populateCMergeFileInput(c *C.git_merge_file_input, input MergeFileInput) {
c.path = C.CString(input.Path)
if input.Contents != nil {
c.ptr = (*C.char)(unsafe.Pointer(&input.Contents[0]))
c.size = C.size_t(len(input.Contents))
}
c.mode = C.uint(input.Mode)
}

func freeCMergeFileInput(c *C.git_merge_file_input) {
C.free(unsafe.Pointer(c.path))
}

type MergeFileFlags int

const (
Expand Down Expand Up @@ -378,16 +365,26 @@ func freeCMergeFileOptions(c *C.git_merge_file_options) {

func MergeFile(ancestor MergeFileInput, ours MergeFileInput, theirs MergeFileInput, options *MergeFileOptions) (*MergeFileResult, error) {

var cancestor C.git_merge_file_input
var cours C.git_merge_file_input
var ctheirs C.git_merge_file_input
ancestorPath := C.CString(ancestor.Path)
defer C.free(unsafe.Pointer(ancestorPath))
var ancestorContents *byte
if len(ancestor.Contents) > 0 {
ancestorContents = &ancestor.Contents[0]
}

oursPath := C.CString(ours.Path)
defer C.free(unsafe.Pointer(oursPath))
var oursContents *byte
if len(ours.Contents) > 0 {
oursContents = &ours.Contents[0]
}

populateCMergeFileInput(&cancestor, ancestor)
defer freeCMergeFileInput(&cancestor)
populateCMergeFileInput(&cours, ours)
defer freeCMergeFileInput(&cours)
populateCMergeFileInput(&ctheirs, theirs)
defer freeCMergeFileInput(&ctheirs)
theirsPath := C.CString(theirs.Path)
defer C.free(unsafe.Pointer(theirsPath))
var theirsContents *byte
if len(theirs.Contents) > 0 {
theirsContents = &theirs.Contents[0]
}

var copts *C.git_merge_file_options
if options != nil {
Expand All @@ -404,7 +401,11 @@ func MergeFile(ancestor MergeFileInput, ours MergeFileInput, theirs MergeFileInp
defer runtime.UnlockOSThread()

var result C.git_merge_file_result
ecode := C.git_merge_file(&result, &cancestor, &cours, &ctheirs, copts)
ecode := C._go_git_merge_file(&result,
(*C.char)(unsafe.Pointer(ancestorContents)), C.size_t(len(ancestor.Contents)), ancestorPath, C.uint(ancestor.Mode),
(*C.char)(unsafe.Pointer(oursContents)), C.size_t(len(ours.Contents)), oursPath, C.uint(ours.Mode),
(*C.char)(unsafe.Pointer(theirsContents)), C.size_t(len(theirs.Contents)), theirsPath, C.uint(theirs.Mode),
copts)
if ecode < 0 {
return nil, MakeGitError(ecode)
}
Expand Down
7 changes: 5 additions & 2 deletions odb.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,15 @@ func (v *Odb) Exists(oid *Oid) bool {

func (v *Odb) Write(data []byte, otype ObjectType) (oid *Oid, err error) {
oid = new(Oid)
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&data))
var cptr unsafe.Pointer
if len(data) > 0 {
cptr = unsafe.Pointer(&data[0])
}

runtime.LockOSThread()
defer runtime.UnlockOSThread()

ret := C.git_odb_write(oid.toC(), v.ptr, unsafe.Pointer(hdr.Data), C.size_t(hdr.Len), C.git_otype(otype))
ret := C.git_odb_write(oid.toC(), v.ptr, cptr, C.size_t(len(data)), C.git_otype(otype))

if ret < 0 {
return nil, MakeGitError(ret)
Expand Down
23 changes: 23 additions & 0 deletions wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,4 +141,27 @@ int _go_git_tag_foreach(git_repository *repo, void *payload)
return git_tag_foreach(repo, (git_tag_foreach_cb)&gitTagForeachCb, payload);
}

int _go_git_merge_file(git_merge_file_result* out, char* ancestorContents, size_t ancestorLen, char* ancestorPath, unsigned int ancestorMode, char* oursContents, size_t oursLen, char* oursPath, unsigned int oursMode, char* theirsContents, size_t theirsLen, char* theirsPath, unsigned int theirsMode, git_merge_file_options* copts) {
git_merge_file_input ancestor = GIT_MERGE_FILE_INPUT_INIT;
git_merge_file_input ours = GIT_MERGE_FILE_INPUT_INIT;
git_merge_file_input theirs = GIT_MERGE_FILE_INPUT_INIT;

ancestor.ptr = ancestorContents;
ancestor.size = ancestorLen;
ancestor.path = ancestorPath;
ancestor.mode = ancestorMode;

ours.ptr = oursContents;
ours.size = oursLen;
ours.path = oursPath;
ours.mode = oursMode;

theirs.ptr = theirsContents;
theirs.size = theirsLen;
theirs.path = theirsPath;
theirs.mode = theirsMode;

return git_merge_file(out, &ancestor, &ours, &theirs, copts);
}

/* EOF */