WebKitTools:

        Reviewed by darin.

        http://bugzilla.opendarwin.org/show_bug.cgi?id=9299
        Teach svn-create-patch and friends to work with binary files

        * Scripts/svn-apply: Updated to use base64-encoded text for binary files when applying patches.
        * Scripts/svn-create-patch: Updated to include binary file content as base64-encoded text in patches.
        * Scripts/svn-unapply: Updated to recognize binary files when unapplying patches.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@14718 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/WebKitTools/Scripts/svn-apply b/WebKitTools/Scripts/svn-apply
index f96d7b3..299d70e 100755
--- a/WebKitTools/Scripts/svn-apply
+++ b/WebKitTools/Scripts/svn-apply
@@ -38,11 +38,11 @@
 #       makes patches generated by "cvs diff" work (increasingly unimportant since we
 #       use Subversion now).
 #   ChangeLog patches use --fuzz=3 to prevent rejects.
+#   Handles binary files (requires patches made by svn-create-patch).
 #
 # Missing features:
 #
 #   Handle property changes.
-#   Handle binary files (requires patches made by svn-create-patch).
 #   Handle file moves (requires patches made by svn-create-patch).
 #   When doing a removal, check that old file matches what's being removed.
 #   Notice a patch that's being applied at the "wrong level" and make it work anyway.
@@ -52,6 +52,7 @@
 use strict;
 use Cwd;
 use Getopt::Long;
+use MIME::Base64;
 
 my $merge = 0;
 GetOptions("merge" => \$merge); 
@@ -127,42 +128,46 @@
 
     my $deletion = 0;
     my $addition = 0;
+    my $isBinary = 0;
 
     $addition = 1 if $patch =~ /\n--- .+\(revision 0\)\n/;
     $deletion = 1 if $patch =~ /\n@@ .* \+0,0 @@/;
+    $isBinary = 1 if $patch =~ /\nCannot display: file marked as a binary type\./;
 
-    if (!$addition && !$deletion) {
+    if (!$addition && !$deletion && !$isBinary) {
         # Standard patch, patch tool can handle this.
         if ($base eq "ChangeLog") {
             my $changeLogDotOrigExisted = -f "${fullpath}.orig";
             applyPatch($patch, $fullpath, ["--fuzz=3"]);
             unlink("${fullpath}.orig") if (! $changeLogDotOrigExisted);
-        }
-        else {
+        } else {
             applyPatch($patch, $fullpath);
         }
     } else {
-        # Either a deletion or an addition.
+        # Either a deletion, an addition or a binary change.
 
         # Change directory down into the directory in question.
         chdirAddingDirectoriesIfNeeded($prefix);
 
-        if ($deletion) {
+        if ($isBinary) {
+            # Binary change
+            handleBinaryChange($base, $patch);
+        } elsif ($deletion) {
             # Deletion.
             system "svn", "rm", $base;
         } else {
             # Addition.
-            my $file = $patch;
-            if ($file !~ s/^(.*\n)*@@[^\n]+@@\n//) {
-                # Empty file.
-                $file = "";
+            my $contents = $patch;
+            if ($contents !~ s/^(.*\n)*@@[^\n]+@@\n//) {
+                # Empty contents.
+                $contents = "";
             } else {
-                # Non-empty file: Remove leading + signs.
-                $file =~ s/^\+//;
-                $file =~ s/\n\+/\n/g;
+                # Non-empty contents: Remove leading + signs.
+                $contents =~ s/^\+//;
+                $contents =~ s/\n\+/\n/g;
             }
             open FILE, ">", $base or die;
-            print FILE $file;
+            print FILE $contents;
             close FILE;
             system "svn", "add", "$base";
         }
@@ -171,6 +176,30 @@
     }
 }
 
+sub handleBinaryChange
+{
+    my ($base, $contents) = @_;
+    if ($contents =~ m#((\n[A-Za-z0-9+/]{76})+\n[A-Za-z0-9+/=]{4,76}\n)\n#) {
+        # Addition or Modification
+        open FILE, ">", $base or die;
+        print FILE decode_base64($1);
+        close FILE;
+        open SVN, "svn stat '$base' |" or die;
+        my $svnStatus = <SVN>;
+        close SVN;
+        if (substr($svnStatus, 0 ,1) eq "?") {
+            # Addition
+            system "svn", "add", "$base";
+        } else {
+            # Modification
+            print $svnStatus;
+        }
+    } else {
+        # Deletion
+        system "svn", "rm", "$base";
+    }
+}
+
 sub chdirAddingDirectoriesIfNeeded
 {
     my $path = shift;