aboutsummaryrefslogtreecommitdiffstats
path: root/formats/packfile
diff options
context:
space:
mode:
Diffstat (limited to 'formats/packfile')
-rw-r--r--formats/packfile/parser.go28
-rw-r--r--formats/packfile/parser_test.go14
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)
}