From 3003e5e190bb566a978062a63247d250ec5c1c28 Mon Sep 17 00:00:00 2001 From: David Calavera Date: Thu, 24 Jul 2014 15:37:59 -0700 Subject: [PATCH 1/8] Add Repository#RevParse. --- revparse.go | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ revparse_test.go | 1 + 2 files changed, 55 insertions(+) create mode 100644 revparse.go create mode 100644 revparse_test.go diff --git a/revparse.go b/revparse.go new file mode 100644 index 0000000..f78867f --- /dev/null +++ b/revparse.go @@ -0,0 +1,54 @@ +package git + +/* +#include +#include + +extern void _go_git_revspec_free(git_revspec *revspec); +*/ +import "C" +import ( + "runtime" + "unsafe" +) + +type RevSpec struct { + ptr *C.git_revspec + From Object + To Object + repo *Repository +} + +func newRevSpecFrom(ptr *C.git_revspec, repo *Repository) *RevSpec { + rev := &RevSpec{ + ptr: ptr, + From: allocObject(ptr.from, repo), + To: allocObject(ptr.to, repo), + repo: repo, + } + runtime.SetFinalizer(rev, (*RevSpec).Free) + + return rev +} + +func (r *RevSpec) Free() { + runtime.SetFinalizer(r, nil) + r.From.Free() + r.To.Free() +} + +func (r *Repository) RevParse(spec string) (*RevSpec, error) { + cspec := C.CString(spec) + defer C.free(unsafe.Pointer(cspec)) + var ptr *C.git_revspec + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ecode := C.git_revparse(ptr, r.ptr, cspec) + if ecode < 0 { + return nil, MakeGitError(ecode) + } + + return newRevSpecFrom(ptr, r), nil +} diff --git a/revparse_test.go b/revparse_test.go new file mode 100644 index 0000000..cd99cdb --- /dev/null +++ b/revparse_test.go @@ -0,0 +1 @@ +package git From 8bbcdd65a64773b06ad4f88b183c7f3e1248b8f0 Mon Sep 17 00:00:00 2001 From: David Calavera Date: Thu, 24 Jul 2014 17:02:14 -0700 Subject: [PATCH 2/8] Move RevSpec#From and RevSpec#To to struct methods. --- revparse.go | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/revparse.go b/revparse.go index f78867f..7c43798 100644 --- a/revparse.go +++ b/revparse.go @@ -14,39 +14,45 @@ import ( type RevSpec struct { ptr *C.git_revspec - From Object - To Object repo *Repository } func newRevSpecFrom(ptr *C.git_revspec, repo *Repository) *RevSpec { rev := &RevSpec{ ptr: ptr, - From: allocObject(ptr.from, repo), - To: allocObject(ptr.to, repo), repo: repo, } - runtime.SetFinalizer(rev, (*RevSpec).Free) return rev } -func (r *RevSpec) Free() { - runtime.SetFinalizer(r, nil) - r.From.Free() - r.To.Free() +func (r *RevSpec) From() Object { + if r.ptr.from == nil { + return nil + } + + return allocObject(r.ptr.from, r.repo) +} + +func (r *RevSpec) To() Object { + if r.ptr.to == nil { + return nil + } + + return allocObject(r.ptr.to, r.repo) } func (r *Repository) RevParse(spec string) (*RevSpec, error) { cspec := C.CString(spec) defer C.free(unsafe.Pointer(cspec)) + var ptr *C.git_revspec runtime.LockOSThread() defer runtime.UnlockOSThread() ecode := C.git_revparse(ptr, r.ptr, cspec) - if ecode < 0 { + if ecode != 0 { return nil, MakeGitError(ecode) } From 1e651aaa22a35bbcaaa1af4da0e05a674833ebdc Mon Sep 17 00:00:00 2001 From: David Calavera Date: Thu, 24 Jul 2014 17:08:58 -0700 Subject: [PATCH 3/8] Add simple test for `rev-parse HEAD`. --- revparse_test.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/revparse_test.go b/revparse_test.go index cd99cdb..dea2150 100644 --- a/revparse_test.go +++ b/revparse_test.go @@ -1 +1,30 @@ package git + +import ( + "fmt" + "os" + "testing" +) + +func TestRevParseSingle(t *testing.T) { + repo := createTestRepo(t) + defer os.RemoveAll(repo.Workdir()) + + commitId, _ := seedTestRepo(t, repo) + fmt.Println(commitId) + + revSpec, err := repo.RevParse("HEAD") + checkFatal(t, err) + + checkObject(t, revSpec.From(), commitId) +} + +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()) + } +} From 43b6e0b15487b3a109f586fedfc69c8e73089b70 Mon Sep 17 00:00:00 2001 From: David Calavera Date: Thu, 24 Jul 2014 17:20:22 -0700 Subject: [PATCH 4/8] Make a new pointer to pass to git_revparse. --- revparse.go | 2 +- revparse_test.go | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/revparse.go b/revparse.go index 7c43798..bc9a4e2 100644 --- a/revparse.go +++ b/revparse.go @@ -46,7 +46,7 @@ func (r *Repository) RevParse(spec string) (*RevSpec, error) { cspec := C.CString(spec) defer C.free(unsafe.Pointer(cspec)) - var ptr *C.git_revspec + ptr := new(C.git_revspec) runtime.LockOSThread() defer runtime.UnlockOSThread() diff --git a/revparse_test.go b/revparse_test.go index dea2150..45dc7dc 100644 --- a/revparse_test.go +++ b/revparse_test.go @@ -1,7 +1,6 @@ package git import ( - "fmt" "os" "testing" ) @@ -11,7 +10,6 @@ func TestRevParseSingle(t *testing.T) { defer os.RemoveAll(repo.Workdir()) commitId, _ := seedTestRepo(t, repo) - fmt.Println(commitId) revSpec, err := repo.RevParse("HEAD") checkFatal(t, err) From 691d8f23bad4e6ff850fd0504bc7a8ed1cd656e9 Mon Sep 17 00:00:00 2001 From: David Calavera Date: Thu, 24 Jul 2014 17:41:10 -0700 Subject: [PATCH 5/8] Add Repository#RevParseSingle. --- revparse.go | 17 +++++++++++++++++ revparse_test.go | 14 +++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/revparse.go b/revparse.go index bc9a4e2..9cd494f 100644 --- a/revparse.go +++ b/revparse.go @@ -58,3 +58,20 @@ func (r *Repository) RevParse(spec string) (*RevSpec, error) { return newRevSpecFrom(ptr, r), nil } + +func (r *Repository) RevParseSingle(spec string) (Object, error) { + cspec := C.CString(spec) + defer C.free(unsafe.Pointer(cspec)) + + var obj *C.git_object + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + ecode := C.git_revparse_single(&obj, r.ptr, cspec) + if ecode != 0 { + return nil, MakeGitError(ecode) + } + + return allocObject(obj, r), nil +} diff --git a/revparse_test.go b/revparse_test.go index 45dc7dc..df553a0 100644 --- a/revparse_test.go +++ b/revparse_test.go @@ -5,7 +5,7 @@ import ( "testing" ) -func TestRevParseSingle(t *testing.T) { +func TestRevParse(t *testing.T) { repo := createTestRepo(t) defer os.RemoveAll(repo.Workdir()) @@ -17,6 +17,18 @@ func TestRevParseSingle(t *testing.T) { 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 checkObject(t *testing.T, obj Object, id *Oid) { if obj == nil { t.Fatalf("bad object") From 94d207e11cf2b7c3f405191c0525cdf67b4b14f7 Mon Sep 17 00:00:00 2001 From: David Calavera Date: Thu, 24 Jul 2014 21:03:50 -0700 Subject: [PATCH 6/8] Add Repository#RevParseExt. --- revparse.go | 22 ++++++++++++++++++++++ revparse_test.go | 18 ++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/revparse.go b/revparse.go index 9cd494f..05a75a0 100644 --- a/revparse.go +++ b/revparse.go @@ -75,3 +75,25 @@ func (r *Repository) RevParseSingle(spec string) (Object, error) { return allocObject(obj, r), 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 index df553a0..fc267a3 100644 --- a/revparse_test.go +++ b/revparse_test.go @@ -29,6 +29,24 @@ func TestRevParseSingle(t *testing.T) { 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") From 29840d28ade46db361fc0fe492115e41e8ecf9fd Mon Sep 17 00:00:00 2001 From: David Calavera Date: Fri, 22 Aug 2014 22:36:18 -0700 Subject: [PATCH 7/8] Extract data into a go struct. --- repository.go | 17 ----------- revparse.go | 73 +++++++++++++++++++++++++++++------------------- revparse_test.go | 12 ++++---- 3 files changed, 50 insertions(+), 52 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 index 05a75a0..6992238 100644 --- a/revparse.go +++ b/revparse.go @@ -12,37 +12,52 @@ import ( "unsafe" ) -type RevSpec struct { - ptr *C.git_revspec - repo *Repository +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 newRevSpecFrom(ptr *C.git_revspec, repo *Repository) *RevSpec { - rev := &RevSpec{ - ptr: ptr, - repo: repo, +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) } - return rev -} - -func (r *RevSpec) From() Object { - if r.ptr.from == nil { - return nil + if ptr.from != nil { + from = allocObject(ptr.from, repo) } - return allocObject(r.ptr.from, r.repo) -} - -func (r *RevSpec) To() Object { - if r.ptr.to == nil { - return nil + return &Revspec{ + to: to, + from: from, + flags: RevparseFlag(ptr.flags), } - - return allocObject(r.ptr.to, r.repo) } -func (r *Repository) RevParse(spec string) (*RevSpec, error) { +func (r *Repository) Revparse(spec string) (*Revspec, error) { cspec := C.CString(spec) defer C.free(unsafe.Pointer(cspec)) @@ -56,27 +71,27 @@ func (r *Repository) RevParse(spec string) (*RevSpec, error) { return nil, MakeGitError(ecode) } - return newRevSpecFrom(ptr, r), nil + return newRevspecFromC(ptr, r), nil } -func (r *Repository) RevParseSingle(spec string) (Object, error) { +func (v *Repository) RevparseSingle(spec string) (Object, error) { cspec := C.CString(spec) defer C.free(unsafe.Pointer(cspec)) - var obj *C.git_object + var ptr *C.git_object runtime.LockOSThread() defer runtime.UnlockOSThread() - ecode := C.git_revparse_single(&obj, r.ptr, cspec) - if ecode != 0 { + ecode := C.git_revparse_single(&ptr, v.ptr, cspec) + if ecode < 0 { return nil, MakeGitError(ecode) } - return allocObject(obj, r), nil + return allocObject(ptr, v), nil } -func (r *Repository) RevParseExt(spec string) (Object, *Reference, error) { +func (r *Repository) RevparseExt(spec string) (Object, *Reference, error) { cspec := C.CString(spec) defer C.free(unsafe.Pointer(cspec)) diff --git a/revparse_test.go b/revparse_test.go index fc267a3..c046a20 100644 --- a/revparse_test.go +++ b/revparse_test.go @@ -5,31 +5,31 @@ import ( "testing" ) -func TestRevParse(t *testing.T) { +func TestRevparse(t *testing.T) { repo := createTestRepo(t) defer os.RemoveAll(repo.Workdir()) commitId, _ := seedTestRepo(t, repo) - revSpec, err := repo.RevParse("HEAD") + revSpec, err := repo.Revparse("HEAD") checkFatal(t, err) checkObject(t, revSpec.From(), commitId) } -func TestRevParseSingle(t *testing.T) { +func TestRevparseSingle(t *testing.T) { repo := createTestRepo(t) defer os.RemoveAll(repo.Workdir()) commitId, _ := seedTestRepo(t, repo) - obj, err := repo.RevParseSingle("HEAD") + obj, err := repo.RevparseSingle("HEAD") checkFatal(t, err) checkObject(t, obj, commitId) } -func TestRevParseExt(t *testing.T) { +func TestRevparseExt(t *testing.T) { repo := createTestRepo(t) defer os.RemoveAll(repo.Workdir()) @@ -38,7 +38,7 @@ func TestRevParseExt(t *testing.T) { ref, err := repo.CreateReference("refs/heads/master", treeId, true, nil, "") checkFatal(t, err) - obj, ref, err := repo.RevParseExt("master") + obj, ref, err := repo.RevparseExt("master") checkFatal(t, err) checkObject(t, obj, treeId) From 0d585802492b33b1eae28755b034d8e0f2999657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Tue, 26 Aug 2014 12:35:05 +0200 Subject: [PATCH 8/8] Remove unnecessary heap allocation --- revparse.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/revparse.go b/revparse.go index 6992238..9e0070e 100644 --- a/revparse.go +++ b/revparse.go @@ -61,17 +61,17 @@ func (r *Repository) Revparse(spec string) (*Revspec, error) { cspec := C.CString(spec) defer C.free(unsafe.Pointer(cspec)) - ptr := new(C.git_revspec) + var crevspec C.git_revspec runtime.LockOSThread() defer runtime.UnlockOSThread() - ecode := C.git_revparse(ptr, r.ptr, cspec) + ecode := C.git_revparse(&crevspec, r.ptr, cspec) if ecode != 0 { return nil, MakeGitError(ecode) } - return newRevspecFromC(ptr, r), nil + return newRevspecFromC(&crevspec, r), nil } func (v *Repository) RevparseSingle(spec string) (Object, error) {