@@ -3,6 +3,7 @@ package packfile
3
3
import (
4
4
"bytes"
5
5
"errors"
6
+ "io"
6
7
7
8
"gopkg.in/src-d/go-git.v4/plumbing"
8
9
)
@@ -35,14 +36,20 @@ func ApplyDelta(target, base plumbing.EncodedObject, delta []byte) error {
35
36
}
36
37
src := buf .Bytes ()
37
38
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 )
39
43
if err != nil {
40
44
return err
41
45
}
42
46
43
- target .SetSize (int64 (len (dst )))
44
47
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 )
46
53
return err
47
54
}
48
55
@@ -55,23 +62,31 @@ var (
55
62
// An error will be returned if delta is corrupted (ErrDeltaLen) or an action command
56
63
// is not copy from source or copy from delta (ErrDeltaCmd).
57
64
func 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 {
58
73
if len (delta ) < deltaSizeMin {
59
- return nil , ErrInvalidDelta
74
+ return ErrInvalidDelta
60
75
}
61
76
62
77
srcSz , delta := decodeLEB128 (delta )
63
78
if srcSz != uint (len (src )) {
64
- return nil , ErrInvalidDelta
79
+ return ErrInvalidDelta
65
80
}
66
81
67
82
targetSz , delta := decodeLEB128 (delta )
68
83
remainingTargetSz := targetSz
69
84
70
85
var cmd byte
71
- dest := make ([] byte , 0 , targetSz )
86
+ dst . Grow ( int ( targetSz ) )
72
87
for {
73
88
if len (delta ) == 0 {
74
- return nil , ErrInvalidDelta
89
+ return ErrInvalidDelta
75
90
}
76
91
77
92
cmd = delta [0 ]
@@ -81,43 +96,43 @@ func PatchDelta(src, delta []byte) ([]byte, error) {
81
96
var err error
82
97
offset , delta , err = decodeOffset (cmd , delta )
83
98
if err != nil {
84
- return nil , err
99
+ return err
85
100
}
86
101
87
102
sz , delta , err = decodeSize (cmd , delta )
88
103
if err != nil {
89
- return nil , err
104
+ return err
90
105
}
91
106
92
107
if invalidSize (sz , targetSz ) ||
93
108
invalidOffsetSize (offset , sz , srcSz ) {
94
109
break
95
110
}
96
- dest = append ( dest , src [offset :offset + sz ]... )
111
+ dst . Write ( src [offset :offset + sz ])
97
112
remainingTargetSz -= sz
98
113
} else if isCopyFromDelta (cmd ) {
99
114
sz := uint (cmd ) // cmd is the size itself
100
115
if invalidSize (sz , targetSz ) {
101
- return nil , ErrInvalidDelta
116
+ return ErrInvalidDelta
102
117
}
103
118
104
119
if uint (len (delta )) < sz {
105
- return nil , ErrInvalidDelta
120
+ return ErrInvalidDelta
106
121
}
107
122
108
- dest = append ( dest , delta [0 :sz ]... )
123
+ dst . Write ( delta [0 :sz ])
109
124
remainingTargetSz -= sz
110
125
delta = delta [sz :]
111
126
} else {
112
- return nil , ErrDeltaCmd
127
+ return ErrDeltaCmd
113
128
}
114
129
115
130
if remainingTargetSz <= 0 {
116
131
break
117
132
}
118
133
}
119
134
120
- return dest , nil
135
+ return nil
121
136
}
122
137
123
138
// Decodes a number encoded as an unsigned LEB128 at the start of some
0 commit comments