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

Commit cdfa0bb

Browse files
authored
Merge pull request #927 from jfontan/fix/iterate-objects-by-offset
plumbing/idxfile: object iterators returns entries in offset order
2 parents cc27d4a + f84c6b1 commit cdfa0bb

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)