[SCM] WebKit Debian packaging branch, debian/experimental, updated. debian/1.3.8-1-1049-g2e11a8e
commit-queue at webkit.org
commit-queue at webkit.org
Fri Jan 21 15:07:02 UTC 2011
The following commit has been merged in the debian/experimental branch:
commit bb8e4f1c21766943da0e9e84a19cb45f8552af7a
Author: commit-queue at webkit.org <commit-queue at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Fri Jan 7 09:46:42 2011 +0000
2011-01-07 Shane Stephens <shanestephens at google.com>
Reviewed by Eric Seidel.
svn-apply: should support git binary delta diffs
https://bugs.webkit.org/show_bug.cgi?id=38864
* Scripts/VCSUtils.pm:
* Scripts/svn-apply:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@75235 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Tools/ChangeLog b/Tools/ChangeLog
index b2c1535..302a25c 100644
--- a/Tools/ChangeLog
+++ b/Tools/ChangeLog
@@ -1,3 +1,13 @@
+2011-01-07 Shane Stephens <shanestephens at google.com>
+
+ Reviewed by Eric Seidel.
+
+ svn-apply: should support git binary delta diffs
+ https://bugs.webkit.org/show_bug.cgi?id=38864
+
+ * Scripts/VCSUtils.pm:
+ * Scripts/svn-apply:
+
2011-01-06 Julie Parent <jparent at chromium.org>
Reviewed by Eric Seidel.
diff --git a/Tools/Scripts/VCSUtils.pm b/Tools/Scripts/VCSUtils.pm
index 78ba217..ffe499f 100644
--- a/Tools/Scripts/VCSUtils.pm
+++ b/Tools/Scripts/VCSUtils.pm
@@ -44,11 +44,13 @@ BEGIN {
$VERSION = 1.00;
@ISA = qw(Exporter);
@EXPORT = qw(
+ &applyGitBinaryPatchDelta
&callSilently
&canonicalizePath
&changeLogEmailAddress
&changeLogName
&chdirReturningRelativePath
+ &decodeGitBinaryChunk
&decodeGitBinaryPatch
&determineSVNRoot
&determineVCSRoot
@@ -1742,7 +1744,6 @@ sub decodeGitBinaryPatch($$)
#
# Each chunk a line which starts from either "literal" or "delta",
# followed by a number which specifies decoded size of the chunk.
- # The "delta" type chunks aren't supported by this function yet.
#
# Then, content of the chunk comes. To decode the content, we
# need decode it with base85 first, and then zlib.
@@ -1763,10 +1764,94 @@ sub decodeGitBinaryPatch($$)
my $reverseBinaryChunk = decodeGitBinaryChunk($encodedReverseChunk, $fullPath);
my $reverseBinaryChunkActualSize = length($reverseBinaryChunk);
- die "$fullPath: unexpected size of the first chunk (expected $binaryChunkExpectedSize but was $binaryChunkActualSize" if ($binaryChunkExpectedSize != $binaryChunkActualSize);
- die "$fullPath: unexpected size of the second chunk (expected $reverseBinaryChunkExpectedSize but was $reverseBinaryChunkActualSize" if ($reverseBinaryChunkExpectedSize != $reverseBinaryChunkActualSize);
+ die "$fullPath: unexpected size of the first chunk (expected $binaryChunkExpectedSize but was $binaryChunkActualSize" if ($binaryChunkType eq "literal" and $binaryChunkExpectedSize != $binaryChunkActualSize);
+ die "$fullPath: unexpected size of the second chunk (expected $reverseBinaryChunkExpectedSize but was $reverseBinaryChunkActualSize" if ($reverseBinaryChunkType eq "literal" and $reverseBinaryChunkExpectedSize != $reverseBinaryChunkActualSize);
return ($binaryChunkType, $binaryChunk, $reverseBinaryChunkType, $reverseBinaryChunk);
}
+sub readByte($$)
+{
+ my ($data, $location) = @_;
+
+ # Return the byte at $location in $data as a numeric value.
+ return ord(substr($data, $location, 1));
+}
+
+# The git binary delta format is undocumented, except in code:
+# - https://github.com/git/git/blob/master/delta.h:get_delta_hdr_size is the source
+# of the algorithm in decodeGitBinaryPatchDeltaSize.
+# - https://github.com/git/git/blob/master/patch-delta.c:patch_delta is the source
+# of the algorithm in applyGitBinaryPatchDelta.
+sub decodeGitBinaryPatchDeltaSize($)
+{
+ my ($binaryChunk) = @_;
+
+ # Source and destination buffer sizes are stored in 7-bit chunks at the
+ # start of the binary delta patch data. The highest bit in each byte
+ # except the last is set; the remaining 7 bits provide the next
+ # chunk of the size. The chunks are stored in ascending significance
+ # order.
+ my $cmd;
+ my $size = 0;
+ my $shift = 0;
+ for (my $i = 0; $i < length($binaryChunk);) {
+ $cmd = readByte($binaryChunk, $i++);
+ $size |= ($cmd & 0x7f) << $shift;
+ $shift += 7;
+ if (!($cmd & 0x80)) {
+ return ($size, $i);
+ }
+ }
+}
+
+sub applyGitBinaryPatchDelta($$)
+{
+ my ($binaryChunk, $originalContents) = @_;
+
+ # Git delta format consists of two headers indicating source buffer size
+ # and result size, then a series of commands. Each command is either
+ # a copy-from-old-version (the 0x80 bit is set) or a copy-from-delta
+ # command. Commands are applied sequentially to generate the result.
+ #
+ # A copy-from-old-version command encodes an offset and size to copy
+ # from in subsequent bits, while a copy-from-delta command consists only
+ # of the number of bytes to copy from the delta.
+
+ # We don't use these values, but we need to know how big they are so that
+ # we can skip to the diff data.
+ my ($size, $bytesUsed) = decodeGitBinaryPatchDeltaSize($binaryChunk);
+ $binaryChunk = substr($binaryChunk, $bytesUsed);
+ ($size, $bytesUsed) = decodeGitBinaryPatchDeltaSize($binaryChunk);
+ $binaryChunk = substr($binaryChunk, $bytesUsed);
+
+ my $out = "";
+ for (my $i = 0; $i < length($binaryChunk); ) {
+ my $cmd = ord(substr($binaryChunk, $i++, 1));
+ if ($cmd & 0x80) {
+ # Extract an offset and size from the delta data, then copy
+ # $size bytes from $offset in the original data into the output.
+ my $offset = 0;
+ my $size = 0;
+ if ($cmd & 0x01) { $offset = readByte($binaryChunk, $i++); }
+ if ($cmd & 0x02) { $offset |= readByte($binaryChunk, $i++) << 8; }
+ if ($cmd & 0x04) { $offset |= readByte($binaryChunk, $i++) << 16; }
+ if ($cmd & 0x08) { $offset |= readByte($binaryChunk, $i++) << 24; }
+ if ($cmd & 0x10) { $size = readByte($binaryChunk, $i++); }
+ if ($cmd & 0x20) { $size |= readByte($binaryChunk, $i++) << 8; }
+ if ($cmd & 0x40) { $size |= readByte($binaryChunk, $i++) << 16; }
+ if ($size == 0) { $size = 0x10000; }
+ $out .= substr($originalContents, $offset, $size);
+ } elsif ($cmd) {
+ # Copy $cmd bytes from the delta data into the output.
+ $out .= substr($binaryChunk, $i, $cmd);
+ $i += $cmd;
+ } else {
+ die "unexpected delta opcode 0";
+ }
+ }
+
+ return $out;
+}
+
1;
diff --git a/Tools/Scripts/svn-apply b/Tools/Scripts/svn-apply
index cab7fb4..0c2e5e5 100755
--- a/Tools/Scripts/svn-apply
+++ b/Tools/Scripts/svn-apply
@@ -244,8 +244,6 @@ sub handleGitBinaryChange($$)
my $contents = $diffHashRef->{svnConvertedText};
my ($binaryChunkType, $binaryChunk, $reverseBinaryChunkType, $reverseBinaryChunk) = decodeGitBinaryPatch($contents, $fullPath);
- # FIXME: support "delta" type.
- die "only literal type is supported now" if ($binaryChunkType ne "literal" || $reverseBinaryChunkType ne "literal");
my $isFileAddition = $diffHashRef->{isNew};
my $isFileDeletion = $diffHashRef->{isDeletion};
@@ -257,14 +255,26 @@ sub handleGitBinaryChange($$)
$originalContents = join("", <FILE>);
close FILE;
}
- die "Original content of $fullPath mismatches" if $originalContents ne $reverseBinaryChunk;
+
+ if ($reverseBinaryChunkType eq "literal") {
+ die "Original content of $fullPath mismatches" if $originalContents ne $reverseBinaryChunk;
+ }
if ($isFileDeletion) {
scmRemove($fullPath);
} else {
# Addition or Modification
+ my $out = "";
+ if ($binaryChunkType eq "delta") {
+ $out = applyGitBinaryPatchDelta($binaryChunk, $originalContents);
+ } else {
+ $out = $binaryChunk;
+ }
+ if ($reverseBinaryChunkType eq "delta") {
+ die "Original content of $fullPath mismatches" if $originalContents ne applyGitBinaryPatchDelta($reverseBinaryChunk, $out);
+ }
open FILE, ">", $fullPath or die "Failed to open $fullPath.";
- print FILE $binaryChunk;
+ print FILE $out;
close FILE;
if ($isFileAddition) {
scmAdd($fullPath);
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list