Return the same index and odb objects in successive calls

Instead of creating a new Go object each time Repository.Index()/Odb()
are called, return the same one as long as the underlying pointer
remains the same.
This commit is contained in:
Carlos Martín Nieto 2013-09-28 14:32:37 +02:00
parent 66e1c47619
commit 57ceb04c78
5 changed files with 60 additions and 11 deletions

View File

@ -22,6 +22,20 @@ func TestCreateRepoAndStage(t *testing.T) {
}
}
func TestIndexTwoCalls(t *testing.T) {
repo := createTestRepo(t)
defer os.RemoveAll(repo.Workdir())
idx1, err := repo.Index()
checkFatal(t, err)
idx2, err := repo.Index()
checkFatal(t, err)
if idx1 != idx2 {
t.Fatal("Two Index() calls give different objects")
}
}
func checkFatal(t *testing.T, err error) {
if err == nil {
return

6
odb.go
View File

@ -17,6 +17,12 @@ type Odb struct {
ptr *C.git_odb
}
func newOdbFromC(ptr *C.git_odb) *Odb {
odb := &Odb{ptr}
runtime.SetFinalizer(odb, (*Odb).Free)
return odb
}
func (v *Odb) Exists(oid *Oid) bool {
ret := C.git_odb_exists(v.ptr, oid.toC())
return ret != 0

View File

@ -33,3 +33,17 @@ func TestOdbStream(t *testing.T) {
t.Fatal("Wrong data written")
}
}
func TestOdbTwoCalls(t *testing.T) {
repo := createTestRepo(t)
defer os.RemoveAll(repo.Workdir())
odb1, err := repo.Odb()
checkFatal(t, err)
odb2, err := repo.Odb()
checkFatal(t, err)
if odb1 != odb2 {
t.Fatal("Two Odb() calls return different objects")
}
}

View File

@ -13,6 +13,11 @@ import (
// Repository
type Repository struct {
ptr *C.git_repository
// These are kept so that two repo.Index() or repo.Odb() calls
// return the same object, as we do in the library
idx *Index
odb *Odb
}
func OpenRepository(path string) (*Repository, error) {
@ -72,17 +77,22 @@ func (v *Repository) Config() (*Config, error) {
}
func (v *Repository) Index() (*Index, error) {
var ptr *C.git_index
runtime.LockOSThread()
defer runtime.UnlockOSThread()
var ptr *C.git_index
ret := C.git_repository_index(&ptr, v.ptr)
if ret < 0 {
return nil, LastError()
}
return newIndexFromC(ptr), nil
if v.idx != nil && v.idx.ptr == ptr {
C.git_index_free(ptr) // decrease the refcount
return v.idx, nil
}
v.idx = newIndexFromC(ptr)
return v.idx, nil
}
func (v *Repository) lookupType(oid *Oid, t ObjectType) (Object, error) {
@ -246,18 +256,23 @@ func (v *Odb) Free() {
C.git_odb_free(v.ptr)
}
func (v *Repository) Odb() (odb *Odb, err error) {
odb = new(Odb)
func (v *Repository) Odb() (*Odb, error) {
runtime.LockOSThread()
defer runtime.UnlockOSThread()
if ret := C.git_repository_odb(&odb.ptr, v.ptr); ret < 0 {
var ptr *C.git_odb
if ret := C.git_repository_odb(&ptr, v.ptr); ret < 0 {
return nil, LastError()
}
runtime.SetFinalizer(odb, (*Odb).Free)
return
if v.odb != nil && v.odb.ptr == ptr {
C.git_odb_free(ptr) // decrease the refcount
return v.odb, nil
}
v.odb = newOdbFromC(ptr)
return v.odb, nil
}
func (repo *Repository) Path() string {

View File

@ -153,7 +153,7 @@ func (sub *Submodule) Save() error {
func (sub *Submodule) Owner() *Repository {
repo := C.git_submodule_owner(sub.ptr)
//FIXME: how to handle dangling references ?
return &Repository{repo}
return &Repository{ptr: repo}
}
func (sub *Submodule) Name() string {