From 57ceb04c783e8a96325c995b2e71bc0d5ef054da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 28 Sep 2013 14:32:37 +0200 Subject: [PATCH] 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. --- index_test.go | 14 ++++++++++++++ odb.go | 6 ++++++ odb_test.go | 16 +++++++++++++++- repository.go | 33 ++++++++++++++++++++++++--------- submodule.go | 2 +- 5 files changed, 60 insertions(+), 11 deletions(-) diff --git a/index_test.go b/index_test.go index 9828d0f..cf5e35e 100644 --- a/index_test.go +++ b/index_test.go @@ -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 diff --git a/odb.go b/odb.go index 638ef74..8d38e75 100644 --- a/odb.go +++ b/odb.go @@ -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 diff --git a/odb_test.go b/odb_test.go index 3c7624c..5d51f70 100644 --- a/odb_test.go +++ b/odb_test.go @@ -32,4 +32,18 @@ func TestOdbStream(t *testing.T) { if stream.Id.Cmp(expectedId) != 0 { t.Fatal("Wrong data written") } -} \ No newline at end of file +} + +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") + } +} diff --git a/repository.go b/repository.go index 3a9068d..617f099 100644 --- a/repository.go +++ b/repository.go @@ -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 { diff --git a/submodule.go b/submodule.go index 48ea151..84ec993 100644 --- a/submodule.go +++ b/submodule.go @@ -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 {