WebKitTools:
authorddkilzer <ddkilzer@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 4 Jun 2006 18:52:24 +0000 (18:52 +0000)
committerddkilzer <ddkilzer@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 4 Jun 2006 18:52:24 +0000 (18:52 +0000)
        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: https://svn.webkit.org/repository/webkit/trunk@14718 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebKitTools/ChangeLog
WebKitTools/Scripts/svn-apply
WebKitTools/Scripts/svn-create-patch
WebKitTools/Scripts/svn-unapply

index f0a0355d6aefdac982361c586c1c0bd1fd2983f9..ba5c48e2b4829836cce64df65981453e5946baa3 100644 (file)
@@ -1,3 +1,14 @@
+2006-06-04  David Kilzer  <ddkilzer@kilzer.net>
+
+        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.
+
 2006-06-03  David Kilzer  <ddkilzer@kilzer.net>
 
         Reviewed by Maciej.
index f96d7b38c38257ef0eb1135ae007f8ce00c3a52c..299d70e36bd4ee32438a614988c29477aa10fb87 100755 (executable)
 #       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 @@ sub patch
 
     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 patch
     }
 }
 
+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;
index 1dd11f73104b70c0665234c8d40da87048ec1c99..0c3f903643b9ce18bcfbac216e92f26a491f3746 100755 (executable)
@@ -1,6 +1,6 @@
 #!/usr/bin/perl -w
 
-# Copyright (C) 2005 Apple Computer, Inc.  All rights reserved.
+# Copyright (C) 2005, 2006 Apple Computer, Inc.  All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions
 #
 #   Uses the real diff, not svn's built-in diff.
 #   Always passes "-p" to diff so it will try to include function names.
+#   Handles binary files (encoded as a base64 chunk of text).
 #
 # Missing features:
 #
 #   Sort the diffs, since svn emits them in a seemingly-random order.
-#   Handle binary files (some text form of the binary file).
 #   Handle moved files.
 
 use strict;
@@ -44,8 +44,10 @@ use Cwd;
 use Getopt::Long;
 use Time::gmtime;
 use File::stat;
+use File::Spec;
 use POSIX qw(:errno_h);
 use Config;
+use MIME::Base64;
 
 my $startDir = getcwd();
 my %paths;
@@ -115,13 +117,18 @@ sub diff
     chdir $dir or die;
     open DIFF, "svn diff --diff-cmd diff -x -uNp '$base' |" or die;
     my $indexPath;
+    my $binaryPath;
     while (<DIFF>) {
         if (/^Index: (.*)/) {
+            # New patch just started
             $indexPath = $1;
             if ($dir ne ".") {
                 $indexPath = "$dir/$indexPath";
                 s/Index: .*/Index: $indexPath/;
             }
+            # Output encoded binary contents of last patch before beginning of next patch
+            outputBinaryContent(File::Spec->abs2rel($binaryPath, $dir)) if ($binaryPath);
+            undef $binaryPath;
         }
         if ($indexPath) {
             # Fix paths on diff, ---, and +++ lines to match preceding Index: line.
@@ -129,13 +136,36 @@ sub diff
             s/^--- \S+/--- $indexPath/;
             s/^\+\+\+ \S+/+++ $indexPath/ && undef $indexPath;
         }
+        if ($binaryPath) {
+            # Fix path on "Property changes on:" line to match preceding Index: line.
+            s/^(Property changes on:) \S+/$1 $indexPath/;
+        }
+        $binaryPath = $indexPath if (/^Cannot display: file marked as a binary type\.$/);
         print;
     }
     close DIFF;
+    # Output encoded binary contents if the last patch was binary
+    outputBinaryContent(File::Spec->abs2rel($binaryPath, $dir)) if ($binaryPath);
     chdir $startDir or die;
     print STDERR $errors;
 }
 
+# Outputs binary content as encoded text
+sub outputBinaryContent
+{
+    my ($path) = @_;
+    # Deletion
+    return if (! -e $path);
+    # Addition or Modification
+    my $buffer;
+    open BINARY, $path  or die;
+    while (read(BINARY, $buffer, 60*57)) {
+        print encode_base64($buffer);
+    }
+    close BINARY;
+    print "\n";
+}
+
 # Generate the diff for each passed file or directory.
 for my $path (sort keys %paths) {
     diff($path);
index 14fa4f0d2f6c9f57b518161f2486af911517c3c5..7e04ff90b7c476655d3f09c4eeff2318d55fe759 100755 (executable)
 #       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).
 #   Use version numbers in the patch file and do a 3-way merge.
 #   When reversing an addition, check that the file matches what's being removed.
@@ -97,35 +97,34 @@ sub patch
 
     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";
             unapplyPatch($patch, $fullpath, ["--fuzz=3"]);
             unlink("${fullpath}.orig") if (! $changeLogDotOrigExisted);
-        }
-        else {
+        } else {
             unapplyPatch($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.
         if ($prefix) {
             chdir $prefix or die "Failed to chdir to $prefix";
         }
 
-        if ($deletion) {
-            # Reverse a deletion.
-            system "svn", "revert", "$base";
-        } else {
-            # Reverse an addition.
-            system "svn", "rm", "--force", $base;
-        }
+        # Reverse change by deleting current copy if it exists first
+        unlink($base) if (-e $base);
+
+        # Then run svn revert
+        system "svn", "revert", "$base";
 
         chdir $startDir or die;
     }