summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--merge.go31
-rw-r--r--merge_test.go59
2 files changed, 90 insertions, 0 deletions
diff --git a/merge.go b/merge.go
index 5b68a8b..8c87391 100644
--- a/merge.go
+++ b/merge.go
@@ -10,6 +10,7 @@ extern git_annotated_commit* _go_git_annotated_commit_array_get(git_annotated_co
*/
import "C"
import (
+ "reflect"
"runtime"
"unsafe"
)
@@ -243,6 +244,36 @@ func (r *Repository) MergeBase(one *Oid, two *Oid) (*Oid, error) {
return newOidFromC(&oid), nil
}
+// MergeBases retrieves the list of merge bases between two commits.
+//
+// If none are found, an empty slice is returned and the error is set
+// approprately
+func (r *Repository) MergeBases(one, two *Oid) ([]*Oid, error) {
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ var coids C.git_oidarray
+ ret := C.git_merge_bases(&coids, r.ptr, one.toC(), two.toC())
+ if ret < 0 {
+ return make([]*Oid, 0), MakeGitError(ret)
+ }
+
+ oids := make([]*Oid, coids.count)
+ hdr := reflect.SliceHeader {
+ Data: uintptr(unsafe.Pointer(coids.ids)),
+ Len: int(coids.count),
+ Cap: int(coids.count),
+ }
+
+ goSlice := *(*[]C.git_oid)(unsafe.Pointer(&hdr))
+
+ for i, cid := range goSlice {
+ oids[i] = newOidFromC(&cid)
+ }
+
+ return oids, nil
+}
+
//TODO: int git_merge_base_many(git_oid *out, git_repository *repo, size_t length, const git_oid input_array[]);
//TODO: GIT_EXTERN(int) git_merge_base_octopus(git_oid *out,git_repository *repo,size_t length,const git_oid input_array[]);
diff --git a/merge_test.go b/merge_test.go
index 0b1faca..c09deed 100644
--- a/merge_test.go
+++ b/merge_test.go
@@ -2,6 +2,7 @@ package git
import (
"testing"
+ "time"
)
func TestMergeWithSelf(t *testing.T) {
@@ -88,6 +89,64 @@ func TestMergeTreesWithoutAncestor(t *testing.T) {
}
+func appendCommit(t *testing.T, repo *Repository) (*Oid, *Oid) {
+ loc, err := time.LoadLocation("Europe/Berlin")
+ checkFatal(t, err)
+ sig := &Signature{
+ Name: "Rand Om Hacker",
+ Email: "[email protected]",
+ When: time.Date(2013, 03, 06, 14, 30, 0, 0, loc),
+ }
+
+ idx, err := repo.Index()
+ checkFatal(t, err)
+ err = idx.AddByPath("README")
+ checkFatal(t, err)
+ treeId, err := idx.WriteTree()
+ checkFatal(t, err)
+
+ message := "This is another commit\n"
+ tree, err := repo.LookupTree(treeId)
+ checkFatal(t, err)
+
+ ref, err := repo.LookupReference("HEAD")
+ checkFatal(t, err)
+
+ parent, err := ref.Peel(ObjectCommit)
+ checkFatal(t, err)
+
+ commitId, err := repo.CreateCommit("HEAD", sig, sig, message, tree, parent.(*Commit))
+ checkFatal(t, err)
+
+ return commitId, treeId
+}
+
+func TestMergeBase(t *testing.T) {
+ repo := createTestRepo(t)
+ defer cleanupTestRepo(t, repo)
+
+ commitAId, _ := seedTestRepo(t, repo)
+ commitBId, _ := appendCommit(t, repo)
+
+ mergeBase, err := repo.MergeBase(commitAId, commitBId)
+ checkFatal(t, err)
+
+ if mergeBase.Cmp(commitAId) != 0 {
+ t.Fatalf("unexpected merge base")
+ }
+
+ mergeBases, err := repo.MergeBases(commitAId, commitBId)
+ checkFatal(t, err)
+
+ if len(mergeBases) != 1 {
+ t.Fatalf("expected merge bases len to be 1, got %v", len(mergeBases))
+ }
+
+ if mergeBases[0].Cmp(commitAId) != 0 {
+ t.Fatalf("unexpected merge base")
+ }
+}
+
func compareBytes(t *testing.T, expected, actual []byte) {
for i, v := range expected {
if actual[i] != v {