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

Commit f62cd8e

Browse files
authored
Merge pull request #1025 from mcuadros/eoie
plumbing: format/index: support for EOIE extension
2 parents 2431109 + b99653a commit f62cd8e

File tree

4 files changed

+122
-4
lines changed

4 files changed

+122
-4
lines changed

plumbing/format/index/decoder.go

+25
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,17 @@ func (d *Decoder) readExtension(idx *Index, header []byte) error {
261261
if err := d.Decode(idx.ResolveUndo); err != nil {
262262
return err
263263
}
264+
case bytes.Equal(header, endOfIndexEntryExtSignature):
265+
r, err := d.getExtensionReader()
266+
if err != nil {
267+
return err
268+
}
269+
270+
idx.EndOfIndexEntry = &EndOfIndexEntry{}
271+
d := &endOfIndexEntryDecoder{r}
272+
if err := d.Decode(idx.EndOfIndexEntry); err != nil {
273+
return err
274+
}
264275
default:
265276
return errUnknownExtension
266277
}
@@ -449,3 +460,17 @@ func (d *resolveUndoDecoder) readStage(e *ResolveUndoEntry, s Stage) error {
449460

450461
return nil
451462
}
463+
464+
type endOfIndexEntryDecoder struct {
465+
r io.Reader
466+
}
467+
468+
func (d *endOfIndexEntryDecoder) Decode(e *EndOfIndexEntry) error {
469+
var err error
470+
e.Offset, err = binary.ReadUint32(d.r)
471+
if err != nil {
472+
return err
473+
}
474+
475+
return binary.Read(d.r, &e.Hash)
476+
}

plumbing/format/index/decoder_test.go

+16
Original file line numberDiff line numberDiff line change
@@ -202,3 +202,19 @@ func (s *IndexSuite) TestDecodeV4(c *C) {
202202
c.Assert(idx.Entries[6].IntentToAdd, Equals, true)
203203
c.Assert(idx.Entries[6].SkipWorktree, Equals, false)
204204
}
205+
206+
func (s *IndexSuite) TestDecodeEndOfIndexEntry(c *C) {
207+
f, err := fixtures.Basic().ByTag("end-of-index-entry").One().DotGit().Open("index")
208+
c.Assert(err, IsNil)
209+
defer func() { c.Assert(f.Close(), IsNil) }()
210+
211+
idx := &Index{}
212+
d := NewDecoder(f)
213+
err = d.Decode(idx)
214+
c.Assert(err, IsNil)
215+
216+
c.Assert(idx.Version, Equals, uint32(2))
217+
c.Assert(idx.EndOfIndexEntry, NotNil)
218+
c.Assert(idx.EndOfIndexEntry.Offset, Equals, uint32(716))
219+
c.Assert(idx.EndOfIndexEntry.Hash.String(), Equals, "922e89d9ffd7cefce93a211615b2053c0f42bd78")
220+
}

plumbing/format/index/doc.go

