Skip to content

Commit

Permalink
Merge pull request src-d#1025 from mcuadros/eoie
Browse files Browse the repository at this point in the history
plumbing: format/index: support for EOIE extension
  • Loading branch information
mcuadros committed Nov 19, 2018
2 parents 2431109 + b99653a commit f62cd8e
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 4 deletions.
25 changes: 25 additions & 0 deletions plumbing/format/index/decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,17 @@ func (d *Decoder) readExtension(idx *Index, header []byte) error {
if err := d.Decode(idx.ResolveUndo); err != nil {
return err
}
case bytes.Equal(header, endOfIndexEntryExtSignature):
r, err := d.getExtensionReader()
if err != nil {
return err
}

idx.EndOfIndexEntry = &EndOfIndexEntry{}
d := &endOfIndexEntryDecoder{r}
if err := d.Decode(idx.EndOfIndexEntry); err != nil {
return err
}
default:
return errUnknownExtension
}
Expand Down Expand Up @@ -449,3 +460,17 @@ func (d *resolveUndoDecoder) readStage(e *ResolveUndoEntry, s Stage) error {

return nil
}

type endOfIndexEntryDecoder struct {
r io.Reader
}

func (d *endOfIndexEntryDecoder) Decode(e *EndOfIndexEntry) error {
var err error
e.Offset, err = binary.ReadUint32(d.r)
if err != nil {
return err
}

return binary.Read(d.r, &e.Hash)
}
16 changes: 16 additions & 0 deletions plumbing/format/index/decoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,3 +202,19 @@ func (s *IndexSuite) TestDecodeV4(c *C) {
c.Assert(idx.Entries[6].IntentToAdd, Equals, true)
c.Assert(idx.Entries[6].SkipWorktree, Equals, false)
}

func (s *IndexSuite) TestDecodeEndOfIndexEntry(c *C) {
f, err := fixtures.Basic().ByTag("end-of-index-entry").One().DotGit().Open("index")
c.Assert(err, IsNil)
defer func() { c.Assert(f.Close(), IsNil) }()

idx := &Index{}
d := NewDecoder(f)
err = d.Decode(idx)
c.Assert(err, IsNil)

c.Assert(idx.Version, Equals, uint32(2))
c.Assert(idx.EndOfIndexEntry, NotNil)
c.Assert(idx.EndOfIndexEntry.Offset, Equals, uint32(716))
c.Assert(idx.EndOfIndexEntry.Hash.String(), Equals, "922e89d9ffd7cefce93a211615b2053c0f42bd78")
}
61 changes: 60 additions & 1 deletion plumbing/format/index/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,5 +297,64 @@
// in the previous ewah bitmap.
//
// - One NUL.
// Source https://www.kernel.org/pub/software/scm/git/docs/technical/index-format.txt
//
// == File System Monitor cache
//
// The file system monitor cache tracks files for which the core.fsmonitor
// hook has told us about changes. The signature for this extension is
// { 'F', 'S', 'M', 'N' }.
//
// The extension starts with
//
// - 32-bit version number: the current supported version is 1.
//
// - 64-bit time: the extension data reflects all changes through the given
// time which is stored as the nanoseconds elapsed since midnight,
// January 1, 1970.
//
// - 32-bit bitmap size: the size of the CE_FSMONITOR_VALID bitmap.
//
// - An ewah bitmap, the n-th bit indicates whether the n-th index entry
// is not CE_FSMONITOR_VALID.
//
// == End of Index Entry
//
// The End of Index Entry (EOIE) is used to locate the end of the variable
// length index entries and the begining of the extensions. Code can take
// advantage of this to quickly locate the index extensions without having
// to parse through all of the index entries.
//
// Because it must be able to be loaded before the variable length cache
// entries and other index extensions, this extension must be written last.
// The signature for this extension is { 'E', 'O', 'I', 'E' }.
//
// The extension consists of:
//
// - 32-bit offset to the end of the index entries
//
// - 160-bit SHA-1 over the extension types and their sizes (but not
// their contents). E.g. if we have "TREE" extension that is N-bytes
// long, "REUC" extension that is M-bytes long, followed by "EOIE",
// then the hash would be:
//
// SHA-1("TREE" + <binary representation of N> +
// "REUC" + <binary representation of M>)
//
// == Index Entry Offset Table
//
// The Index Entry Offset Table (IEOT) is used to help address the CPU
// cost of loading the index by enabling multi-threading the process of
// converting cache entries from the on-disk format to the in-memory format.
// The signature for this extension is { 'I', 'E', 'O', 'T' }.
//
// The extension consists of:
//
// - 32-bit version (currently 1)
//
// - A number of index offset entries each consisting of:
//
// - 32-bit offset from the begining of the file to the first cache entry
// in this block of entries.
//
// - 32-bit count of cache entries in this blockpackage index
package index
24 changes: 21 additions & 3 deletions plumbing/format/index/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ var (
// ErrEntryNotFound is returned by Index.Entry, if an entry is not found.
ErrEntryNotFound = errors.New("entry not found")

indexSignature = []byte{'D', 'I', 'R', 'C'}
treeExtSignature = []byte{'T', 'R', 'E', 'E'}
resolveUndoExtSignature = []byte{'R', 'E', 'U', 'C'}
indexSignature = []byte{'D', 'I', 'R', 'C'}
treeExtSignature = []byte{'T', 'R', 'E', 'E'}
resolveUndoExtSignature = []byte{'R', 'E', 'U', 'C'}
endOfIndexEntryExtSignature = []byte{'E', 'O', 'I', 'E'}
)

// Stage during merge
Expand Down Expand Up @@ -50,6 +51,8 @@ type Index struct {
Cache *Tree
// ResolveUndo represents the 'Resolve undo' extension
ResolveUndo *ResolveUndo
// EndOfIndexEntry represents the 'End of Index Entry' extension
EndOfIndexEntry *EndOfIndexEntry
}

// Add creates a new Entry and returns it. The caller should first check that
Expand Down Expand Up @@ -193,3 +196,18 @@ type ResolveUndoEntry struct {
Path string
Stages map[Stage]plumbing.Hash
}

// EndOfIndexEntry is the End of Index Entry (EOIE) is used to locate the end of
// the variable length index entries and the begining of the extensions. Code
// can take advantage of this to quickly locate the index extensions without
// having to parse through all of the index entries.
//
// Because it must be able to be loaded before the variable length cache
// entries and other index extensions, this extension must be written last.
type EndOfIndexEntry struct {
// Offset to the end of the index entries
Offset uint32
// Hash is a SHA-1 over the extension types and their sizes (but not
// their contents).
Hash plumbing.Hash
}

0 comments on commit f62cd8e

Please sign in to comment.