Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

Commit 834cd6f

Browse files
authored
Merge pull request #724 from jfontan/improvement/buffered-tee-reader
plumbing: packfile, Add a buffer to crc writer
2 parents f6aca08 + 1cb896b commit 834cd6f

File tree

2 files changed

+106
-13
lines changed

2 files changed

+106
-13
lines changed

plumbing/format/packfile/scanner.go

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,7 @@ func NewScanner(r io.Reader) *Scanner {
6363

6464
crc := crc32.NewIEEE()
6565
return &Scanner{
66-
r: &teeReader{
67-
newByteReadSeeker(seeker),
68-
crc,
69-
},
66+
r: newTeeReader(newByteReadSeeker(seeker), crc),
7067
crc: crc,
7168
IsSeekable: ok,
7269
}
@@ -143,6 +140,8 @@ func (s *Scanner) readCount() (uint32, error) {
143140

144141
// NextObjectHeader returns the ObjectHeader for the next object in the reader
145142
func (s *Scanner) NextObjectHeader() (*ObjectHeader, error) {
143+
defer s.Flush()
144+
146145
if err := s.doPending(); err != nil {
147146
return nil, err
148147
}
@@ -271,6 +270,7 @@ func (s *Scanner) NextObject(w io.Writer) (written int64, crc32 uint32, err erro
271270

272271
s.pendingObject = nil
273272
written, err = s.copyObject(w)
273+
s.Flush()
274274
crc32 = s.crc.Sum32()
275275
return
276276
}
@@ -339,6 +339,16 @@ func (s *Scanner) Close() error {
339339
return err
340340
}
341341

342+
// Flush finishes writing the buffer to crc hasher in case we are using
343+
// a teeReader. Otherwise it is a no-op.
344+
func (s *Scanner) Flush() error {
345+
tee, ok := s.r.(*teeReader)
346+
if ok {
347+
return tee.Flush()
348+
}
349+
return nil
350+
}
351+
342352
type trackableReader struct {
343353
count int64
344354
io.Reader
@@ -400,10 +410,21 @@ type reader interface {
400410

401411
type teeReader struct {
402412
reader
403-
w hash.Hash32
413+
w hash.Hash32
414+
bufWriter *bufio.Writer
415+
}
416+
417+
func newTeeReader(r reader, h hash.Hash32) *teeReader {
418+
return &teeReader{
419+
reader: r,
420+
w: h,
421+
bufWriter: bufio.NewWriter(h),
422+
}
404423
}
405424

406425
func (r *teeReader) Read(p []byte) (n int, err error) {
426+
r.Flush()
427+
407428
n, err = r.reader.Read(p)
408429
if n > 0 {
409430
if n, err := r.w.Write(p[:n]); err != nil {
@@ -416,11 +437,12 @@ func (r *teeReader) Read(p []byte) (n int, err error) {
416437
func (r *teeReader) ReadByte() (b byte, err error) {
417438
b, err = r.reader.ReadByte()
418439
if err == nil {
419-
_, err := r.w.Write([]byte{b})
420-
if err != nil {
421-
return 0, err
422-
}
440+
return b, r.bufWriter.WriteByte(b)
423441
}
424442

425443
return
426444
}
445+
446+
func (r *teeReader) Flush() (err error) {
447+
return r.bufWriter.Flush()
448+
}

plumbing/format/packfile/scanner_test.go

Lines changed: 75 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,16 @@ func (s *ScannerSuite) TestNextObjectHeaderWithoutHeader(c *C) {
4141
}
4242

4343
func (s *ScannerSuite) TestNextObjectHeaderREFDelta(c *C) {
44-
s.testNextObjectHeader(c, "ref-delta", expectedHeadersREF)
44+
s.testNextObjectHeader(c, "ref-delta", expectedHeadersREF, expectedCRCREF)
4545
}
4646

4747
func (s *ScannerSuite) TestNextObjectHeaderOFSDelta(c *C) {
48-
s.testNextObjectHeader(c, "ofs-delta", expectedHeadersOFS)
48+
s.testNextObjectHeader(c, "ofs-delta", expectedHeadersOFS, expectedCRCOFS)
4949
}
5050

51-
func (s *ScannerSuite) testNextObjectHeader(c *C, tag string, expected []ObjectHeader) {
51+
func (s *ScannerSuite) testNextObjectHeader(c *C, tag string,
52+
expected []ObjectHeader, expectedCRC []uint32) {
53+
5254
r := fixtures.Basic().ByTag(tag).One().Packfile()
5355
p := NewScanner(r)
5456

@@ -61,9 +63,10 @@ func (s *ScannerSuite) testNextObjectHeader(c *C, tag string, expected []ObjectH
6163
c.Assert(*h, DeepEquals, expected[i])
6264

6365
buf := bytes.NewBuffer(nil)
64-
n, _, err := p.NextObject(buf)
66+
n, crcFromScanner, err := p.NextObject(buf)
6567
c.Assert(err, IsNil)
6668
c.Assert(n, Equals, h.Length)
69+
c.Assert(crcFromScanner, Equals, expectedCRC[i])
6770
}
6871

6972
n, err := p.Checksum()
@@ -149,6 +152,40 @@ var expectedHeadersOFS = []ObjectHeader{
149152
{Type: plumbing.OFSDeltaObject, Offset: 84760, Length: 4, OffsetReference: 84741},
150153
}
151154

155+
var expectedCRCOFS = []uint32{
156+
0xaa07ba4b,
157+
0xf706df58,
158+
0x12438846,
159+
0x2905a38c,
160+
0xd9429436,
161+
0xbecfde4e,
162+
0x780e4b3e,
163+
0xdc18344f,
164+
0xcf4e4280,
165+
0x1f08118a,
166+
0xafded7b8,
167+
0xcc1428ed,
168+
0x1631d22f,
169+
0xbfff5850,
170+
0xd108e1d8,
171+
0x8e97ba25,
172+
0x7316ff70,
173+
0xdb4fce56,
174+
0x901cce2c,
175+
0xec4552b0,
176+
0x847905bf,
177+
0x3689459a,
178+
0xe67af94a,
179+
0xc2314a2e,
180+
0xcd987848,
181+
0x8a853a6d,
182+
0x70c6518,
183+
0x4f4108e2,
184+
0xd6fe09e9,
185+
0xf07a2804,
186+
0x1d75d6be,
187+
}
188+
152189
var expectedHeadersREF = []ObjectHeader{
153190
{Type: plumbing.CommitObject, Offset: 12, Length: 254},
154191
{Type: plumbing.REFDeltaObject, Offset: 186, Length: 93,
@@ -188,3 +225,37 @@ var expectedHeadersREF = []ObjectHeader{
188225
Reference: plumbing.NewHash("eba74343e2f15d62adedfd8c883ee0262b5c8021")},
189226
{Type: plumbing.TreeObject, Offset: 85485, Length: 73},
190227
}
228+
229+
var expectedCRCREF = []uint32{
230+
0xaa07ba4b,
231+
0xfb4725a4,
232+
0x12438846,
233+
0x2905a38c,
234+
0xd9429436,
235+
0xbecfde4e,
236+
0xdc18344f,
237+
0x780e4b3e,
238+
0xcf4e4280,
239+
0x1f08118a,
240+
0xafded7b8,
241+
0xcc1428ed,
242+
0x1631d22f,
243+
0x847905bf,
244+
0x3e20f31d,
245+
0x3689459a,
246+
0xd108e1d8,
247+
0x71143d4a,
248+
0xe67af94a,
249+
0x739fb89f,
250+
0xc2314a2e,
251+
0x87864926,
252+
0x415d752f,
253+
0xf72fb182,
254+
0x3ffa37d4,
255+
0xcd987848,
256+
0x2f20ac8f,
257+
0xf2f0575,
258+
0x7d8726e1,
259+
0x740bf39,
260+
0x26af4735,
261+
}

0 commit comments

Comments
 (0)