summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--repository.go17
-rw-r--r--revparse.go114
-rw-r--r--revparse_test.go58
3 files changed, 172 insertions, 17 deletions
diff --git a/repository.go b/repository.go
index 8cc966c..5b4e806 100644
--- a/repository.go
+++ b/repository.go
@@ -469,23 +469,6 @@ func (v *Repository) TreeBuilderFromTree(tree *Tree) (*TreeBuilder, error) {
return bld, nil
}
-func (v *Repository) RevparseSingle(spec string) (Object, error) {
- cspec := C.CString(spec)
- defer C.free(unsafe.Pointer(cspec))
-
- var ptr *C.git_object
-
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
-
- ecode := C.git_revparse_single(&ptr, v.ptr, cspec)
- if ecode < 0 {
- return nil, MakeGitError(ecode)
- }
-
- return allocObject(ptr, v), nil
-}
-
// EnsureLog ensures that there is a reflog for the given reference
// name and creates an empty one if necessary.
func (v *Repository) EnsureLog(name string) error {
diff --git a/revparse.go b/revparse.go
new file mode 100644
index 0000000..9e0070e
--- /dev/null
+++ b/revparse.go
@@ -0,0 +1,114 @@
+package git
+
+/*
+#include <git2.h>
+#include <git2/errors.h>
+
+extern void _go_git_revspec_free(git_revspec *revspec);
+*/
+import "C"
+import (
+ "runtime"
+ "unsafe"
+)
+
+type RevparseFlag int
+
+const (
+ RevparseSingle RevparseFlag = C.GIT_REVPARSE_SINGLE
+ RevparseRange = C.GIT_REVPARSE_RANGE
+ RevparseMergeBase = C.GIT_REVPARSE_MERGE_BASE
+)
+
+type Revspec struct {
+ to Object
+ from Object
+ flags RevparseFlag
+}
+
+func (rs *Revspec) To() Object {
+ return rs.to
+}
+
+func (rs *Revspec) From() Object {
+ return rs.from
+}
+
+func (rs *Revspec) Flags() RevparseFlag {
+ return rs.flags
+}
+
+func newRevspecFromC(ptr *C.git_revspec, repo *Repository) *Revspec {
+ var to Object
+ var from Object
+
+ if ptr.to != nil {
+ to = allocObject(ptr.to, repo)
+ }
+
+ if ptr.from != nil {
+ from = allocObject(ptr.from, repo)
+ }
+
+ return &Revspec{
+ to: to,
+ from: from,
+ flags: RevparseFlag(ptr.flags),
+ }
+}
+
+func (r *Repository) Revparse(spec string) (*Revspec, error) {
+ cspec := C.CString(spec)
+ defer C.free(unsafe.Pointer(cspec))
+
+ var crevspec C.git_revspec
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ecode := C.git_revparse(&crevspec, r.ptr, cspec)
+ if ecode != 0 {
+ return nil, MakeGitError(ecode)
+ }
+
+ return newRevspecFromC(&crevspec, r), nil
+}
+
+func (v *Repository) RevparseSingle(spec string) (Object, error) {
+ cspec := C.CString(spec)
+ defer C.free(unsafe.Pointer(cspec))
+
+ var ptr *C.git_object
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ecode := C.git_revparse_single(&ptr, v.ptr, cspec)
+ if ecode < 0 {
+ return nil, MakeGitError(ecode)
+ }
+
+ return allocObject(ptr, v), nil
+}
+
+func (r *Repository) RevparseExt(spec string) (Object, *Reference, error) {
+ cspec := C.CString(spec)
+ defer C.free(unsafe.Pointer(cspec))
+
+ var obj *C.git_object
+ var ref *C.git_reference
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ ecode := C.git_revparse_ext(&obj, &ref, r.ptr, cspec)
+ if ecode != 0 {
+ return nil, nil, MakeGitError(ecode)
+ }
+
+ if ref == nil {
+ return allocObject(obj, r), nil, nil
+ }
+
+ return allocObject(obj, r), newReferenceFromC(ref, r), nil
+}
diff --git a/revparse_test.go b/revparse_test.go
new file mode 100644
index 0000000..c046a20
--- /dev/null
+++ b/revparse_test.go
@@ -0,0 +1,58 @@
+package git
+
+import (
+ "os"
+ "testing"
+)
+
+func TestRevparse(t *testing.T) {
+ repo := createTestRepo(t)
+ defer os.RemoveAll(repo.Workdir())
+
+ commitId, _ := seedTestRepo(t, repo)
+
+ revSpec, err := repo.Revparse("HEAD")
+ checkFatal(t, err)
+
+ checkObject(t, revSpec.From(), commitId)
+}
+
+func TestRevparseSingle(t *testing.T) {
+ repo := createTestRepo(t)
+ defer os.RemoveAll(repo.Workdir())
+
+ commitId, _ := seedTestRepo(t, repo)
+
+ obj, err := repo.RevparseSingle("HEAD")
+ checkFatal(t, err)
+
+ checkObject(t, obj, commitId)
+}
+
+func TestRevparseExt(t *testing.T) {
+ repo := createTestRepo(t)
+ defer os.RemoveAll(repo.Workdir())
+
+ _, treeId := seedTestRepo(t, repo)
+
+ ref, err := repo.CreateReference("refs/heads/master", treeId, true, nil, "")
+ checkFatal(t, err)
+
+ obj, ref, err := repo.RevparseExt("master")
+ checkFatal(t, err)
+
+ checkObject(t, obj, treeId)
+ if ref == nil {
+ t.Fatalf("bad reference")
+ }
+}
+
+func checkObject(t *testing.T, obj Object, id *Oid) {
+ if obj == nil {
+ t.Fatalf("bad object")
+ }
+
+ if !obj.Id().Equal(id) {
+ t.Fatalf("bad object, expected %s, got %s", id.String(), obj.Id().String())
+ }
+}