aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSantiago M. Mola <santi@mola.io>2017-06-02 14:51:35 +0200
committerGitHub <noreply@github.com>2017-06-02 14:51:35 +0200
commitb25c5ead44698a4a036435c8977581ea34f761dd (patch)
treec775ac6b264d260393e711b75432c250583fe06f
parent87d2475dd70169bbcb49a70d79ca6cfdff492c38 (diff)
parentf8480053f659120bc3fd33cbf92521cab11b06a6 (diff)
downloadgo-git-b25c5ead44698a4a036435c8977581ea34f761dd.tar.gz
Merge pull request #411 from src-d/fix/delta-copy-operations
packfile: A copy operation cannot be bigger than 64kb
-rw-r--r--plumbing/format/packfile/delta_test.go17
-rw-r--r--plumbing/format/packfile/diff_delta.go19
2 files changed, 35 insertions, 1 deletions
diff --git a/plumbing/format/packfile/delta_test.go b/plumbing/format/packfile/delta_test.go
index 43253b0..9ee3499 100644
--- a/plumbing/format/packfile/delta_test.go
+++ b/plumbing/format/packfile/delta_test.go
@@ -2,6 +2,7 @@ package packfile
import (
"fmt"
+ "math/rand"
. "gopkg.in/check.v1"
)
@@ -61,9 +62,25 @@ func (s *DeltaSuite) SetUpSuite(c *C) {
{"4", 400}, {"5", 23}},
target: []piece{{"1", 30}, {"2", 20}, {"7", 40}, {"4", 400},
{"5", 10}},
+ }, {
+ description: "A copy operation bigger tan 64kb",
+ base: []piece{{bigRandStr, 1}, {"1", 200}},
+ target: []piece{{bigRandStr, 1}},
}}
}
+var bigRandStr = randStringBytes(100 * 1024)
+
+const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+func randStringBytes(n int) string {
+ b := make([]byte, n)
+ for i := range b {
+ b[i] = letterBytes[rand.Intn(len(letterBytes))]
+ }
+ return string(b)
+}
+
func (s *DeltaSuite) TestAddDelta(c *C) {
for _, t := range s.testCases {
baseBuf := genBytes(t.base)
diff --git a/plumbing/format/packfile/diff_delta.go b/plumbing/format/packfile/diff_delta.go
index e3438aa..60a04d9 100644
--- a/plumbing/format/packfile/diff_delta.go
+++ b/plumbing/format/packfile/diff_delta.go
@@ -15,6 +15,10 @@ import (
const (
// Standard chunk size used to generate fingerprints
s = 16
+
+ // https://github.com/git/git/blob/f7466e94375b3be27f229c78873f0acf8301c0a5/diff-delta.c#L428
+ // Max size of a copy operation (64KB)
+ maxCopySize = 64 * 1024
)
// GetDelta returns an EncodedObject of type OFSDeltaObject. Base and Target object,
@@ -70,7 +74,20 @@ func DiffDelta(src []byte, tgt []byte) []byte {
ibuf.WriteByte(tgt[i])
} else {
encodeInsertOperation(ibuf, buf)
- buf.Write(encodeCopyOperation(offset, l))
+
+ rl := l
+ aOffset := offset
+ for {
+ if rl < maxCopySize {
+ buf.Write(encodeCopyOperation(aOffset, rl))
+ break
+ }
+
+ buf.Write(encodeCopyOperation(aOffset, maxCopySize))
+ rl -= maxCopySize
+ aOffset += maxCopySize
+ }
+
i += l - 1
}
}