Merge branch 'master' into next
This commit is contained in:
commit
ac719c6759
20
handles.go
20
handles.go
|
@ -10,15 +10,14 @@ type HandleList struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
// stores the Go pointers
|
// stores the Go pointers
|
||||||
handles []interface{}
|
handles []interface{}
|
||||||
// Indicates which indices are in use, and keeps a pointer to slot int variable (the handle)
|
// Indicates which indices are in use.
|
||||||
// in the Go world, so that the Go garbage collector does not free it.
|
set map[int]bool
|
||||||
set map[int]*int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewHandleList() *HandleList {
|
func NewHandleList() *HandleList {
|
||||||
return &HandleList{
|
return &HandleList{
|
||||||
handles: make([]interface{}, 5),
|
handles: make([]interface{}, 5),
|
||||||
set: make(map[int]*int),
|
set: make(map[int]bool),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,8 +25,7 @@ func NewHandleList() *HandleList {
|
||||||
// list. You must only run this function while holding a write lock.
|
// list. You must only run this function while holding a write lock.
|
||||||
func (v *HandleList) findUnusedSlot() int {
|
func (v *HandleList) findUnusedSlot() int {
|
||||||
for i := 1; i < len(v.handles); i++ {
|
for i := 1; i < len(v.handles); i++ {
|
||||||
_, isUsed := v.set[i]
|
if !v.set[i] {
|
||||||
if !isUsed {
|
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,16 +46,16 @@ func (v *HandleList) Track(pointer interface{}) unsafe.Pointer {
|
||||||
|
|
||||||
slot := v.findUnusedSlot()
|
slot := v.findUnusedSlot()
|
||||||
v.handles[slot] = pointer
|
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()
|
v.Unlock()
|
||||||
|
|
||||||
return unsafe.Pointer(&slot)
|
return unsafe.Pointer(uintptr(slot))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Untrack stops tracking the pointer given by the handle
|
// Untrack stops tracking the pointer given by the handle
|
||||||
func (v *HandleList) Untrack(handle unsafe.Pointer) {
|
func (v *HandleList) Untrack(handle unsafe.Pointer) {
|
||||||
slot := *(*int)(handle)
|
slot := int(uintptr(handle))
|
||||||
|
|
||||||
v.Lock()
|
v.Lock()
|
||||||
|
|
||||||
|
@ -69,11 +67,11 @@ func (v *HandleList) Untrack(handle unsafe.Pointer) {
|
||||||
|
|
||||||
// Get retrieves the pointer from the given handle
|
// Get retrieves the pointer from the given handle
|
||||||
func (v *HandleList) Get(handle unsafe.Pointer) interface{} {
|
func (v *HandleList) Get(handle unsafe.Pointer) interface{} {
|
||||||
slot := *(*int)(handle)
|
slot := int(uintptr(handle))
|
||||||
|
|
||||||
v.RLock()
|
v.RLock()
|
||||||
|
|
||||||
if _, ok := v.set[slot]; !ok {
|
if !v.set[slot] {
|
||||||
panic(fmt.Sprintf("invalid pointer handle: %p", handle))
|
panic(fmt.Sprintf("invalid pointer handle: %p", handle))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
49
merge.go
49
merge.go
|
@ -6,6 +6,7 @@ package git
|
||||||
extern git_annotated_commit** _go_git_make_merge_head_array(size_t len);
|
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 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 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"
|
import "C"
|
||||||
|
@ -327,20 +328,6 @@ type MergeFileInput struct {
|
||||||
Contents []byte
|
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
|
type MergeFileFlags int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -385,16 +372,26 @@ func freeCMergeFileOptions(c *C.git_merge_file_options) {
|
||||||
|
|
||||||
func MergeFile(ancestor MergeFileInput, ours MergeFileInput, theirs MergeFileInput, options *MergeFileOptions) (*MergeFileResult, error) {
|
func MergeFile(ancestor MergeFileInput, ours MergeFileInput, theirs MergeFileInput, options *MergeFileOptions) (*MergeFileResult, error) {
|
||||||
|
|
||||||
var cancestor C.git_merge_file_input
|
ancestorPath := C.CString(ancestor.Path)
|
||||||
var cours C.git_merge_file_input
|
defer C.free(unsafe.Pointer(ancestorPath))
|
||||||
var ctheirs C.git_merge_file_input
|
var ancestorContents *byte
|
||||||
|
if len(ancestor.Contents) > 0 {
|
||||||
|
ancestorContents = &ancestor.Contents[0]
|
||||||
|
}
|
||||||
|
|
||||||
populateCMergeFileInput(&cancestor, ancestor)
|
oursPath := C.CString(ours.Path)
|
||||||
defer freeCMergeFileInput(&cancestor)
|
defer C.free(unsafe.Pointer(oursPath))
|
||||||
populateCMergeFileInput(&cours, ours)
|
var oursContents *byte
|
||||||
defer freeCMergeFileInput(&cours)
|
if len(ours.Contents) > 0 {
|
||||||
populateCMergeFileInput(&ctheirs, theirs)
|
oursContents = &ours.Contents[0]
|
||||||
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
|
var copts *C.git_merge_file_options
|
||||||
if options != nil {
|
if options != nil {
|
||||||
|
@ -411,7 +408,11 @@ func MergeFile(ancestor MergeFileInput, ours MergeFileInput, theirs MergeFileInp
|
||||||
defer runtime.UnlockOSThread()
|
defer runtime.UnlockOSThread()
|
||||||
|
|
||||||
var result C.git_merge_file_result
|
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 {
|
if ecode < 0 {
|
||||||
return nil, MakeGitError(ecode)
|
return nil, MakeGitError(ecode)
|
||||||
}
|
}
|
||||||
|
|
7
odb.go
7
odb.go
|
@ -76,12 +76,15 @@ func (v *Odb) Exists(oid *Oid) bool {
|
||||||
|
|
||||||
func (v *Odb) Write(data []byte, otype ObjectType) (oid *Oid, err error) {
|
func (v *Odb) Write(data []byte, otype ObjectType) (oid *Oid, err error) {
|
||||||
oid = new(Oid)
|
oid = new(Oid)
|
||||||
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&data))
|
var cptr unsafe.Pointer
|
||||||
|
if len(data) > 0 {
|
||||||
|
cptr = unsafe.Pointer(&data[0])
|
||||||
|
}
|
||||||
|
|
||||||
runtime.LockOSThread()
|
runtime.LockOSThread()
|
||||||
defer runtime.UnlockOSThread()
|
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 {
|
if ret < 0 {
|
||||||
return nil, MakeGitError(ret)
|
return nil, MakeGitError(ret)
|
||||||
|
|
23
wrapper.c
23
wrapper.c
|
@ -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);
|
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 */
|
/* EOF */
|
||||||
|
|
Loading…
Reference in New Issue