# 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.
use strict;
use Cwd;
use Getopt::Long;
+use MIME::Base64;
my $merge = 0;
GetOptions("merge" => \$merge);
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";
}
}
}
+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;