From 9e7ba027086173fdf540b8ddb465a57bfa281126 Mon Sep 17 00:00:00 2001 From: Jesse Ezell Date: Fri, 28 Feb 2014 01:06:41 -0800 Subject: [PATCH] wrap merge functions --- merge.go | 195 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ wrapper.c | 15 +++++ 2 files changed, 210 insertions(+) create mode 100644 merge.go diff --git a/merge.go b/merge.go new file mode 100644 index 0000000..03ace2b --- /dev/null +++ b/merge.go @@ -0,0 +1,195 @@ +package git + +/* +#include +#include + +extern git_merge_head** _go_git_make_merge_head_array(size_t len); +extern void _go_git_merge_head_array_set(git_merge_head** array, git_merge_head* ptr, size_t n); +extern git_merge_head* _go_git_merge_head_array_get(git_merge_head** array, size_t n); + +*/ +import "C" +import ( + "runtime" + "unsafe" +) + +type MergeHead struct { + ptr *C.git_merge_head +} + +func newMergeHeadFromC(c *C.git_merge_head) *MergeHead { + mh := &MergeHead{ptr: c} + runtime.SetFinalizer(mh, (*MergeHead).Free) + return mh +} + +func (mh *MergeHead) Free() { + C.git_merge_head_free(mh.ptr) + runtime.SetFinalizer(mh, nil) +} + +func (r *Repository) MergeHeadFromFetchHead(branchName string, remoteURL string, oid *Oid) (*MergeHead, error) { + mh := &MergeHead{} + + cbranchName := C.CString(branchName) + defer C.free(unsafe.Pointer(cbranchName)) + + cremoteURL := C.CString(remoteURL) + defer C.free(unsafe.Pointer(cremoteURL)) + + ret := C.git_merge_head_from_fetchhead(&mh.ptr, r.ptr, cbranchName, cremoteURL, oid.toC()) + if ret < 0 { + return nil, MakeGitError(ret) + } + runtime.SetFinalizer(mh, (*MergeHead).Free) + return mh, nil +} + +func (r *Repository) MergeHeadFromId(oid *Oid) (*MergeHead, error) { + mh := &MergeHead{} + + ret := C.git_merge_head_from_id(&mh.ptr, r.ptr, oid.toC()) + if ret < 0 { + return nil, MakeGitError(ret) + } + runtime.SetFinalizer(mh, (*MergeHead).Free) + return mh, nil +} + +func (r *Repository) MergeHeadFromRef(ref *Reference) (*MergeHead, error) { + mh := &MergeHead{} + + ret := C.git_merge_head_from_ref(&mh.ptr, r.ptr, ref.ptr) + if ret < 0 { + return nil, MakeGitError(ret) + } + runtime.SetFinalizer(mh, (*MergeHead).Free) + return mh, nil +} + +type MergeOptions struct { +} + +func (mo *MergeOptions) toC() *C.git_merge_opts { + return nil +} + +type MergeTreeOptions struct { +} + +func (mo *MergeTreeOptions) toC() *C.git_merge_tree_opts { + return nil +} + +type MergeResult struct { + ptr *C.git_merge_result +} + +func newMergeResultFromC(c *C.git_merge_result) *MergeResult { + mr := &MergeResult{ptr: c} + runtime.SetFinalizer(mr, (*MergeResult).Free) + return mr +} + +func (mr *MergeResult) Free() { + runtime.SetFinalizer(mr, nil) + C.git_merge_result_free(mr.ptr) +} + +func (mr *MergeResult) IsFastForward() bool { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_merge_result_is_fastforward(mr.ptr) + return ret != 0 +} + +func (mr *MergeResult) IsUpToDate() bool { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ret := C.git_merge_result_is_uptodate(mr.ptr) + return ret != 0 +} + +func (mr *MergeResult) FastForwardId() (*Oid, error) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + var oid C.git_oid + ret := C.git_merge_result_fastforward_id(&oid, mr.ptr) + if ret < 0 { + return nil, MakeGitError(ret) + } + return newOidFromC(&oid), nil +} + +func (r *Repository) Merge(theirHeads []MergeHead, options MergeOptions) (*MergeResult, error) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + var result *C.git_merge_result + + copts := options.toC() + + cmerge_head_array := C._go_git_make_merge_head_array(C.size_t(len(theirHeads))) + defer C.free(unsafe.Pointer(cmerge_head_array)) + + for i, _ := range theirHeads { + C._go_git_merge_head_array_set(cmerge_head_array, theirHeads[i].ptr, C.size_t(i)) + } + + err := C.git_merge(&result, r.ptr, cmerge_head_array, C.size_t(len(theirHeads)), copts) + if err < 0 { + return nil, MakeGitError(err) + } + return newMergeResultFromC(result), nil +} + +func (r *Repository) MergeCommits(ours *Commit, theirs *Commit, options MergeTreeOptions) (*Index, error) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + copts := options.toC() + + idx := &Index{} + + ret := C.git_merge_commits(&idx.ptr, r.ptr, ours.ptr, theirs.ptr, copts) + if ret < 0 { + return nil, MakeGitError(ret) + } + runtime.SetFinalizer(idx, (*Index).Free) + return idx, nil +} + +func (r *Repository) MergeTrees(ancestor *Tree, ours *Tree, theirs *Tree, options MergeTreeOptions) (*Index, error) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + copts := options.toC() + + idx := &Index{} + + ret := C.git_merge_trees(&idx.ptr, r.ptr, ancestor.ptr, ours.ptr, theirs.ptr, copts) + if ret < 0 { + return nil, MakeGitError(ret) + } + runtime.SetFinalizer(idx, (*Index).Free) + return idx, nil +} + +func (r *Repository) MergeBase(one *Oid, two *Oid) (*Oid, error) { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + var oid C.git_oid + ret := C.git_merge_base(&oid, r.ptr, one.toC(), two.toC()) + if ret < 0 { + return nil, MakeGitError(ret) + } + return newOidFromC(&oid), nil +} + +// int git_merge_base_many(git_oid *out, git_repository *repo, size_t length, const git_oid input_array[]); diff --git a/wrapper.c b/wrapper.c index 2af3974..66e10bd 100644 --- a/wrapper.c +++ b/wrapper.c @@ -24,4 +24,19 @@ int _go_git_odb_foreach(git_odb *db, void *payload) { return git_odb_foreach(db, (git_odb_foreach_cb)&odbForEachCb, payload); } + +git_merge_head** _go_git_make_merge_head_array(size_t len) +{ + return (git_merge_head**)malloc(sizeof(git_merge_head*) * len); +} + +void _go_git_merge_head_array_set(git_merge_head** array, git_merge_head* ptr, size_t n) +{ + array[n] = ptr; +} + +git_merge_head* _go_git_merge_head_array_get(git_merge_head** array, size_t n) +{ + return array[n]; +} /* EOF */