Skip to content

Commit

Permalink
Support v3 index
Browse files Browse the repository at this point in the history
Currently the index encoder does not support the v3 index format. This
change adds support to the encoder. This helps to unlock sparse
checkout.
  • Loading branch information
John Cai committed Nov 5, 2021
1 parent 3211a7a commit a04ddf5
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 14 deletions.
34 changes: 25 additions & 9 deletions plumbing/format/index/encoder.go
Expand Up @@ -14,7 +14,7 @@ import (

var (
// EncodeVersionSupported is the range of supported index versions
EncodeVersionSupported uint32 = 2
EncodeVersionSupported uint32 = 3

// ErrInvalidTimestamp is returned by Encode if a Index with a Entry with
// negative timestamp values
Expand All @@ -36,9 +36,9 @@ func NewEncoder(w io.Writer) *Encoder {

// Encode writes the Index to the stream of the encoder.
func (e *Encoder) Encode(idx *Index) error {
// TODO: support versions v3 and v4
// TODO: support v4
// TODO: support extensions
if idx.Version != EncodeVersionSupported {
if idx.Version > EncodeVersionSupported {
return ErrUnsupportedVersion
}

Expand Down Expand Up @@ -68,8 +68,12 @@ func (e *Encoder) encodeEntries(idx *Index) error {
if err := e.encodeEntry(entry); err != nil {
return err
}
entryLength := entryHeaderLength
if entry.IntentToAdd || entry.SkipWorktree {
entryLength += 2
}

wrote := entryHeaderLength + len(entry.Name)
wrote := entryLength + len(entry.Name)
if err := e.padEntry(wrote); err != nil {
return err
}
Expand All @@ -79,10 +83,6 @@ func (e *Encoder) encodeEntries(idx *Index) error {
}

func (e *Encoder) encodeEntry(entry *Entry) error {
if entry.IntentToAdd || entry.SkipWorktree {
return ErrUnsupportedVersion
}

sec, nsec, err := e.timeToUint32(&entry.CreatedAt)
if err != nil {
return err
Expand Down Expand Up @@ -110,9 +110,25 @@ func (e *Encoder) encodeEntry(entry *Entry) error {
entry.GID,
entry.Size,
entry.Hash[:],
flags,
}

flagsFlow := []interface{}{flags}

if entry.IntentToAdd || entry.SkipWorktree {
var extendedFlags uint16

if entry.IntentToAdd {
extendedFlags |= intentToAddMask
}
if entry.SkipWorktree {
extendedFlags |= skipWorkTreeMask
}

flagsFlow = []interface{}{flags | entryExtended, extendedFlags}
}

flow = append(flow, flagsFlow...)

if err := binary.Write(e.w, flow...); err != nil {
return err
}
Expand Down
26 changes: 21 additions & 5 deletions plumbing/format/index/encoder_test.go
Expand Up @@ -57,7 +57,7 @@ func (s *IndexSuite) TestEncode(c *C) {
}

func (s *IndexSuite) TestEncodeUnsupportedVersion(c *C) {
idx := &Index{Version: 3}
idx := &Index{Version: 4}

buf := bytes.NewBuffer(nil)
e := NewEncoder(buf)
Expand All @@ -67,24 +67,40 @@ func (s *IndexSuite) TestEncodeUnsupportedVersion(c *C) {

func (s *IndexSuite) TestEncodeWithIntentToAddUnsupportedVersion(c *C) {
idx := &Index{
Version: 2,
Version: 3,
Entries: []*Entry{{IntentToAdd: true}},
}

buf := bytes.NewBuffer(nil)
e := NewEncoder(buf)
err := e.Encode(idx)
c.Assert(err, Equals, ErrUnsupportedVersion)
c.Assert(err, IsNil)

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

c.Assert(cmp.Equal(idx, output), Equals, true)
c.Assert(output.Entries[0].IntentToAdd, Equals, true)
}

func (s *IndexSuite) TestEncodeWithSkipWorktreeUnsupportedVersion(c *C) {
idx := &Index{
Version: 2,
Version: 3,
Entries: []*Entry{{SkipWorktree: true}},
}

buf := bytes.NewBuffer(nil)
e := NewEncoder(buf)
err := e.Encode(idx)
c.Assert(err, Equals, ErrUnsupportedVersion)
c.Assert(err, IsNil)

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

c.Assert(cmp.Equal(idx, output), Equals, true)
c.Assert(output.Entries[0].SkipWorktree, Equals, true)
}

0 comments on commit a04ddf5

Please sign in to comment.