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

Commit c2ab4ac

Browse files
authored
Merge pull request #962 from jfontan/fix/do-not-close-files-in-iterator
storage/filesystem: keep packs open in PackfileIter
2 parents f69f530 + a7b0102 commit c2ab4ac

File tree

2 files changed

+64
-12
lines changed

2 files changed

+64
-12
lines changed

storage/filesystem/object.go

+24-8
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,10 @@ func (s *ObjectStorage) IterEncodedObjects(t plumbing.ObjectType) (storer.Encode
396396
return storer.NewMultiEncodedObjectIter(iters), nil
397397
}
398398

399-
func (s *ObjectStorage) buildPackfileIters(t plumbing.ObjectType, seen map[plumbing.Hash]struct{}) (storer.EncodedObjectIter, error) {
399+
func (s *ObjectStorage) buildPackfileIters(
400+
t plumbing.ObjectType,
401+
seen map[plumbing.Hash]struct{},
402+
) (storer.EncodedObjectIter, error) {
400403
if err := s.requireIndex(); err != nil {
401404
return nil, err
402405
}
@@ -412,7 +415,10 @@ func (s *ObjectStorage) buildPackfileIters(t plumbing.ObjectType, seen map[plumb
412415
if err != nil {
413416
return nil, err
414417
}
415-
return newPackfileIter(s.dir.Fs(), pack, t, seen, s.index[h], s.deltaBaseCache)
418+
return newPackfileIter(
419+
s.dir.Fs(), pack, t, seen, s.index[h],
420+
s.deltaBaseCache, s.options.KeepDescriptors,
421+
)
416422
},
417423
}, nil
418424
}
@@ -473,16 +479,21 @@ type packfileIter struct {
473479
pack billy.File
474480
iter storer.EncodedObjectIter
475481
seen map[plumbing.Hash]struct{}
482+
483+
// tells whether the pack file should be left open after iteration or not
484+
keepPack bool
476485
}
477486

478487
// NewPackfileIter returns a new EncodedObjectIter for the provided packfile
479488
// and object type. Packfile and index file will be closed after they're
480-
// used.
489+
// used. If keepPack is true the packfile won't be closed after the iteration
490+
// finished.
481491
func NewPackfileIter(
482492
fs billy.Filesystem,
483493
f billy.File,
484494
idxFile billy.File,
485495
t plumbing.ObjectType,
496+
keepPack bool,
486497
) (storer.EncodedObjectIter, error) {
487498
idx := idxfile.NewMemoryIndex()
488499
if err := idxfile.NewDecoder(idxFile).Decode(idx); err != nil {
@@ -493,7 +504,8 @@ func NewPackfileIter(
493504
return nil, err
494505
}
495506

496-
return newPackfileIter(fs, f, t, make(map[plumbing.Hash]struct{}), idx, nil)
507+
seen := make(map[plumbing.Hash]struct{})
508+
return newPackfileIter(fs, f, t, seen, idx, nil, keepPack)
497509
}
498510

499511
func newPackfileIter(
@@ -503,6 +515,7 @@ func newPackfileIter(
503515
seen map[plumbing.Hash]struct{},
504516
index idxfile.Index,
505517
cache cache.Object,
518+
keepPack bool,
506519
) (storer.EncodedObjectIter, error) {
507520
var p *packfile.Packfile
508521
if cache != nil {
@@ -517,9 +530,10 @@ func newPackfileIter(
517530
}
518531

519532
return &packfileIter{
520-
pack: f,
521-
iter: iter,
522-
seen: seen,
533+
pack: f,
534+
iter: iter,
535+
seen: seen,
536+
keepPack: keepPack,
523537
}, nil
524538
}
525539

@@ -557,7 +571,9 @@ func (iter *packfileIter) ForEach(cb func(plumbing.EncodedObject) error) error {
557571

558572
func (iter *packfileIter) Close() {
559573
iter.iter.Close()
560-
_ = iter.pack.Close()
574+
if !iter.keepPack {
575+
_ = iter.pack.Close()
576+
}
561577
}
562578

563579
type objectsIter struct {

storage/filesystem/object_test.go

+40-4
Original file line numberDiff line numberDiff line change
@@ -153,18 +153,54 @@ func (s *FsSuite) TestPackfileIter(c *C) {
153153
idxf, err := dg.ObjectPackIdx(h)
154154
c.Assert(err, IsNil)
155155

156-
iter, err := NewPackfileIter(fs, f, idxf, t)
156+
iter, err := NewPackfileIter(fs, f, idxf, t, false)
157157
c.Assert(err, IsNil)
158+
158159
err = iter.ForEach(func(o plumbing.EncodedObject) error {
159160
c.Assert(o.Type(), Equals, t)
160161
return nil
161162
})
162-
163163
c.Assert(err, IsNil)
164164
}
165165
}
166166
})
167+
}
168+
169+
func (s *FsSuite) TestPackfileIterKeepDescriptors(c *C) {
170+
fixtures.ByTag(".git").Test(c, func(f *fixtures.Fixture) {
171+
fs := f.DotGit()
172+
ops := dotgit.Options{KeepDescriptors: true}
173+
dg := dotgit.NewWithOptions(fs, ops)
174+
175+
for _, t := range objectTypes {
176+
ph, err := dg.ObjectPacks()
177+
c.Assert(err, IsNil)
178+
179+
for _, h := range ph {
180+
f, err := dg.ObjectPack(h)
181+
c.Assert(err, IsNil)
182+
183+
idxf, err := dg.ObjectPackIdx(h)
184+
c.Assert(err, IsNil)
167185

186+
iter, err := NewPackfileIter(fs, f, idxf, t, true)
187+
c.Assert(err, IsNil)
188+
189+
err = iter.ForEach(func(o plumbing.EncodedObject) error {
190+
c.Assert(o.Type(), Equals, t)
191+
return nil
192+
})
193+
c.Assert(err, IsNil)
194+
195+
// test twice to check that packfiles are not closed
196+
err = iter.ForEach(func(o plumbing.EncodedObject) error {
197+
c.Assert(o.Type(), Equals, t)
198+
return nil
199+
})
200+
c.Assert(err, IsNil)
201+
}
202+
}
203+
})
168204
}
169205

170206
func BenchmarkPackfileIter(b *testing.B) {
@@ -201,7 +237,7 @@ func BenchmarkPackfileIter(b *testing.B) {
201237
b.Fatal(err)
202238
}
203239

204-
iter, err := NewPackfileIter(fs, f, idxf, t)
240+
iter, err := NewPackfileIter(fs, f, idxf, t, false)
205241
if err != nil {
206242
b.Fatal(err)
207243
}
@@ -257,7 +293,7 @@ func BenchmarkPackfileIterReadContent(b *testing.B) {
257293
b.Fatal(err)
258294
}
259295

260-
iter, err := NewPackfileIter(fs, f, idxf, t)
296+
iter, err := NewPackfileIter(fs, f, idxf, t, false)
261297
if err != nil {
262298
b.Fatal(err)
263299
}

0 commit comments

Comments
 (0)