aboutsummaryrefslogtreecommitdiffstats
path: root/plumbing/format/packfile/scanner.go
diff options
context:
space:
mode:
authorFilip Navara <filip.navara@gmail.com>2018-11-28 01:29:41 +0100
committerMáximo Cuadros <mcuadros@gmail.com>2018-11-28 01:29:41 +0100
commit8f52c5099e7fe4a2519920a7bbf5a9bb52ff9cec (patch)
tree6b08348c45ad42e1979d35b43908d5077d99cf78 /plumbing/format/packfile/scanner.go
parent3dbfb89e0f5bce0008724e547b999fe3af9f60db (diff)
downloadgo-git-8f52c5099e7fe4a2519920a7bbf5a9bb52ff9cec.tar.gz
plumbing: format/packfile, performance optimizations for reading large commit histories (#963)
Signed-off-by: Filip Navara <navara@emclient.com>
Diffstat (limited to 'plumbing/format/packfile/scanner.go')
-rw-r--r--plumbing/format/packfile/scanner.go46
1 files changed, 42 insertions, 4 deletions
diff --git a/plumbing/format/packfile/scanner.go b/plumbing/format/packfile/scanner.go
index 6fc183b..614b0d1 100644
--- a/plumbing/format/packfile/scanner.go
+++ b/plumbing/format/packfile/scanner.go
@@ -138,14 +138,52 @@ func (s *Scanner) readCount() (uint32, error) {
return binary.ReadUint32(s.r)
}
+// SeekObjectHeader seeks to specified offset and returns the ObjectHeader
+// for the next object in the reader
+func (s *Scanner) SeekObjectHeader(offset int64) (*ObjectHeader, error) {
+ // if seeking we assume that you are not interested in the header
+ if s.version == 0 {
+ s.version = VersionSupported
+ }
+
+ if _, err := s.r.Seek(offset, io.SeekStart); err != nil {
+ return nil, err
+ }
+
+ h, err := s.nextObjectHeader()
+ if err != nil {
+ return nil, err
+ }
+
+ h.Offset = offset
+ return h, nil
+}
+
// NextObjectHeader returns the ObjectHeader for the next object in the reader
func (s *Scanner) NextObjectHeader() (*ObjectHeader, error) {
- defer s.Flush()
-
if err := s.doPending(); err != nil {
return nil, err
}
+ offset, err := s.r.Seek(0, io.SeekCurrent)
+ if err != nil {
+ return nil, err
+ }
+
+ h, err := s.nextObjectHeader()
+ if err != nil {
+ return nil, err
+ }
+
+ h.Offset = offset
+ return h, nil
+}
+
+// nextObjectHeader returns the ObjectHeader for the next object in the reader
+// without the Offset field
+func (s *Scanner) nextObjectHeader() (*ObjectHeader, error) {
+ defer s.Flush()
+
s.crc.Reset()
h := &ObjectHeader{}
@@ -308,7 +346,7 @@ var byteSlicePool = sync.Pool{
// SeekFromStart sets a new offset from start, returns the old position before
// the change.
func (s *Scanner) SeekFromStart(offset int64) (previous int64, err error) {
- // if seeking we assume that you are not interested on the header
+ // if seeking we assume that you are not interested in the header
if s.version == 0 {
s.version = VersionSupported
}
@@ -385,7 +423,7 @@ type bufferedSeeker struct {
}
func (r *bufferedSeeker) Seek(offset int64, whence int) (int64, error) {
- if whence == io.SeekCurrent {
+ if whence == io.SeekCurrent && offset == 0 {
current, err := r.r.Seek(offset, whence)
if err != nil {
return current, err