Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit 6384ab9

Browse files
committed
storage/dotgit: add KeepDescriptors option
This option maintains packfile file descriptors opened after reading objects from them. It improves performance as it does not have to be opening packfiles each time an object is needed. Also adds Close to EncodedObjectStorer to close all the files manualy. Signed-off-by: Javi Fontan <[email protected]>
1 parent 2f15838 commit 6384ab9

File tree

7 files changed

+92
-2
lines changed

7 files changed

+92
-2
lines changed

plumbing/storer/object.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ type EncodedObjectStorer interface {
4040
// HasEncodedObject returns ErrObjNotFound if the object doesn't
4141
// exist. If the object does exist, it returns nil.
4242
HasEncodedObject(plumbing.Hash) error
43+
// Close any opened files.
44+
Close() error
4345
}
4446

4547
// DeltaObjectStorer is an EncodedObjectStorer that can return delta

plumbing/storer/object_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,7 @@ func (o *MockObjectStorage) IterEncodedObjects(t plumbing.ObjectType) (EncodedOb
157157
func (o *MockObjectStorage) Begin() Transaction {
158158
return nil
159159
}
160+
161+
func (o *MockObjectStorage) Close() error {
162+
return nil
163+
}

storage/filesystem/dotgit/dotgit.go

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ type Options struct {
6262
// ExclusiveAccess means that the filesystem is not modified externally
6363
// while the repo is open.
6464
ExclusiveAccess bool
65+
// KeepDescriptors makes the file descriptors to be reused but they will
66+
// need to be manually closed calling Close().
67+
KeepDescriptors bool
6568
}
6669

6770
// The DotGit type represents a local git repository on disk. This
@@ -78,6 +81,8 @@ type DotGit struct {
7881
objectMap map[plumbing.Hash]struct{}
7982
packList []plumbing.Hash
8083
packMap map[plumbing.Hash]struct{}
84+
85+
files map[string]billy.File
8186
}
8287

8388
// New returns a DotGit value ready to be used. The path argument must
@@ -123,6 +128,28 @@ func (d *DotGit) Initialize() error {
123128
return nil
124129
}
125130

131+
// Close closes all opened files.
132+
func (d *DotGit) Close() error {
133+
var firstError error
134+
if d.files != nil {
135+
for _, f := range d.files {
136+
err := f.Close()
137+
if err != nil && firstError == nil {
138+
firstError = err
139+
continue
140+
}
141+
}
142+
143+
d.files = nil
144+
}
145+
146+
if firstError != nil {
147+
return firstError
148+
}
149+
150+
return nil
151+
}
152+
126153
// ConfigWriter returns a file pointer for write to the config file
127154
func (d *DotGit) ConfigWriter() (billy.File, error) {
128155
return d.fs.Create(configPath)
@@ -217,12 +244,22 @@ func (d *DotGit) objectPackPath(hash plumbing.Hash, extension string) string {
217244
}
218245

219246
func (d *DotGit) objectPackOpen(hash plumbing.Hash, extension string) (billy.File, error) {
247+
if d.files == nil {
248+
d.files = make(map[string]billy.File)
249+
}
250+
220251
err := d.hasPack(hash)
221252
if err != nil {
222253
return nil, err
223254
}
224255

225-
pack, err := d.fs.Open(d.objectPackPath(hash, extension))
256+
path := d.objectPackPath(hash, extension)
257+
f, ok := d.files[path]
258+
if ok {
259+
return f, nil
260+
}
261+
262+
pack, err := d.fs.Open(path)
226263
if err != nil {
227264
if os.IsNotExist(err) {
228265
return nil, ErrPackfileNotFound
@@ -231,6 +268,10 @@ func (d *DotGit) objectPackOpen(hash plumbing.Hash, extension string) (billy.Fil
231268
return nil, err
232269
}
233270

271+
if d.options.KeepDescriptors && extension == "pack" {
272+
d.files[path] = pack
273+
}
274+
234275
return pack, nil
235276
}
236277

storage/filesystem/dotgit/dotgit_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,34 @@ func (s *SuiteDotGit) TestObjectPack(c *C) {
465465
c.Assert(filepath.Ext(pack.Name()), Equals, ".pack")
466466
}
467467

468+
func (s *SuiteDotGit) TestObjectPackWithKeepDescriptors(c *C) {
469+
f := fixtures.Basic().ByTag(".git").One()
470+
fs := f.DotGit()
471+
dir := NewWithOptions(fs, Options{KeepDescriptors: true})
472+
473+
pack, err := dir.ObjectPack(f.PackfileHash)
474+
c.Assert(err, IsNil)
475+
c.Assert(filepath.Ext(pack.Name()), Equals, ".pack")
476+
477+
pack2, err := dir.ObjectPack(f.PackfileHash)
478+
c.Assert(err, IsNil)
479+
c.Assert(pack, Equals, pack2)
480+
481+
err = dir.Close()
482+
c.Assert(err, IsNil)
483+
484+
pack2, err = dir.ObjectPack(f.PackfileHash)
485+
c.Assert(err, IsNil)
486+
c.Assert(pack, Not(Equals), pack2)
487+
488+
err = pack2.Close()
489+
c.Assert(err, IsNil)
490+
491+
err = dir.Close()
492+
c.Assert(err, NotNil)
493+
494+
}
495+
468496
func (s *SuiteDotGit) TestObjectPackIdx(c *C) {
469497
f := fixtures.Basic().ByTag(".git").One()
470498
fs := f.DotGit()

storage/filesystem/object.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ func (s *ObjectStorage) loadIdxFile(h plumbing.Hash) (err error) {
7474
}
7575

7676
defer ioutil.CheckClose(f, &err)
77+
7778
idxf := idxfile.NewMemoryIndex()
7879
d := idxfile.NewDecoder(f)
7980
if err = d.Decode(idxf); err != nil {
@@ -280,7 +281,9 @@ func (s *ObjectStorage) getFromPackfile(h plumbing.Hash, canBeDelta bool) (
280281
return nil, err
281282
}
282283

283-
defer ioutil.CheckClose(f, &err)
284+
if !s.options.KeepDescriptors {
285+
defer ioutil.CheckClose(f, &err)
286+
}
284287

285288
idx := s.index[pack]
286289
if canBeDelta {
@@ -423,6 +426,11 @@ func (s *ObjectStorage) buildPackfileIters(t plumbing.ObjectType, seen map[plumb
423426
}, nil
424427
}
425428

429+
// Close closes all opened files.
430+
func (s *ObjectStorage) Close() error {
431+
return s.dir.Close()
432+
}
433+
426434
type lazyPackfilesIter struct {
427435
hashes []plumbing.Hash
428436
open func(h plumbing.Hash) (storer.EncodedObjectIter, error)

storage/filesystem/storage.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ type Options struct {
2727
// ExclusiveAccess means that the filesystem is not modified externally
2828
// while the repo is open.
2929
ExclusiveAccess bool
30+
// KeepDescriptors makes the file descriptors to be reused but they will
31+
// need to be manually closed calling Close().
32+
KeepDescriptors bool
3033
}
3134

3235
// NewStorage returns a new Storage backed by a given `fs.Filesystem`
@@ -41,6 +44,7 @@ func NewStorageWithOptions(
4144
) (*Storage, error) {
4245
dirOps := dotgit.Options{
4346
ExclusiveAccess: ops.ExclusiveAccess,
47+
KeepDescriptors: ops.KeepDescriptors,
4448
}
4549

4650
dir := dotgit.NewWithOptions(fs, dirOps)

storage/memory/storage.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,9 @@ func (o *ObjectStorage) ObjectPacks() ([]plumbing.Hash, error) {
183183
func (o *ObjectStorage) DeleteOldObjectPackAndIndex(plumbing.Hash, time.Time) error {
184184
return nil
185185
}
186+
func (s *ObjectStorage) Close() error {
187+
return nil
188+
}
186189

187190
var errNotSupported = fmt.Errorf("Not supported")
188191

0 commit comments

Comments
 (0)