summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--merge.go195
-rw-r--r--wrapper.c15
2 files changed, 210 insertions, 0 deletions
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 <git2.h>
+#include <git2/errors.h>
+
+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 */