diff options
author | Santiago M. Mola <santi@mola.io> | 2017-07-25 10:08:36 +0200 |
---|---|---|
committer | Santiago M. Mola <santi@mola.io> | 2017-07-26 10:56:59 +0200 |
commit | c64eb817d5e5cbaec10dea1342e1ec95721e886b (patch) | |
tree | 952839005580551bf9042ded89e2dcda56d779fc /plumbing/format/packfile/index.go | |
parent | fbf2a4ab4588c78e3d9d0265dba774ae6b388b5f (diff) | |
download | go-git-c64eb817d5e5cbaec10dea1342e1ec95721e886b.tar.gz |
packfile: create packfile.Index and reuse it
There was an internal type (i.e. storage/filesystem.idx) to
use as in-memory index for packfiles. This was not convenient
to reuse in the packfile.
This commit creates a new representation (format/packfile.Index)
that can be converted to and from idxfile.Idxfile.
A packfile.Index now contains the functionality that was scattered
on storage/filesystem.idx and packfile.Decoder's internals.
storage/filesystem now reuses packfile.Index instances and this
also results in higher cache hit ratios when resolving deltas.
Diffstat (limited to 'plumbing/format/packfile/index.go')
-rw-r--r-- | plumbing/format/packfile/index.go | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/plumbing/format/packfile/index.go b/plumbing/format/packfile/index.go new file mode 100644 index 0000000..2c5f98f --- /dev/null +++ b/plumbing/format/packfile/index.go @@ -0,0 +1,82 @@ +package packfile + +import ( + "gopkg.in/src-d/go-git.v4/plumbing" + "gopkg.in/src-d/go-git.v4/plumbing/format/idxfile" +) + +// Index is an in-memory representation of a packfile index. +// This uses idxfile.Idxfile under the hood to obtain indexes from .idx files +// or to store them. +type Index struct { + byHash map[plumbing.Hash]*idxfile.Entry + byOffset map[uint64]*idxfile.Entry +} + +// NewIndex creates a new empty index with the given size. Size is a hint and +// can be 0. It is recommended to set it to the number of objects to be indexed +// if it is known beforehand (e.g. reading from a packfile). +func NewIndex(size int) *Index { + return &Index{ + byHash: make(map[plumbing.Hash]*idxfile.Entry, size), + byOffset: make(map[uint64]*idxfile.Entry, size), + } +} + +// NewIndexFromIdxFile creates a new Index from an idxfile.IdxFile. +func NewIndexFromIdxFile(idxf *idxfile.Idxfile) *Index { + idx := &Index{ + byHash: make(map[plumbing.Hash]*idxfile.Entry, idxf.ObjectCount), + byOffset: make(map[uint64]*idxfile.Entry, idxf.ObjectCount), + } + for _, e := range idxf.Entries { + idx.add(e) + } + + return idx +} + +// Add adds a new Entry with the given values to the index. +func (idx *Index) Add(h plumbing.Hash, offset uint64, crc32 uint32) { + e := idxfile.Entry{ + Hash: h, + Offset: offset, + CRC32: crc32, + } + idx.add(&e) +} + +func (idx *Index) add(e *idxfile.Entry) { + idx.byHash[e.Hash] = e + idx.byOffset[e.Offset] = e +} + +// LookupHash looks an entry up by its hash. An idxfile.Entry is returned and +// a bool, which is true if it was found or false if it wasn't. +func (idx *Index) LookupHash(h plumbing.Hash) (*idxfile.Entry, bool) { + e, ok := idx.byHash[h] + return e, ok +} + +// LookupHash looks an entry up by its offset in the packfile. An idxfile.Entry +// is returned and a bool, which is true if it was found or false if it wasn't. +func (idx *Index) LookupOffset(offset uint64) (*idxfile.Entry, bool) { + e, ok := idx.byOffset[offset] + return e, ok +} + +// Size returns the number of entries in the index. +func (idx *Index) Size() int { + return len(idx.byHash) +} + +// ToIdxFile converts the index to an idxfile.Idxfile, which can then be used +// to serialize. +func (idx *Index) ToIdxFile() *idxfile.Idxfile { + idxf := idxfile.NewIdxfile() + for _, e := range idx.byHash { + idxf.Entries = append(idxf.Entries, e) + } + + return idxf +} |