Repository: libgit2/git2go
Pull request #423 (2018-01-26 00:02:26)

merge: add two missing AnnotatedCommit methods
These should be reviewed somewhat skeptically; the implementation was pulled in monkey-see-monkey-do from similar calls.



Patch:
diff --git a/merge.go b/merge.go
index 955289a..06e98a0 100644
--- a/merge.go
+++ b/merge.go
@@ -27,6 +27,15 @@ func newAnnotatedCommitFromC(ptr *C.git_annotated_commit, r *Repository) *Annota
 	return mh
 }
 
+func (mh *AnnotatedCommit) Id() *Oid {
+	runtime.LockOSThread()
+	defer runtime.UnlockOSThread()
+
+	ret := newOidFromC(C.git_annotated_commit_id(mh.ptr))
+	runtime.KeepAlive(mh)
+	return ret
+}
+
 func (mh *AnnotatedCommit) Free() {
 	runtime.SetFinalizer(mh, nil)
 	C.git_annotated_commit_free(mh.ptr)
@@ -49,7 +58,9 @@ func (r *Repository) AnnotatedCommitFromFetchHead(branchName string, remoteURL s
 		return nil, MakeGitError(ret)
 	}
 
-	return newAnnotatedCommitFromC(ptr, r), nil
+	annotatedCommit := newAnnotatedCommitFromC(ptr, r)
+	runtime.KeepAlive(r)
+	return annotatedCommit, nil
 }
 
 func (r *Repository) LookupAnnotatedCommit(oid *Oid) (*AnnotatedCommit, error) {
@@ -62,7 +73,10 @@ func (r *Repository) LookupAnnotatedCommit(oid *Oid) (*AnnotatedCommit, error) {
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
-	return newAnnotatedCommitFromC(ptr, r), nil
+
+	annotatedCommit := newAnnotatedCommitFromC(ptr, r)
+	runtime.KeepAlive(r)
+	return annotatedCommit, nil
 }
 
 func (r *Repository) AnnotatedCommitFromRef(ref *Reference) (*AnnotatedCommit, error) {
@@ -76,7 +90,29 @@ func (r *Repository) AnnotatedCommitFromRef(ref *Reference) (*AnnotatedCommit, e
 	if ret < 0 {
 		return nil, MakeGitError(ret)
 	}
-	return newAnnotatedCommitFromC(ptr, r), nil
+
+	annotatedCommit := newAnnotatedCommitFromC(ptr, r)
+	runtime.KeepAlive(r)
+	return annotatedCommit, nil
+}
+
+func (r *Repository) AnnotatedCommitFromRevspec(spec string) (*AnnotatedCommit, error) {
+	crevspec := C.CString(spec)
+	defer C.free(unsafe.Pointer(crevspec))
+
+	runtime.LockOSThread()
+	defer runtime.UnlockOSThread()
+
+	var ptr *C.git_annotated_commit
+	ret := C.git_annotated_commit_from_revspec(&ptr, r.ptr, crevspec)
+	runtime.KeepAlive(r)
+	if ret < 0 {
+		return nil, MakeGitError(ret)
+	}
+
+	annotatedCommit := newAnnotatedCommitFromC(ptr, r)
+	runtime.KeepAlive(r)
+	return annotatedCommit, nil
 }
 
 type MergeTreeFlag int


Test patch:
diff --git a/merge_test.go b/merge_test.go
index f2c84bc..7cf034f 100644
--- a/merge_test.go
+++ b/merge_test.go
@@ -5,6 +5,22 @@ import (
 	"time"
 )
 
+func TestAnnotatedCommitFromRevspec(t *testing.T) {
+	t.Parallel()
+	repo := createTestRepo(t)
+	defer cleanupTestRepo(t, repo)
+
+	seedTestRepo(t, repo)
+
+	mergeHead, err := repo.AnnotatedCommitFromRevspec("refs/heads/master")
+	checkFatal(t, err)
+
+	expectedId := "473bf778b67b6d53e2ab289e0f1a2e8addef2fc2"
+	if mergeHead.Id().String() != expectedId {
+		t.Errorf("mergeHead.Id() = %v, want %v", mergeHead.Id(), expectedId)
+	}
+}
+
 func TestMergeWithSelf(t *testing.T) {
 	t.Parallel()
 	repo := createTestRepo(t)
@@ -18,6 +34,11 @@ func TestMergeWithSelf(t *testing.T) {
 	mergeHead, err := repo.AnnotatedCommitFromRef(master)
 	checkFatal(t, err)
 
+	expectedId := "473bf778b67b6d53e2ab289e0f1a2e8addef2fc2"
+	if mergeHead.Id().String() != expectedId {
+		t.Errorf("mergeHead.Id() = %v, want %v", mergeHead.Id(), expectedId)
+	}
+
 	mergeHeads := make([]*AnnotatedCommit, 1)
 	mergeHeads[0] = mergeHead
 	err = repo.Merge(mergeHeads, nil, nil)