diff options
| author | Carlos Martín Nieto <[email protected]> | 2016-03-07 11:17:10 +0100 |
|---|---|---|
| committer | Carlos Martín Nieto <[email protected]> | 2016-03-07 11:22:53 +0100 |
| commit | 2ae7d13ba1037c7fa579fc52263ea280b37244ea (patch) | |
| tree | f2509df04ec4e6187943aad83ea672e660102a8b /object.go | |
| parent | fa644d2fc9efa3baee93b525212d76dfa17a5db5 (diff) | |
| parent | e095c85fd06b5820d2f0098ff3e66b266553dbd5 (diff) | |
Merge branch 'next'
Diffstat (limited to 'object.go')
| -rw-r--r-- | object.go | 173 |
1 files changed, 121 insertions, 52 deletions
@@ -4,7 +4,11 @@ package git #include <git2.h> */ import "C" -import "runtime" +import ( + "errors" + "fmt" + "runtime" +) type ObjectType int @@ -17,15 +21,7 @@ const ( ObjectTag ObjectType = C.GIT_OBJ_TAG ) -type Object interface { - Free() - Id() *Oid - Type() ObjectType - Owner() *Repository - Peel(t ObjectType) (Object, error) -} - -type gitObject struct { +type Object struct { ptr *C.git_object repo *Repository } @@ -49,23 +45,128 @@ func (t ObjectType) String() string { return "" } -func (o gitObject) Id() *Oid { +func (o *Object) Id() *Oid { return newOidFromC(C.git_object_id(o.ptr)) } -func (o gitObject) Type() ObjectType { +func (o *Object) Type() ObjectType { return ObjectType(C.git_object_type(o.ptr)) } // Owner returns a weak reference to the repository which owns this -// object -func (o gitObject) Owner() *Repository { +// object. This won't keep the underlying repository alive. +func (o *Object) Owner() *Repository { return &Repository{ ptr: C.git_object_owner(o.ptr), } } -func (o *gitObject) Free() { +func dupObject(obj *Object, kind ObjectType) (*C.git_object, error) { + if obj.Type() != kind { + return nil, errors.New(fmt.Sprintf("object is not a %v", kind)) + } + + var cobj *C.git_object + + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + if err := C.git_object_dup(&cobj, obj.ptr); err < 0 { + return nil, MakeGitError(err) + } + + return cobj, nil +} + +func allocTree(ptr *C.git_tree, repo *Repository) *Tree { + tree := &Tree{ + Object: Object{ + ptr: (*C.git_object)(ptr), + repo: repo, + }, + cast_ptr: ptr, + } + runtime.SetFinalizer(tree, (*Tree).Free) + + return tree +} + +func (o *Object) AsTree() (*Tree, error) { + cobj, err := dupObject(o, ObjectTree) + if err != nil { + return nil, err + } + + return allocTree((*C.git_tree)(cobj), o.repo), nil +} + +func allocCommit(ptr *C.git_commit, repo *Repository) *Commit { + commit := &Commit{ + Object: Object{ + ptr: (*C.git_object)(ptr), + repo: repo, + }, + cast_ptr: ptr, + } + runtime.SetFinalizer(commit, (*Commit).Free) + + return commit +} + +func (o *Object) AsCommit() (*Commit, error) { + cobj, err := dupObject(o, ObjectCommit) + if err != nil { + return nil, err + } + + return allocCommit((*C.git_commit)(cobj), o.repo), nil +} + +func allocBlob(ptr *C.git_blob, repo *Repository) *Blob { + blob := &Blob{ + Object: Object{ + ptr: (*C.git_object)(ptr), + repo: repo, + }, + cast_ptr: ptr, + } + runtime.SetFinalizer(blob, (*Blob).Free) + + return blob +} + +func (o *Object) AsBlob() (*Blob, error) { + cobj, err := dupObject(o, ObjectBlob) + if err != nil { + return nil, err + } + + return allocBlob((*C.git_blob)(cobj), o.repo), nil +} + +func allocTag(ptr *C.git_tag, repo *Repository) *Tag { + tag := &Tag{ + Object: Object{ + ptr: (*C.git_object)(ptr), + repo: repo, + }, + cast_ptr: ptr, + } + runtime.SetFinalizer(tag, (*Tag).Free) + + return tag +} + +func (o *Object) AsTag() (*Tag, error) { + cobj, err := dupObject(o, ObjectTag) + if err != nil { + return nil, err + } + + return allocTag((*C.git_tag)(cobj), o.repo), nil +} + +func (o *Object) Free() { runtime.SetFinalizer(o, nil) C.git_object_free(o.ptr) } @@ -82,7 +183,7 @@ func (o *gitObject) Free() { // // If peeling a tag we discover an object which cannot be peeled to the target // type due to the object model, an error will be returned. -func (o *gitObject) Peel(t ObjectType) (Object, error) { +func (o *Object) Peel(t ObjectType) (*Object, error) { var cobj *C.git_object runtime.LockOSThread() @@ -95,44 +196,12 @@ func (o *gitObject) Peel(t ObjectType) (Object, error) { return allocObject(cobj, o.repo), nil } -func allocObject(cobj *C.git_object, repo *Repository) Object { - obj := gitObject{ +func allocObject(cobj *C.git_object, repo *Repository) *Object { + obj := &Object{ ptr: cobj, repo: repo, } + runtime.SetFinalizer(obj, (*Object).Free) - switch ObjectType(C.git_object_type(cobj)) { - case ObjectCommit: - commit := &Commit{ - gitObject: obj, - cast_ptr: (*C.git_commit)(cobj), - } - runtime.SetFinalizer(commit, (*Commit).Free) - return commit - - case ObjectTree: - tree := &Tree{ - gitObject: obj, - cast_ptr: (*C.git_tree)(cobj), - } - runtime.SetFinalizer(tree, (*Tree).Free) - return tree - - case ObjectBlob: - blob := &Blob{ - gitObject: obj, - cast_ptr: (*C.git_blob)(cobj), - } - runtime.SetFinalizer(blob, (*Blob).Free) - return blob - case ObjectTag: - tag := &Tag{ - gitObject: obj, - cast_ptr: (*C.git_tag)(cobj), - } - runtime.SetFinalizer(tag, (*Tag).Free) - return tag - } - - return nil + return obj } |
