package v2 import ( "math" "github.com/go-git/go-git/v5/plumbing" ) // MemoryIndex provides a way to build the commit-graph in memory // for later encoding to file. type MemoryIndex struct { commitData []commitData indexMap map[plumbing.Hash]uint32 hasGenerationV2 bool } type commitData struct { Hash plumbing.Hash *CommitData } // NewMemoryIndex creates in-memory commit graph representation func NewMemoryIndex() *MemoryIndex { return &MemoryIndex{ indexMap: make(map[plumbing.Hash]uint32), hasGenerationV2: true, } } // GetIndexByHash gets the index in the commit graph from commit hash, if available func (mi *MemoryIndex) GetIndexByHash(h plumbing.Hash) (uint32, error) { i, ok := mi.indexMap[h] if ok { return i, nil } return 0, plumbing.ErrObjectNotFound } // GetHashByIndex gets the hash given an index in the commit graph func (mi *MemoryIndex) GetHashByIndex(i uint32) (plumbing.Hash, error) { if i >= uint32(len(mi.commitData)) { return plumbing.ZeroHash, plumbing.ErrObjectNotFound } return mi.commitData[i].Hash, nil } // GetCommitDataByIndex gets the commit node from the commit graph using index // obtained from child node, if available func (mi *MemoryIndex) GetCommitDataByIndex(i uint32) (*CommitData, error) { if i >= uint32(len(mi.commitData)) { return nil, plumbing.ErrObjectNotFound } commitData := mi.commitData[i] // Map parent hashes to parent indexes if commitData.ParentIndexes == nil { parentIndexes := make([]uint32, len(commitData.ParentHashes)) for i, parentHash := range commitData.ParentHashes { var err error if parentIndexes[i], err = mi.GetIndexByHash(parentHash); err != nil { return nil, err } } commitData.ParentIndexes = parentIndexes } return commitData.CommitData, nil } // Hashes returns all the hashes that are available in the index func (mi *MemoryIndex) Hashes() []plumbing.Hash { hashes := make([]plumbing.Hash, 0, len(mi.indexMap)) for k := range mi.indexMap { hashes = append(hashes, k) } return hashes } // Add adds new node to the memory index func (mi *MemoryIndex) Add(hash plumbing.Hash, data *CommitData) { // The parent indexes are calculated lazily in GetNodeByIndex // which allows adding nodes out of order as long as all parents // are eventually resolved data.ParentIndexes = nil mi.indexMap[hash] = uint32(len(mi.commitData)) mi.commitData = append(mi.commitData, commitData{Hash: hash, CommitData: data}) if data.GenerationV2 == math.MaxUint64 { // if GenerationV2 is not available reset it to zero data.GenerationV2 = 0 } mi.hasGenerationV2 = mi.hasGenerationV2 && data.GenerationV2 != 0 } func (mi *MemoryIndex) HasGenerationV2() bool { return mi.hasGenerationV2 } // Close closes the index func (mi *MemoryIndex) Close() error { return nil } func (mi *MemoryIndex) MaximumNumberOfHashes() uint32 { return uint32(len(mi.indexMap)) }