From d190d8a6b3717402744902d060be57195f27d604 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Tue, 16 Apr 2013 23:04:35 +0200 Subject: [PATCH] Take 2 on polymorphism --- blob.go | 18 +++++++++++++----- commit.go | 20 ++++++++++++++------ object.go | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ odb.go | 9 --------- repository.go | 40 +++++++++++++++++++++++----------------- tree.go | 29 +++++++++++++---------------- 6 files changed, 112 insertions(+), 53 deletions(-) create mode 100644 object.go diff --git a/blob.go b/blob.go index 73e3ab3..ee50a15 100644 --- a/blob.go +++ b/blob.go @@ -7,17 +7,25 @@ package git */ import "C" import ( - "runtime" "unsafe" + "runtime" ) type Blob struct { - ptr *C.git_object + ptr *C.git_blob } -func (v *Blob) Free() { - runtime.SetFinalizer(v, nil) - C.git_object_free(v.ptr) +func (o *Blob) Id() *Oid { + return newOidFromC(C.git_blob_id(o.ptr)) +} + +func (o *Blob) Type() ObjectType { + return OBJ_BLOB +} + +func (o *Blob) Free() { + runtime.SetFinalizer(o, nil) + C.git_blob_free(o.ptr) } func (v *Blob) Size() int64 { diff --git a/commit.go b/commit.go index d31f684..b1ca6c4 100644 --- a/commit.go +++ b/commit.go @@ -19,8 +19,17 @@ type Commit struct { ptr *C.git_commit } -func (c *Commit) Id() *Oid { - return newOidFromC(C.git_commit_id(c.ptr)) +func (o *Commit) Id() *Oid { + return newOidFromC(C.git_commit_id(o.ptr)) +} + +func (o *Commit) Type() ObjectType { + return OBJ_COMMIT +} + +func (o *Commit) Free() { + runtime.SetFinalizer(o, nil) + C.git_commit_free(o.ptr) } func (c *Commit) Message() string { @@ -28,15 +37,14 @@ func (c *Commit) Message() string { } func (c *Commit) Tree() (*Tree, error) { - tree := new(Tree) + var ptr *C.git_object - err := C.git_commit_tree(&tree.ptr, c.ptr) + err := C.git_commit_tree(&ptr, c.ptr) if err < 0 { return nil, LastError() } - runtime.SetFinalizer(tree, (*Tree).Free) - return tree, nil + return allocObject(ptr).(*Tree), nil } func (c *Commit) TreeId() *Oid { diff --git a/object.go b/object.go new file mode 100644 index 0000000..0d55409 --- /dev/null +++ b/object.go @@ -0,0 +1,49 @@ +package git + +/* +#cgo pkg-config: libgit2 +#include +#include +*/ +import "C" +import "runtime" + +type ObjectType int + +var ( + OBJ_ANY ObjectType = C.GIT_OBJ_ANY + OBJ_BAD ObjectType = C.GIT_OBJ_BAD + OBJ_COMMIT ObjectType = C.GIT_OBJ_COMMIT + OBJ_TREE ObjectType = C.GIT_OBJ_TREE + OBJ_BLOB ObjectType = C.GIT_OBJ_BLOB + OBJ_TAG ObjectType = C.GIT_OBJ_TAG +) + +type Object interface { + Free() + Id() *Oid + Type() ObjectType +} + +func allocObject(cobj *C.git_object) Object { + var object Object + + switch ObjectType(C.git_object_type(cobj)) { + case OBJ_COMMIT: + object = &Commit{cobj} + runtime.SetFinalizer(object, (*Commit).Free) + + case OBJ_TREE: + object = &Tree{cobj} + runtime.SetFinalizer(object, (*Tree).Free) + + case OBJ_BLOB: + object = &Blob{cobj} + runtime.SetFinalizer(object, (*Blob).Free) + + default: + return nil + } + + return object +} diff --git a/odb.go b/odb.go index bf17171..37d9fcd 100644 --- a/odb.go +++ b/odb.go @@ -12,15 +12,6 @@ import ( "runtime" ) -var ( - OBJ_ANY = C.GIT_OBJ_ANY - OBJ_BAD = C.GIT_OBJ_BAD - OBJ_COMMIT = C.GIT_OBJ_COMMIT - OBJ_TREE = C.GIT_OBJ_TREE - OBJ_BLOB = C.GIT_OBJ_BLOB - OBJ_TAG = C.GIT_OBJ_TAG -) - type Odb struct { ptr *C.git_odb } diff --git a/repository.go b/repository.go index 3de4974..015e5bf 100644 --- a/repository.go +++ b/repository.go @@ -72,35 +72,41 @@ func (v *Repository) Index() (*Index, error) { return newIndexFromC(ptr), nil } -func (v *Repository) LookupTree(oid *Oid) (*Tree, error) { - tree := new(Tree) - ret := C.git_tree_lookup(&tree.ptr, v.ptr, oid.toC()) +func (v *Repository) Lookup(oid *Oid, t ObjectType) (Object, error) { + var ptr *C.git_object + ret := C.git_object_lookup(&ptr, v.ptr, oid.toC(), C.git_otype(t)) if ret < 0 { return nil, LastError() } - return tree, nil + return allocObject(ptr), nil } -func (v *Repository) LookupCommit(o *Oid) (*Commit, error) { - commit := new(Commit) - ecode := C.git_commit_lookup(&commit.ptr, v.ptr, o.toC()) - if ecode < 0 { - return nil, LastError() +func (v *Repository) LookupTree(oid *Oid) (*Tree, error) { + obj, err := v.Lookup(oid, OBJ_TREE) + if err != nil { + return nil, err } - return commit, nil + return obj.(*Tree), nil } -func (v *Repository) LookupBlob(o *Oid) (*Blob, error) { - blob := new(Blob) - ecode := C.git_blob_lookup(&blob.ptr, v.ptr, o.toC()) - if ecode < 0 { - return nil, LastError() +func (v *Repository) LookupCommit(oid *Oid) (*Commit, error) { + obj, err := v.Lookup(oid, OBJ_COMMIT) + if err != nil { + return nil, err } - runtime.SetFinalizer(blob, (*Blob).Free) - return blob, nil + return obj.(*Commit), nil +} + +func (v *Repository) LookupBlob(oid *Oid) (*Blob, error) { + obj, err := v.Lookup(oid, OBJ_BLOB) + if err != nil { + return nil, err + } + + return obj.(*Blob), nil } func (v *Repository) LookupReference(name string) (*Reference, error) { diff --git a/tree.go b/tree.go index dc82929..d8a639c 100644 --- a/tree.go +++ b/tree.go @@ -17,6 +17,19 @@ type Tree struct { ptr *C.git_tree } +func (o *Tree) Id() *Oid { + return newOidFromC(C.git_tree_id(o.ptr)) +} + +func (o *Tree) Type() ObjectType { + return OBJ_TREE +} + +func (o *Tree) Free() { + runtime.SetFinalizer(o, nil) + C.git_tree_free(o.ptr) +} + type TreeEntry struct { Name string Id *Oid @@ -31,22 +44,6 @@ func newTreeEntry(entry *C.git_tree_entry) *TreeEntry { } } -func (t *Tree) Free() { - runtime.SetFinalizer(t, nil) - C.git_tree_free(t.ptr) -} - -func TreeLookup(repo *Repository, oid *Oid) (*Tree, error) { - tree := new(Tree) - err := C.git_tree_lookup(&tree.ptr, repo.ptr, oid.toC()) - if err < 0 { - return nil, LastError() - } - - runtime.SetFinalizer(tree, (*Tree).Free) - return tree, nil -} - func (t *Tree) EntryByName(filename string) *TreeEntry { cname := C.CString(filename) defer C.free(unsafe.Pointer(cname))