+60-1
Original file line numberDiff line numberDiff line change
@@ -297,5 +297,64 @@
297297
// in the previous ewah bitmap.
298298
//
299299
// - One NUL.
300-
// Source https://www.kernel.org/pub/software/scm/git/docs/technical/index-format.txt
300+
//
301+
// == File System Monitor cache
302+
//
303+
// The file system monitor cache tracks files for which the core.fsmonitor
304+
// hook has told us about changes. The signature for this extension is
305+
// { 'F', 'S', 'M', 'N' }.
306+
//
307+
// The extension starts with
308+
//
309+
// - 32-bit version number: the current supported version is 1.
310+
//
311+
// - 64-bit time: the extension data reflects all changes through the given
312+
// time which is stored as the nanoseconds elapsed since midnight,
313+
// January 1, 1970.
314+
//
315+
// - 32-bit bitmap size: the size of the CE_FSMONITOR_VALID bitmap.
316+
//
317+
// - An ewah bitmap, the n-th bit indicates whether the n-th index entry
318+
// is not CE_FSMONITOR_VALID.
319+
//
320+
// == End of Index Entry
321+
//
322+
// The End of Index Entry (EOIE) is used to locate the end of the variable
323+
// length index entries and the begining of the extensions. Code can take
324+
// advantage of this to quickly locate the index extensions without having
325+
// to parse through all of the index entries.
326+
//
327+
// Because it must be able to be loaded before the variable length cache
328+
// entries and other index extensions, this extension must be written last.
329+
// The signature for this extension is { 'E', 'O', 'I', 'E' }.
330+
//
331+
// The extension consists of:
332+
//
333+
// - 32-bit offset to the end of the index entries
334+
//
335+
// - 160-bit SHA-1 over the extension types and their sizes (but not
336+
// their contents). E.g. if we have "TREE" extension that is N-bytes
337+
// long, "REUC" extension that is M-bytes long, followed by "EOIE",
338+
// then the hash would be:
339+
//
340+
// SHA-1("TREE" + <binary representation of N> +
341+
// "REUC" + <binary representation of M>)
342+
//
343+
// == Index Entry Offset Table
344+
//
345+
// The Index Entry Offset Table (IEOT) is used to help address the CPU
346+
// cost of loading the index by enabling multi-threading the process of
347+
// converting cache entries from the on-disk format to the in-memory format.
348+
// The signature for this extension is { 'I', 'E', 'O', 'T' }.
349+
//
350+
// The extension consists of:
351+
//
352+
// - 32-bit version (currently 1)
353+
//
354+
// - A number of index offset entries each consisting of:
355+
//
356+
// - 32-bit offset from the begining of the file to the first cache entry
357+
// in this block of entries.
358+
//
359+
// - 32-bit count of cache entries in this blockpackage index
301360
package index

plumbing/format/index/index.go

+21-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ var (
1818
// ErrEntryNotFound is returned by Index.Entry, if an entry is not found.
1919
ErrEntryNotFound = errors.New("entry not found")
2020

21-
indexSignature = []byte{'D', 'I', 'R', 'C'}
22-
treeExtSignature = []byte{'T', 'R', 'E', 'E'}
23-
resolveUndoExtSignature = []byte{'R', 'E', 'U', 'C'}
21+
indexSignature = []byte{'D', 'I', 'R', 'C'}
22+
treeExtSignature = []byte{'T', 'R', 'E', 'E'}
23+
resolveUndoExtSignature = []byte{'R', 'E', 'U', 'C'}
24+
endOfIndexEntryExtSignature = []byte{'E', 'O', 'I', 'E'}
2425
)
2526

2627
// Stage during merge
@@ -50,6 +51,8 @@ type Index struct {
5051
Cache *Tree
5152
// ResolveUndo represents the 'Resolve undo' extension
5253
ResolveUndo *ResolveUndo
54+
// EndOfIndexEntry represents the 'End of Index Entry' extension
55+
EndOfIndexEntry *EndOfIndexEntry
5356
}
5457

5558
// Add creates a new Entry and returns it. The caller should first check that
@@ -193,3 +196,18 @@ type ResolveUndoEntry struct {
193196
Path string
194197
Stages map[Stage]plumbing.Hash
195198
}
199+
200+
// EndOfIndexEntry is the End of Index Entry (EOIE) is used to locate the end of
201+
// the variable length index entries and the begining of the extensions. Code
202+
// can take advantage of this to quickly locate the index extensions without
203+
// having to parse through all of the index entries.
204+
//
205+
// Because it must be able to be loaded before the variable length cache
206+
// entries and other index extensions, this extension must be written last.
207+
type EndOfIndexEntry struct {
208+
// Offset to the end of the index entries
209+
Offset uint32
210+
// Hash is a SHA-1 over the extension types and their sizes (but not
211+
// their contents).
212+
Hash plumbing.Hash
213+
}

0 commit comments

Comments
 (0)