@@ -55,7 +55,8 @@ type MemoryIndex struct {
5555 PackfileChecksum [20 ]byte
5656 IdxChecksum [20 ]byte
5757
58- offsetHash map [int64 ]plumbing.Hash
58+ offsetHash map [int64 ]plumbing.Hash
59+ offsetHashIsFull bool
5960}
6061
6162var _ Index = (* MemoryIndex )(nil )
@@ -121,7 +122,17 @@ func (idx *MemoryIndex) FindOffset(h plumbing.Hash) (int64, error) {
121122 return 0 , plumbing .ErrObjectNotFound
122123 }
123124
124- return idx .getOffset (k , i )
125+ offset , err := idx .getOffset (k , i )
126+
127+ if ! idx .offsetHashIsFull {
128+ // Save the offset for reverse lookup
129+ if idx .offsetHash == nil {
130+ idx .offsetHash = make (map [int64 ]plumbing.Hash )
131+ }
132+ idx .offsetHash [offset ] = h
133+ }
134+
135+ return offset , err
125136}
126137
127138const isO64Mask = uint64 (1 ) << 31
@@ -167,14 +178,24 @@ func (idx *MemoryIndex) getCRC32(firstLevel, secondLevel int) (uint32, error) {
167178
168179// FindHash implements the Index interface.
169180func (idx * MemoryIndex ) FindHash (o int64 ) (plumbing.Hash , error ) {
181+ var hash plumbing.Hash
182+ var ok bool
183+
184+ if idx .offsetHash != nil {
185+ if hash , ok = idx .offsetHash [o ]; ok {
186+ return hash , nil
187+ }
188+ }
189+
170190 // Lazily generate the reverse offset/hash map if required.
171- if idx .offsetHash == nil {
191+ if ! idx . offsetHashIsFull || idx .offsetHash == nil {
172192 if err := idx .genOffsetHash (); err != nil {
173193 return plumbing .ZeroHash , err
174194 }
195+
196+ hash , ok = idx .offsetHash [o ]
175197 }
176198
177- hash , ok := idx .offsetHash [o ]
178199 if ! ok {
179200 return plumbing .ZeroHash , plumbing .ErrObjectNotFound
180201 }
@@ -190,6 +211,7 @@ func (idx *MemoryIndex) genOffsetHash() error {
190211 }
191212
192213 idx .offsetHash = make (map [int64 ]plumbing.Hash , count )
214+ idx .offsetHashIsFull = true
193215
194216 iter , err := idx .Entries ()
195217 if err != nil {
0 commit comments