aboutsummaryrefslogtreecommitdiffstats
path: root/plumbing/format
diff options
context:
space:
mode:
Diffstat (limited to 'plumbing/format')
-rw-r--r--plumbing/format/config/encoder.go17
-rw-r--r--plumbing/format/config/fixtures_test.go35
-rw-r--r--plumbing/format/config/section.go2
-rw-r--r--plumbing/format/diff/patch.go10
-rw-r--r--plumbing/format/gitattributes/pattern.go5
-rw-r--r--plumbing/format/gitattributes/pattern_test.go6
-rw-r--r--plumbing/format/objfile/reader.go17
-rw-r--r--plumbing/format/objfile/writer.go7
-rw-r--r--plumbing/format/packfile/common.go18
-rw-r--r--plumbing/format/packfile/diff_delta.go21
-rw-r--r--plumbing/format/packfile/packfile.go34
-rw-r--r--plumbing/format/packfile/parser.go19
-rw-r--r--plumbing/format/packfile/parser_test.go28
-rw-r--r--plumbing/format/packfile/patch_delta.go17
-rw-r--r--plumbing/format/packfile/scanner.go54
15 files changed, 174 insertions, 116 deletions
diff --git a/plumbing/format/config/encoder.go b/plumbing/format/config/encoder.go
index 4eac896..de069ae 100644
--- a/plumbing/format/config/encoder.go
+++ b/plumbing/format/config/encoder.go
@@ -11,6 +11,10 @@ type Encoder struct {
w io.Writer
}
+var (
+ subsectionReplacer = strings.NewReplacer(`"`, `\"`, `\`, `\\`)
+ valueReplacer = strings.NewReplacer(`"`, `\"`, `\`, `\\`, "\n", `\n`, "\t", `\t`, "\b", `\b`)
+)
// NewEncoder returns a new encoder that writes to w.
func NewEncoder(w io.Writer) *Encoder {
return &Encoder{w}
@@ -48,8 +52,7 @@ func (e *Encoder) encodeSection(s *Section) error {
}
func (e *Encoder) encodeSubsection(sectionName string, s *Subsection) error {
- //TODO: escape
- if err := e.printf("[%s \"%s\"]\n", sectionName, s.Name); err != nil {
+ if err := e.printf("[%s \"%s\"]\n", sectionName, subsectionReplacer.Replace(s.Name)); err != nil {
return err
}
@@ -58,12 +61,14 @@ func (e *Encoder) encodeSubsection(sectionName string, s *Subsection) error {
func (e *Encoder) encodeOptions(opts Options) error {
for _, o := range opts {
- pattern := "\t%s = %s\n"
- if strings.Contains(o.Value, "\\") {
- pattern = "\t%s = %q\n"
+ var value string
+ if strings.ContainsAny(o.Value, "#;\"\t\n\\") || strings.HasPrefix(o.Value, " ") || strings.HasSuffix(o.Value, " ") {
+ value = `"`+valueReplacer.Replace(o.Value)+`"`
+ } else {
+ value = o.Value
}
- if err := e.printf(pattern, o.Key, o.Value); err != nil {
+ if err := e.printf("\t%s = %s\n", o.Key, value); err != nil {
return err
}
}
diff --git a/plumbing/format/config/fixtures_test.go b/plumbing/format/config/fixtures_test.go
index f3533df..2fa7840 100644
--- a/plumbing/format/config/fixtures_test.go
+++ b/plumbing/format/config/fixtures_test.go
@@ -43,6 +43,41 @@ var fixtures = []*Fixture{
Config: New().AddOption("core", "", "repositoryformatversion", "0"),
},
{
+ Raw: `[section]
+ option1 = "has # hash"
+ option2 = "has \" quote"
+ option3 = "has \\ backslash"
+ option4 = "has ; semicolon"
+ option5 = "has \n line-feed"
+ option6 = "has \t tab"
+ option7 = " has leading spaces"
+ option8 = "has trailing spaces "
+ option9 = has no special characters
+ option10 = has unusual ` + "\x01\x7f\xc8\x80 characters\n",
+ Text: `[section]
+ option1 = "has # hash"
+ option2 = "has \" quote"
+ option3 = "has \\ backslash"
+ option4 = "has ; semicolon"
+ option5 = "has \n line-feed"
+ option6 = "has \t tab"
+ option7 = " has leading spaces"
+ option8 = "has trailing spaces "
+ option9 = has no special characters
+ option10 = has unusual ` + "\x01\x7f\xc8\x80 characters\n",
+ Config: New().
+ AddOption("section", "", "option1", `has # hash`).
+ AddOption("section", "", "option2", `has " quote`).
+ AddOption("section", "", "option3", `has \ backslash`).
+ AddOption("section", "", "option4", `has ; semicolon`).
+ AddOption("section", "", "option5", "has \n line-feed").
+ AddOption("section", "", "option6", "has \t tab").
+ AddOption("section", "", "option7", ` has leading spaces`).
+ AddOption("section", "", "option8", `has trailing spaces `).
+ AddOption("section", "", "option9", `has no special characters`).
+ AddOption("section", "", "option10", "has unusual \x01\x7f\u0200 characters"),
+ },
+ {
Raw: `
[sect1]
opt1 = value1
diff --git a/plumbing/format/config/section.go b/plumbing/format/config/section.go
index 07f72f3..4625ac5 100644
--- a/plumbing/format/config/section.go
+++ b/plumbing/format/config/section.go
@@ -103,7 +103,7 @@ func (s *Section) RemoveSubsection(name string) *Section {
return s
}
-// Option return the value for the specified key. Empty string is returned if
+// Option returns the value for the specified key. Empty string is returned if
// key does not exists.
func (s *Section) Option(key string) string {
return s.Options.Get(key)
diff --git a/plumbing/format/diff/patch.go b/plumbing/format/diff/patch.go
index 39a66a1..c7678b0 100644
--- a/plumbing/format/diff/patch.go
+++ b/plumbing/format/diff/patch.go
@@ -9,7 +9,7 @@ import (
type Operation int
const (
- // Equal item represents a equals diff.
+ // Equal item represents an equals diff.
Equal Operation = iota
// Add item represents an insert diff.
Add
@@ -26,15 +26,15 @@ type Patch interface {
Message() string
}
-// FilePatch represents the necessary steps to transform one file to another.
+// FilePatch represents the necessary steps to transform one file into another.
type FilePatch interface {
// IsBinary returns true if this patch is representing a binary file.
IsBinary() bool
- // Files returns the from and to Files, with all the necessary metadata to
+ // Files returns the from and to Files, with all the necessary metadata
// about them. If the patch creates a new file, "from" will be nil.
// If the patch deletes a file, "to" will be nil.
Files() (from, to File)
- // Chunks returns a slice of ordered changes to transform "from" File to
+ // Chunks returns a slice of ordered changes to transform "from" File into
// "to" File. If the file is a binary one, Chunks will be empty.
Chunks() []Chunk
}
@@ -49,7 +49,7 @@ type File interface {
Path() string
}
-// Chunk represents a portion of a file transformation to another.
+// Chunk represents a portion of a file transformation into another.
type Chunk interface {
// Content contains the portion of the file.
Content() string
diff --git a/plumbing/format/gitattributes/pattern.go b/plumbing/format/gitattributes/pattern.go
index d961aba..f101f47 100644
--- a/plumbing/format/gitattributes/pattern.go
+++ b/plumbing/format/gitattributes/pattern.go
@@ -52,6 +52,11 @@ func (p *pattern) Match(path []string) bool {
var match, doublestar bool
var err error
for _, part := range path {
+ // path is deeper than pattern
+ if len(pattern) == 0 {
+ return false
+ }
+
// skip empty
if pattern[0] == "" {
pattern = pattern[1:]
diff --git a/plumbing/format/gitattributes/pattern_test.go b/plumbing/format/gitattributes/pattern_test.go
index f95be6e..981d56f 100644
--- a/plumbing/format/gitattributes/pattern_test.go
+++ b/plumbing/format/gitattributes/pattern_test.go
@@ -174,6 +174,12 @@ func (s *PatternSuite) TestGlobMatch_tailingAsterisks_single(c *C) {
c.Assert(r, Equals, true)
}
+func (s *PatternSuite) TestGlobMatch_tailingAsterisk_single(c *C) {
+ p := ParsePattern("/*lue/*", nil)
+ r := p.Match([]string{"value", "volcano", "tail"})
+ c.Assert(r, Equals, false)
+}
+
func (s *PatternSuite) TestGlobMatch_tailingAsterisks_exactMatch(c *C) {
p := ParsePattern("/*lue/vol?ano/**", nil)
r := p.Match([]string{"value", "volcano"})
diff --git a/plumbing/format/objfile/reader.go b/plumbing/format/objfile/reader.go
index b6b2ca0..d7932f4 100644
--- a/plumbing/format/objfile/reader.go
+++ b/plumbing/format/objfile/reader.go
@@ -1,13 +1,13 @@
package objfile
import (
- "compress/zlib"
"errors"
"io"
"strconv"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/format/packfile"
+ "github.com/go-git/go-git/v5/utils/sync"
)
var (
@@ -20,20 +20,22 @@ var (
// Reader implements io.ReadCloser. Close should be called when finished with
// the Reader. Close will not close the underlying io.Reader.
type Reader struct {
- multi io.Reader
- zlib io.ReadCloser
- hasher plumbing.Hasher
+ multi io.Reader
+ zlib io.Reader
+ zlibref sync.ZLibReader
+ hasher plumbing.Hasher
}
// NewReader returns a new Reader reading from r.
func NewReader(r io.Reader) (*Reader, error) {
- zlib, err := zlib.NewReader(r)
+ zlib, err := sync.GetZlibReader(r)
if err != nil {
return nil, packfile.ErrZLib.AddDetails(err.Error())
}
return &Reader{
- zlib: zlib,
+ zlib: zlib.Reader,
+ zlibref: zlib,
}, nil
}
@@ -110,5 +112,6 @@ func (r *Reader) Hash() plumbing.Hash {
// Close releases any resources consumed by the Reader. Calling Close does not
// close the wrapped io.Reader originally passed to NewReader.
func (r *Reader) Close() error {
- return r.zlib.Close()
+ sync.PutZlibReader(r.zlibref)
+ return nil
}
diff --git a/plumbing/format/objfile/writer.go b/plumbing/format/objfile/writer.go
index 2a96a43..0d0f154 100644
--- a/plumbing/format/objfile/writer.go
+++ b/plumbing/format/objfile/writer.go
@@ -7,6 +7,7 @@ import (
"strconv"
"github.com/go-git/go-git/v5/plumbing"
+ "github.com/go-git/go-git/v5/utils/sync"
)
var (
@@ -18,9 +19,9 @@ var (
// not close the underlying io.Writer.
type Writer struct {
raw io.Writer
- zlib io.WriteCloser
hasher plumbing.Hasher
multi io.Writer
+ zlib *zlib.Writer
closed bool
pending int64 // number of unwritten bytes
@@ -31,9 +32,10 @@ type Writer struct {
// The returned Writer implements io.WriteCloser. Close should be called when
// finished with the Writer. Close will not close the underlying io.Writer.
func NewWriter(w io.Writer) *Writer {
+ zlib := sync.GetZlibWriter(w)
return &Writer{
raw: w,
- zlib: zlib.NewWriter(w),
+ zlib: zlib,
}
}
@@ -100,6 +102,7 @@ func (w *Writer) Hash() plumbing.Hash {
// Calling Close does not close the wrapped io.Writer originally passed to
// NewWriter.
func (w *Writer) Close() error {
+ defer sync.PutZlibWriter(w.zlib)
if err := w.zlib.Close(); err != nil {
return err
}
diff --git a/plumbing/format/packfile/common.go b/plumbing/format/packfile/common.go
index df423ad..36c5ef5 100644
--- a/plumbing/format/packfile/common.go
+++ b/plumbing/format/packfile/common.go
@@ -1,10 +1,7 @@
package packfile
import (
- "bytes"
- "compress/zlib"
"io"
- "sync"
"github.com/go-git/go-git/v5/plumbing/storer"
"github.com/go-git/go-git/v5/utils/ioutil"
@@ -61,18 +58,3 @@ func WritePackfileToObjectStorage(
return err
}
-
-var bufPool = sync.Pool{
- New: func() interface{} {
- return bytes.NewBuffer(nil)
- },
-}
-
-var zlibInitBytes = []byte{0x78, 0x9c, 0x01, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01}
-
-var zlibReaderPool = sync.Pool{
- New: func() interface{} {
- r, _ := zlib.NewReader(bytes.NewReader(zlibInitBytes))
- return r
- },
-}
diff --git a/plumbing/format/packfile/diff_delta.go b/plumbing/format/packfile/diff_delta.go
index 1951b34..2c7a335 100644
--- a/plumbing/format/packfile/diff_delta.go
+++ b/plumbing/format/packfile/diff_delta.go
@@ -5,6 +5,7 @@ import (
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/utils/ioutil"
+ "github.com/go-git/go-git/v5/utils/sync"
)
// See https://github.com/jelmer/dulwich/blob/master/dulwich/pack.py and
@@ -43,18 +44,16 @@ func getDelta(index *deltaIndex, base, target plumbing.EncodedObject) (o plumbin
defer ioutil.CheckClose(tr, &err)
- bb := bufPool.Get().(*bytes.Buffer)
- defer bufPool.Put(bb)
- bb.Reset()
+ bb := sync.GetBytesBuffer()
+ defer sync.PutBytesBuffer(bb)
_, err = bb.ReadFrom(br)
if err != nil {
return nil, err
}
- tb := bufPool.Get().(*bytes.Buffer)
- defer bufPool.Put(tb)
- tb.Reset()
+ tb := sync.GetBytesBuffer()
+ defer sync.PutBytesBuffer(tb)
_, err = tb.ReadFrom(tr)
if err != nil {
@@ -80,9 +79,8 @@ func DiffDelta(src, tgt []byte) []byte {
}
func diffDelta(index *deltaIndex, src []byte, tgt []byte) []byte {
- buf := bufPool.Get().(*bytes.Buffer)
- defer bufPool.Put(buf)
- buf.Reset()
+ buf := sync.GetBytesBuffer()
+ defer sync.PutBytesBuffer(buf)
buf.Write(deltaEncodeSize(len(src)))
buf.Write(deltaEncodeSize(len(tgt)))
@@ -90,9 +88,8 @@ func diffDelta(index *deltaIndex, src []byte, tgt []byte) []byte {
index.init(src)
}
- ibuf := bufPool.Get().(*bytes.Buffer)
- defer bufPool.Put(ibuf)
- ibuf.Reset()
+ ibuf := sync.GetBytesBuffer()
+ defer sync.PutBytesBuffer(ibuf)
for i := 0; i < len(tgt); i++ {
offset, l := index.findMatch(src, tgt, i)
diff --git a/plumbing/format/packfile/packfile.go b/plumbing/format/packfile/packfile.go
index 8dd6041..6852702 100644
--- a/plumbing/format/packfile/packfile.go
+++ b/plumbing/format/packfile/packfile.go
@@ -2,7 +2,6 @@ package packfile
import (
"bytes"
- "compress/zlib"
"fmt"
"io"
"os"
@@ -13,6 +12,7 @@ import (
"github.com/go-git/go-git/v5/plumbing/format/idxfile"
"github.com/go-git/go-git/v5/plumbing/storer"
"github.com/go-git/go-git/v5/utils/ioutil"
+ "github.com/go-git/go-git/v5/utils/sync"
)
var (
@@ -138,9 +138,8 @@ func (p *Packfile) getObjectSize(h *ObjectHeader) (int64, error) {
case plumbing.CommitObject, plumbing.TreeObject, plumbing.BlobObject, plumbing.TagObject:
return h.Length, nil
case plumbing.REFDeltaObject, plumbing.OFSDeltaObject:
- buf := bufPool.Get().(*bytes.Buffer)
- defer bufPool.Put(buf)
- buf.Reset()
+ buf := sync.GetBytesBuffer()
+ defer sync.PutBytesBuffer(buf)
if _, _, err := p.s.NextObject(buf); err != nil {
return 0, err
@@ -227,9 +226,9 @@ func (p *Packfile) getNextObject(h *ObjectHeader, hash plumbing.Hash) (plumbing.
// For delta objects we read the delta data and apply the small object
// optimization only if the expanded version of the object still meets
// the small object threshold condition.
- buf := bufPool.Get().(*bytes.Buffer)
- defer bufPool.Put(buf)
- buf.Reset()
+ buf := sync.GetBytesBuffer()
+ defer sync.PutBytesBuffer(buf)
+
if _, _, err := p.s.NextObject(buf); err != nil {
return nil, err
}
@@ -290,14 +289,13 @@ func (p *Packfile) getObjectContent(offset int64) (io.ReadCloser, error) {
func asyncReader(p *Packfile) (io.ReadCloser, error) {
reader := ioutil.NewReaderUsingReaderAt(p.file, p.s.r.offset)
- zr := zlibReaderPool.Get().(io.ReadCloser)
-
- if err := zr.(zlib.Resetter).Reset(reader, nil); err != nil {
+ zr, err := sync.GetZlibReader(reader)
+ if err != nil {
return nil, fmt.Errorf("zlib reset error: %s", err)
}
- return ioutil.NewReadCloserWithCloser(zr, func() error {
- zlibReaderPool.Put(zr)
+ return ioutil.NewReadCloserWithCloser(zr.Reader, func() error {
+ sync.PutZlibReader(zr)
return nil
}), nil
@@ -373,9 +371,9 @@ func (p *Packfile) fillRegularObjectContent(obj plumbing.EncodedObject) (err err
}
func (p *Packfile) fillREFDeltaObjectContent(obj plumbing.EncodedObject, ref plumbing.Hash) error {
- buf := bufPool.Get().(*bytes.Buffer)
- defer bufPool.Put(buf)
- buf.Reset()
+ buf := sync.GetBytesBuffer()
+ defer sync.PutBytesBuffer(buf)
+
_, _, err := p.s.NextObject(buf)
if err != nil {
return err
@@ -417,9 +415,9 @@ func (p *Packfile) fillREFDeltaObjectContentWithBuffer(obj plumbing.EncodedObjec
}
func (p *Packfile) fillOFSDeltaObjectContent(obj plumbing.EncodedObject, offset int64) error {
- buf := bufPool.Get().(*bytes.Buffer)
- defer bufPool.Put(buf)
- buf.Reset()
+ buf := sync.GetBytesBuffer()
+ defer sync.PutBytesBuffer(buf)
+
_, _, err := p.s.NextObject(buf)
if err != nil {
return err
diff --git a/plumbing/format/packfile/parser.go b/plumbing/format/packfile/parser.go
index 9ec838e..522c146 100644
--- a/plumbing/format/packfile/parser.go
+++ b/plumbing/format/packfile/parser.go
@@ -10,6 +10,7 @@ import (
"github.com/go-git/go-git/v5/plumbing/cache"
"github.com/go-git/go-git/v5/plumbing/storer"
"github.com/go-git/go-git/v5/utils/ioutil"
+ "github.com/go-git/go-git/v5/utils/sync"
)
var (
@@ -175,7 +176,8 @@ func (p *Parser) init() error {
}
func (p *Parser) indexObjects() error {
- buf := new(bytes.Buffer)
+ buf := sync.GetBytesBuffer()
+ defer sync.PutBytesBuffer(buf)
for i := uint32(0); i < p.count; i++ {
buf.Reset()
@@ -219,6 +221,7 @@ func (p *Parser) indexObjects() error {
ota = newBaseObject(oh.Offset, oh.Length, t)
}
+ buf.Grow(int(oh.Length))
_, crc, err := p.scanner.NextObject(buf)
if err != nil {
return err
@@ -264,7 +267,9 @@ func (p *Parser) indexObjects() error {
}
func (p *Parser) resolveDeltas() error {
- buf := &bytes.Buffer{}
+ buf := sync.GetBytesBuffer()
+ defer sync.PutBytesBuffer(buf)
+
for _, obj := range p.oi {
buf.Reset()
err := p.get(obj, buf)
@@ -346,9 +351,8 @@ func (p *Parser) get(o *objectInfo, buf *bytes.Buffer) (err error) {
}
if o.DiskType.IsDelta() {
- b := bufPool.Get().(*bytes.Buffer)
- defer bufPool.Put(b)
- b.Reset()
+ b := sync.GetBytesBuffer()
+ defer sync.PutBytesBuffer(b)
err := p.get(o.Parent, b)
if err != nil {
return err
@@ -382,9 +386,8 @@ func (p *Parser) resolveObject(
if !o.DiskType.IsDelta() {
return nil
}
- buf := bufPool.Get().(*bytes.Buffer)
- defer bufPool.Put(buf)
- buf.Reset()
+ buf := sync.GetBytesBuffer()
+ defer sync.PutBytesBuffer(buf)
err := p.readData(buf, o)
if err != nil {
return err
diff --git a/plumbing/format/packfile/parser_test.go b/plumbing/format/packfile/parser_test.go
index 09f3f97..651d05f 100644
--- a/plumbing/format/packfile/parser_test.go
+++ b/plumbing/format/packfile/parser_test.go
@@ -10,8 +10,10 @@ import (
fixtures "github.com/go-git/go-git-fixtures/v4"
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
+ "github.com/go-git/go-git/v5/plumbing/cache"
"github.com/go-git/go-git/v5/plumbing/format/packfile"
"github.com/go-git/go-git/v5/plumbing/storer"
+ "github.com/go-git/go-git/v5/storage/filesystem"
. "gopkg.in/check.v1"
)
@@ -248,3 +250,29 @@ func BenchmarkParseBasic(b *testing.B) {
}
}
}
+
+func BenchmarkParser(b *testing.B) {
+ f := fixtures.Basic().One()
+ defer fixtures.Clean()
+
+ b.ResetTimer()
+ for n := 0; n < b.N; n++ {
+ b.StopTimer()
+ scanner := packfile.NewScanner(f.Packfile())
+ fs := osfs.New(os.TempDir())
+ storage := filesystem.NewStorage(fs, cache.NewObjectLRUDefault())
+
+ parser, err := packfile.NewParserWithStorage(scanner, storage)
+ if err != nil {
+ b.Error(err)
+ }
+
+ b.StartTimer()
+ _, err = parser.Parse()
+
+ b.StopTimer()
+ if err != nil {
+ b.Error(err)
+ }
+ }
+}
diff --git a/plumbing/format/packfile/patch_delta.go b/plumbing/format/packfile/patch_delta.go
index 17da11e..f00562d 100644
--- a/plumbing/format/packfile/patch_delta.go
+++ b/plumbing/format/packfile/patch_delta.go
@@ -9,6 +9,7 @@ import (
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/utils/ioutil"
+ "github.com/go-git/go-git/v5/utils/sync"
)
// See https://github.com/git/git/blob/49fa3dc76179e04b0833542fa52d0f287a4955ac/delta.h
@@ -34,18 +35,16 @@ func ApplyDelta(target, base plumbing.EncodedObject, delta []byte) (err error) {
defer ioutil.CheckClose(w, &err)
- buf := bufPool.Get().(*bytes.Buffer)
- defer bufPool.Put(buf)
- buf.Reset()
+ buf := sync.GetBytesBuffer()
+ defer sync.PutBytesBuffer(buf)
_, err = buf.ReadFrom(r)
if err != nil {
return err
}
src := buf.Bytes()
- dst := bufPool.Get().(*bytes.Buffer)
- defer bufPool.Put(dst)
- dst.Reset()
+ dst := sync.GetBytesBuffer()
+ defer sync.PutBytesBuffer(dst)
err = patchDelta(dst, src, delta)
if err != nil {
return err
@@ -53,9 +52,9 @@ func ApplyDelta(target, base plumbing.EncodedObject, delta []byte) (err error) {
target.SetSize(int64(dst.Len()))
- b := byteSlicePool.Get().([]byte)
- _, err = io.CopyBuffer(w, dst, b)
- byteSlicePool.Put(b)
+ b := sync.GetByteSlice()
+ _, err = io.CopyBuffer(w, dst, *b)
+ sync.PutByteSlice(b)
return err
}
diff --git a/plumbing/format/packfile/scanner.go b/plumbing/format/packfile/scanner.go
index 5d9e8fb..9ebb84a 100644
--- a/plumbing/format/packfile/scanner.go
+++ b/plumbing/format/packfile/scanner.go
@@ -3,17 +3,16 @@ package packfile
import (
"bufio"
"bytes"
- "compress/zlib"
"fmt"
"hash"
"hash/crc32"
"io"
stdioutil "io/ioutil"
- "sync"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/utils/binary"
"github.com/go-git/go-git/v5/utils/ioutil"
+ "github.com/go-git/go-git/v5/utils/sync"
)
var (
@@ -114,7 +113,7 @@ func (s *Scanner) Header() (version, objects uint32, err error) {
return
}
-// readSignature reads an returns the signature field in the packfile.
+// readSignature reads a returns the signature field in the packfile.
func (s *Scanner) readSignature() ([]byte, error) {
var sig = make([]byte, 4)
if _, err := io.ReadFull(s.r, sig); err != nil {
@@ -323,14 +322,14 @@ func (s *Scanner) NextObject(w io.Writer) (written int64, crc32 uint32, err erro
// ReadObject returns a reader for the object content and an error
func (s *Scanner) ReadObject() (io.ReadCloser, error) {
s.pendingObject = nil
- zr := zlibReaderPool.Get().(io.ReadCloser)
+ zr, err := sync.GetZlibReader(s.r)
- if err := zr.(zlib.Resetter).Reset(s.r, nil); err != nil {
+ if err != nil {
return nil, fmt.Errorf("zlib reset error: %s", err)
}
- return ioutil.NewReadCloserWithCloser(zr, func() error {
- zlibReaderPool.Put(zr)
+ return ioutil.NewReadCloserWithCloser(zr.Reader, func() error {
+ sync.PutZlibReader(zr)
return nil
}), nil
}
@@ -338,26 +337,20 @@ func (s *Scanner) ReadObject() (io.ReadCloser, error) {
// ReadRegularObject reads and write a non-deltified object
// from it zlib stream in an object entry in the packfile.
func (s *Scanner) copyObject(w io.Writer) (n int64, err error) {
- zr := zlibReaderPool.Get().(io.ReadCloser)
- defer zlibReaderPool.Put(zr)
+ zr, err := sync.GetZlibReader(s.r)
+ defer sync.PutZlibReader(zr)
- if err = zr.(zlib.Resetter).Reset(s.r, nil); err != nil {
+ if err != nil {
return 0, fmt.Errorf("zlib reset error: %s", err)
}
- defer ioutil.CheckClose(zr, &err)
- buf := byteSlicePool.Get().([]byte)
- n, err = io.CopyBuffer(w, zr, buf)
- byteSlicePool.Put(buf)
+ defer ioutil.CheckClose(zr.Reader, &err)
+ buf := sync.GetByteSlice()
+ n, err = io.CopyBuffer(w, zr.Reader, *buf)
+ sync.PutByteSlice(buf)
return
}
-var byteSlicePool = sync.Pool{
- New: func() interface{} {
- return make([]byte, 32*1024)
- },
-}
-
// SeekFromStart sets a new offset from start, returns the old position before
// the change.
func (s *Scanner) SeekFromStart(offset int64) (previous int64, err error) {
@@ -387,9 +380,10 @@ func (s *Scanner) Checksum() (plumbing.Hash, error) {
// Close reads the reader until io.EOF
func (s *Scanner) Close() error {
- buf := byteSlicePool.Get().([]byte)
- _, err := io.CopyBuffer(stdioutil.Discard, s.r, buf)
- byteSlicePool.Put(buf)
+ buf := sync.GetByteSlice()
+ _, err := io.CopyBuffer(stdioutil.Discard, s.r, *buf)
+ sync.PutByteSlice(buf)
+
return err
}
@@ -399,13 +393,13 @@ func (s *Scanner) Flush() error {
}
// scannerReader has the following characteristics:
-// - Provides an io.SeekReader impl for bufio.Reader, when the underlying
-// reader supports it.
-// - Keeps track of the current read position, for when the underlying reader
-// isn't an io.SeekReader, but we still want to know the current offset.
-// - Writes to the hash writer what it reads, with the aid of a smaller buffer.
-// The buffer helps avoid a performance penality for performing small writes
-// to the crc32 hash writer.
+// - Provides an io.SeekReader impl for bufio.Reader, when the underlying
+// reader supports it.
+// - Keeps track of the current read position, for when the underlying reader
+// isn't an io.SeekReader, but we still want to know the current offset.
+// - Writes to the hash writer what it reads, with the aid of a smaller buffer.
+// The buffer helps avoid a performance penalty for performing small writes
+// to the crc32 hash writer.
type scannerReader struct {
reader io.Reader
crc io.Writer