aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plumbing/format/index/decoder.go70
-rw-r--r--storage/filesystem/index.go2
2 files changed, 37 insertions, 35 deletions
diff --git a/plumbing/format/index/decoder.go b/plumbing/format/index/decoder.go
index 6778cf7..6f32418 100644
--- a/plumbing/format/index/decoder.go
+++ b/plumbing/format/index/decoder.go
@@ -39,6 +39,7 @@ const (
// A Decoder reads and decodes index files from an input stream.
type Decoder struct {
+ buf *bufio.Reader
r io.Reader
hash hash.Hash
lastEntry *Entry
@@ -49,8 +50,10 @@ type Decoder struct {
// NewDecoder returns a new decoder that reads from r.
func NewDecoder(r io.Reader) *Decoder {
h := hash.New(hash.CryptoType)
+ buf := bufio.NewReader(r)
return &Decoder{
- r: io.TeeReader(r, h),
+ buf: buf,
+ r: io.TeeReader(buf, h),
hash: h,
extReader: bufio.NewReader(nil),
}
@@ -210,64 +213,64 @@ func (d *Decoder) readExtensions(idx *Index) error {
// count that they are not supported by jgit or libgit
var expected []byte
+ var peeked []byte
var err error
- var header [4]byte
+ // we should always be able to peek for 4 bytes (header) + 4 bytes (extlen) + final hash
+ // if this fails, we know that we're at the end of the index
+ peekLen := 4 + 4 + d.hash.Size()
+
for {
expected = d.hash.Sum(nil)
-
- var n int
- if n, err = io.ReadFull(d.r, header[:]); err != nil {
- if n == 0 {
- err = io.EOF
- }
-
+ peeked, err = d.buf.Peek(peekLen)
+ if len(peeked) < peekLen {
+ // there can't be an extension at this point, so let's bail out
+ err = nil
break
}
+ if err != nil {
+ return err
+ }
- err = d.readExtension(idx, header[:])
+ err = d.readExtension(idx)
if err != nil {
break
}
}
- if err != errUnknownExtension {
+ if err != nil && err != errUnknownExtension {
return err
}
- return d.readChecksum(expected, header)
+ return d.readChecksum(expected)
}
-func (d *Decoder) readExtension(idx *Index, header []byte) error {
- switch {
- case bytes.Equal(header, treeExtSignature):
- r, err := d.getExtensionReader()
- if err != nil {
- return err
- }
+func (d *Decoder) readExtension(idx *Index) error {
+ var header [4]byte
+ if _, err := io.ReadFull(d.r, header[:]); err != nil {
+ return err
+ }
+
+ r, err := d.getExtensionReader()
+ if err != nil {
+ return err
+ }
+
+ switch {
+ case bytes.Equal(header[:], treeExtSignature):
idx.Cache = &Tree{}
d := &treeExtensionDecoder{r}
if err := d.Decode(idx.Cache); err != nil {
return err
}
- case bytes.Equal(header, resolveUndoExtSignature):
- r, err := d.getExtensionReader()
- if err != nil {
- return err
- }
-
+ case bytes.Equal(header[:], resolveUndoExtSignature):
idx.ResolveUndo = &ResolveUndo{}
d := &resolveUndoDecoder{r}
if err := d.Decode(idx.ResolveUndo); err != nil {
return err
}
- case bytes.Equal(header, endOfIndexEntryExtSignature):
- r, err := d.getExtensionReader()
- if err != nil {
- return err
- }
-
+ case bytes.Equal(header[:], endOfIndexEntryExtSignature):
idx.EndOfIndexEntry = &EndOfIndexEntry{}
d := &endOfIndexEntryDecoder{r}
if err := d.Decode(idx.EndOfIndexEntry); err != nil {
@@ -290,11 +293,10 @@ func (d *Decoder) getExtensionReader() (*bufio.Reader, error) {
return d.extReader, nil
}
-func (d *Decoder) readChecksum(expected []byte, alreadyRead [4]byte) error {
+func (d *Decoder) readChecksum(expected []byte) error {
var h plumbing.Hash
- copy(h[:4], alreadyRead[:])
- if _, err := io.ReadFull(d.r, h[4:]); err != nil {
+ if _, err := io.ReadFull(d.r, h[:]); err != nil {
return err
}
diff --git a/storage/filesystem/index.go b/storage/filesystem/index.go
index a19176f..a86ef3e 100644
--- a/storage/filesystem/index.go
+++ b/storage/filesystem/index.go
@@ -48,7 +48,7 @@ func (s *IndexStorage) Index() (i *index.Index, err error) {
defer ioutil.CheckClose(f, &err)
- d := index.NewDecoder(bufio.NewReader(f))
+ d := index.NewDecoder(f)
err = d.Decode(idx)
return idx, err
}