@@ -3,6 +3,7 @@ package packfile
33import (
44 "bytes"
55 "errors"
6+ "io"
67
78 "gopkg.in/src-d/go-git.v4/plumbing"
89)
@@ -35,14 +36,20 @@ func ApplyDelta(target, base plumbing.EncodedObject, delta []byte) error {
3536 }
3637 src := buf .Bytes ()
3738
38- dst , err := PatchDelta (src , delta )
39+ dst := bufPool .Get ().(* bytes.Buffer )
40+ defer bufPool .Put (dst )
41+ dst .Reset ()
42+ err = patchDelta (dst , src , delta )
3943 if err != nil {
4044 return err
4145 }
4246
43- target .SetSize (int64 (len (dst )))
4447
45- _ , err = w .Write (dst )
48+ target .SetSize (int64 (dst .Len ()))
49+
50+ b := byteSlicePool .Get ().([]byte )
51+ _ , err = io .CopyBuffer (w , dst , b )
52+ byteSlicePool .Put (b )
4653 return err
4754}
4855
@@ -55,23 +62,31 @@ var (
5562// An error will be returned if delta is corrupted (ErrDeltaLen) or an action command
5663// is not copy from source or copy from delta (ErrDeltaCmd).
5764func PatchDelta (src , delta []byte ) ([]byte , error ) {
65+ b := & bytes.Buffer {}
66+ if err := patchDelta (b , src , delta ); err != nil {
67+ return nil , err
68+ }
69+ return b .Bytes (), nil
70+ }
71+
72+ func patchDelta (dst * bytes.Buffer , src , delta []byte ) error {
5873 if len (delta ) < deltaSizeMin {
59- return nil , ErrInvalidDelta
74+ return ErrInvalidDelta
6075 }
6176
6277 srcSz , delta := decodeLEB128 (delta )
6378 if srcSz != uint (len (src )) {
64- return nil , ErrInvalidDelta
79+ return ErrInvalidDelta
6580 }
6681
6782 targetSz , delta := decodeLEB128 (delta )
6883 remainingTargetSz := targetSz
6984
7085 var cmd byte
71- dest := make ([] byte , 0 , targetSz )
86+ dst . Grow ( int ( targetSz ) )
7287 for {
7388 if len (delta ) == 0 {
74- return nil , ErrInvalidDelta
89+ return ErrInvalidDelta
7590 }
7691
7792 cmd = delta [0 ]
@@ -81,43 +96,43 @@ func PatchDelta(src, delta []byte) ([]byte, error) {
8196 var err error
8297 offset , delta , err = decodeOffset (cmd , delta )
8398 if err != nil {
84- return nil , err
99+ return err
85100 }
86101
87102 sz , delta , err = decodeSize (cmd , delta )
88103 if err != nil {
89- return nil , err
104+ return err
90105 }
91106
92107 if invalidSize (sz , targetSz ) ||
93108 invalidOffsetSize (offset , sz , srcSz ) {
94109 break
95110 }
96- dest = append ( dest , src [offset :offset + sz ]... )
111+ dst . Write ( src [offset :offset + sz ])
97112 remainingTargetSz -= sz
98113 } else if isCopyFromDelta (cmd ) {
99114 sz := uint (cmd ) // cmd is the size itself
100115 if invalidSize (sz , targetSz ) {
101- return nil , ErrInvalidDelta
116+ return ErrInvalidDelta
102117 }
103118
104119 if uint (len (delta )) < sz {
105- return nil , ErrInvalidDelta
120+ return ErrInvalidDelta
106121 }
107122
108- dest = append ( dest , delta [0 :sz ]... )
123+ dst . Write ( delta [0 :sz ])
109124 remainingTargetSz -= sz
110125 delta = delta [sz :]
111126 } else {
112- return nil , ErrDeltaCmd
127+ return ErrDeltaCmd
113128 }
114129
115130 if remainingTargetSz <= 0 {
116131 break
117132 }
118133 }
119134
120- return dest , nil
135+ return nil
121136}
122137
123138// Decodes a number encoded as an unsigned LEB128 at the start of some
0 commit comments