handles, merge: simplify code, don't copy file contents
diff --git a/handles.go b/handles.go
index a855717..f5d30f0 100644
--- a/handles.go
+++ b/handles.go
@@ -10,15 +10,14 @@
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),
}
}
@@ -26,8 +25,7 @@
// 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
}
}
@@ -48,7 +46,7 @@
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()
@@ -73,7 +71,7 @@
v.RLock()
- if _, ok := v.set[slot]; !ok {
+ if !v.set[slot] {
panic(fmt.Sprintf("invalid pointer handle: %p", handle))
}
diff --git a/merge.go b/merge.go
index 535a5e7..06f5676 100644
--- a/merge.go
+++ b/merge.go
@@ -6,6 +6,7 @@
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"
@@ -85,8 +86,8 @@
)
type MergeOptions struct {
- Version uint
- TreeFlags MergeTreeFlag
+ Version uint
+ TreeFlags MergeTreeFlag
RenameThreshold uint
TargetLimit uint
@@ -98,7 +99,7 @@
func mergeOptionsFromC(opts *C.git_merge_options) MergeOptions {
return MergeOptions{
Version: uint(opts.version),
- TreeFlags: MergeTreeFlag(opts.tree_flags),
+ TreeFlags: MergeTreeFlag(opts.tree_flags),
RenameThreshold: uint(opts.rename_threshold),
TargetLimit: uint(opts.target_limit),
FileFavor: MergeFileFavor(opts.file_favor),
@@ -262,10 +263,10 @@
}
oids := make([]*Oid, coids.count)
- hdr := reflect.SliceHeader{
+ hdr := reflect.SliceHeader {
Data: uintptr(unsafe.Pointer(coids.ids)),
- Len: int(coids.count),
- Cap: int(coids.count),
+ Len: int(coids.count),
+ Cap: int(coids.count),
}
goSlice := *(*[]C.git_oid)(unsafe.Pointer(&hdr))
@@ -320,24 +321,6 @@
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.char {
- c.path = C.CString(input.Path)
- var toFree *C.char
- if input.Contents != nil {
- toFree = C.CString(string(input.Contents))
- c.ptr = toFree
- c.size = C.size_t(len(input.Contents))
- }
- c.mode = C.uint(input.Mode)
- return toFree
-}
-
-func freeCMergeFileInput(c *C.git_merge_file_input, toFree *C.char) {
- C.free(unsafe.Pointer(c.path))
- C.free(unsafe.Pointer(toFree))
-}
-
type MergeFileFlags int
const (
@@ -382,16 +365,26 @@
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]
+ }
- t := populateCMergeFileInput(&cancestor, ancestor)
- defer freeCMergeFileInput(&cancestor, t)
- t = populateCMergeFileInput(&cours, ours)
- defer freeCMergeFileInput(&cours, t)
- t = populateCMergeFileInput(&ctheirs, theirs)
- defer freeCMergeFileInput(&ctheirs, t)
+ oursPath := C.CString(ours.Path)
+ defer C.free(unsafe.Pointer(oursPath))
+ var oursContents *byte
+ if len(ours.Contents) > 0 {
+ oursContents = &ours.Contents[0]
+ }
+
+ 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 {
@@ -408,7 +401,11 @@
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)
}
diff --git a/wrapper.c b/wrapper.c
index 2b1a180..a0688c0 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -141,4 +141,27 @@
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 */