From 7c0ca21db6741af7735e3be332987e362393fb07 Mon Sep 17 00:00:00 2001 From: Máximo Cuadros Date: Fri, 9 Sep 2016 17:38:13 +0200 Subject: format: packfile ignores the header if not read --- formats/packfile/parser.go | 28 ++++++++++++++++++++++++++-- formats/packfile/parser_test.go | 14 ++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/formats/packfile/parser.go b/formats/packfile/parser.go index cbd8d6c..6fa2f42 100644 --- a/formats/packfile/parser.go +++ b/formats/packfile/parser.go @@ -49,7 +49,8 @@ type Scanner struct { // pendingObject is used to detect if an object has been read, or still // is waiting to be read - pendingObject *ObjectHeader + pendingObject *ObjectHeader + version, objects uint32 } // NewParser returns a new Parser that reads from the packfile represented by r. @@ -70,6 +71,10 @@ func NewScanner(r io.ReadSeeker) *Scanner { // It returns the version and the object count and performs checks on the // validity of the signature and the version fields. func (s *Scanner) Header() (version, objects uint32, err error) { + if s.version != 0 { + return s.version, s.objects, nil + } + sig, err := s.readSignature() if err != nil { if err == io.EOF { @@ -85,6 +90,7 @@ func (s *Scanner) Header() (version, objects uint32, err error) { } version, err = s.readVersion() + s.version = version if err != nil { return } @@ -95,6 +101,7 @@ func (s *Scanner) Header() (version, objects uint32, err error) { } objects, err = s.readCount() + s.objects = objects return } @@ -141,7 +148,7 @@ func (s *Scanner) readInt32() (uint32, error) { // NextObjectHeader returns the ObjectHeader for the next object in the reader func (s *Scanner) NextObjectHeader() (*ObjectHeader, error) { - if err := s.discardObjectIfNeeded(); err != nil { + if err := s.doPending(); err != nil { return nil, err } @@ -180,6 +187,18 @@ func (s *Scanner) NextObjectHeader() (*ObjectHeader, error) { return h, nil } +func (s *Scanner) doPending() error { + if s.version == 0 { + var err error + s.version, s.objects, err = s.Header() + if err != nil { + return err + } + } + + return s.discardObjectIfNeeded() +} + func (s *Scanner) discardObjectIfNeeded() error { if s.pendingObject == nil { return nil @@ -275,6 +294,11 @@ func (s *Scanner) copyObject(w io.Writer) (int64, error) { // Seek sets a new offset from start, returns the old position before the change func (s *Scanner) Seek(offset int64) (previous int64, err error) { + // if seeking we asume that you are not interested on the header + if s.version == 0 { + s.version = VersionSupported + } + previous, err = s.r.Seek(0, io.SeekCurrent) if err != nil { return -1, err diff --git a/formats/packfile/parser_test.go b/formats/packfile/parser_test.go index d746b98..2ff2887 100644 --- a/formats/packfile/parser_test.go +++ b/formats/packfile/parser_test.go @@ -26,6 +26,20 @@ func (s *ScannerSuite) TestHeader(c *C) { c.Assert(objects, Equals, uint32(31)) } +func (s *ScannerSuite) TestNextObjectHeaderWithoutHeader(c *C) { + r := fixtures.Basic().One().Packfile() + p := NewScanner(r) + + h, err := p.NextObjectHeader() + c.Assert(err, IsNil) + c.Assert(h, DeepEquals, &expectedHeadersOFS[0]) + + version, objects, err := p.Header() + c.Assert(err, IsNil) + c.Assert(version, Equals, VersionSupported) + c.Assert(objects, Equals, uint32(31)) +} + func (s *ScannerSuite) TestNextObjectHeaderREFDelta(c *C) { s.testNextObjectHeader(c, "ref-delta", expectedHeadersREF) } -- cgit