Skip to content

Commit b25c5ea

Browse files
authored
Merge pull request src-d#411 from src-d/fix/delta-copy-operations
packfile: A copy operation cannot be bigger than 64kb
2 parents 87d2475 + f848005 commit b25c5ea

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

plumbing/format/packfile/delta_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package packfile
22

33
import (
44
"fmt"
5+
"math/rand"
56

67
. "gopkg.in/check.v1"
78
)
@@ -61,9 +62,25 @@ func (s *DeltaSuite) SetUpSuite(c *C) {
6162
{"4", 400}, {"5", 23}},
6263
target: []piece{{"1", 30}, {"2", 20}, {"7", 40}, {"4", 400},
6364
{"5", 10}},
65+
}, {
66+
description: "A copy operation bigger tan 64kb",
67+
base: []piece{{bigRandStr, 1}, {"1", 200}},
68+
target: []piece{{bigRandStr, 1}},
6469
}}
6570
}
6671

72+
var bigRandStr = randStringBytes(100 * 1024)
73+
74+
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
75+
76+
func randStringBytes(n int) string {
77+
b := make([]byte, n)
78+
for i := range b {
79+
b[i] = letterBytes[rand.Intn(len(letterBytes))]
80+
}
81+
return string(b)
82+
}
83+
6784
func (s *DeltaSuite) TestAddDelta(c *C) {
6885
for _, t := range s.testCases {
6986
baseBuf := genBytes(t.base)

plumbing/format/packfile/diff_delta.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ import (
1515
const (
1616
// Standard chunk size used to generate fingerprints
1717
s = 16
18+
19+
// https://github.com/git/git/blob/f7466e94375b3be27f229c78873f0acf8301c0a5/diff-delta.c#L428
20+
// Max size of a copy operation (64KB)
21+
maxCopySize = 64 * 1024
1822
)
1923

2024
// GetDelta returns an EncodedObject of type OFSDeltaObject. Base and Target object,
@@ -70,7 +74,20 @@ func DiffDelta(src []byte, tgt []byte) []byte {
7074
ibuf.WriteByte(tgt[i])
7175
} else {
7276
encodeInsertOperation(ibuf, buf)
73-
buf.Write(encodeCopyOperation(offset, l))
77+
78+
rl := l
79+
aOffset := offset
80+
for {
81+
if rl < maxCopySize {
82+
buf.Write(encodeCopyOperation(aOffset, rl))
83+
break
84+
}
85+
86+
buf.Write(encodeCopyOperation(aOffset, maxCopySize))
87+
rl -= maxCopySize
88+
aOffset += maxCopySize
89+
}
90+
7491
i += l - 1
7592
}
7693
}

0 commit comments

Comments
 (0)