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

Commit f84c6b1

Browse files
committed
plumbing/idxfile: object iterators returns entries in offset order
In the latest change the order was changed from offset order in packfiles to hash order. This makes reading all the objects not as efficient as before. It also created problems when the previous order was expected. Also added EntriesByOffset to indexes. Signed-off-by: Javi Fontan <[email protected]>
1 parent cc27d4a commit f84c6b1

File tree

3 files changed

+85
-1
lines changed

3 files changed

+85
-1
lines changed

plumbing/format/idxfile/idxfile.go

+69
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package idxfile
33
import (
44
"bytes"
55
"io"
6+
"sort"
67

78
"gopkg.in/src-d/go-git.v4/plumbing"
89
"gopkg.in/src-d/go-git.v4/utils/binary"
@@ -34,6 +35,9 @@ type Index interface {
3435
Count() (int64, error)
3536
// Entries returns an iterator to retrieve all index entries.
3637
Entries() (EntryIter, error)
38+
// EntriesByOffset returns an iterator to retrieve all index entries ordered
39+
// by offset.
40+
EntriesByOffset() (EntryIter, error)
3741
}
3842

3943
// MemoryIndex is the in memory representation of an idx file.
@@ -215,6 +219,36 @@ func (idx *MemoryIndex) Entries() (EntryIter, error) {
215219
return &idxfileEntryIter{idx, 0, 0, 0}, nil
216220
}
217221

222+
// EntriesByOffset implements the Index interface.
223+
func (idx *MemoryIndex) EntriesByOffset() (EntryIter, error) {
224+
count, err := idx.Count()
225+
if err != nil {
226+
return nil, err
227+
}
228+
229+
iter := &idxfileEntryOffsetIter{
230+
entries: make(entriesByOffset, count),
231+
}
232+
233+
entries, err := idx.Entries()
234+
if err != nil {
235+
return nil, err
236+
}
237+
238+
for pos := 0; int64(pos) < count; pos++ {
239+
entry, err := entries.Next()
240+
if err != nil {
241+
return nil, err
242+
}
243+
244+
iter.entries[pos] = entry
245+
}
246+
247+
sort.Sort(iter.entries)
248+
249+
return iter, nil
250+
}
251+
218252
// EntryIter is an iterator that will return the entries in a packfile index.
219253
type EntryIter interface {
220254
// Next returns the next entry in the packfile index.
@@ -276,3 +310,38 @@ type Entry struct {
276310
CRC32 uint32
277311
Offset uint64
278312
}
313+
314+
type idxfileEntryOffsetIter struct {
315+
entries entriesByOffset
316+
pos int
317+
}
318+
319+
func (i *idxfileEntryOffsetIter) Next() (*Entry, error) {
320+
if i.pos >= len(i.entries) {
321+
return nil, io.EOF
322+
}
323+
324+
entry := i.entries[i.pos]
325+
i.pos++
326+
327+
return entry, nil
328+
}
329+
330+
func (i *idxfileEntryOffsetIter) Close() error {
331+
i.pos = len(i.entries) + 1
332+
return nil
333+
}
334+
335+
type entriesByOffset []*Entry
336+
337+
func (o entriesByOffset) Len() int {
338+
return len(o)
339+
}
340+
341+
func (o entriesByOffset) Less(i int, j int) bool {
342+
return o[i].Offset < o[j].Offset
343+
}
344+
345+
func (o entriesByOffset) Swap(i int, j int) {
346+
o[i], o[j] = o[j], o[i]
347+
}

plumbing/format/idxfile/idxfile_test.go

+15
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,21 @@ func (s *IndexSuite) TestFindHash(c *C) {
115115
}
116116
}
117117

118+
func (s *IndexSuite) TestEntriesByOffset(c *C) {
119+
idx, err := fixtureIndex()
120+
c.Assert(err, IsNil)
121+
122+
entries, err := idx.EntriesByOffset()
123+
c.Assert(err, IsNil)
124+
125+
for _, pos := range fixtureOffsets {
126+
e, err := entries.Next()
127+
c.Assert(err, IsNil)
128+
129+
c.Assert(e.Offset, Equals, uint64(pos))
130+
}
131+
}
132+
118133
var fixtureHashes = []plumbing.Hash{
119134
plumbing.NewHash("303953e5aa461c203a324821bc1717f9b4fff895"),
120135
plumbing.NewHash("5296768e3d9f661387ccbff18c4dea6c997fd78c"),

plumbing/format/packfile/packfile.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,7 @@ func (p *Packfile) GetByType(typ plumbing.ObjectType) (storer.EncodedObjectIter,
394394
plumbing.TreeObject,
395395
plumbing.CommitObject,
396396
plumbing.TagObject:
397-
entries, err := p.Entries()
397+
entries, err := p.EntriesByOffset()
398398
if err != nil {
399399
return nil, err
400400
}

0 commit comments

Comments
 (0)