WebKitTools:
[WebKit-https.git] / WebKitTools / Scripts / svn-unapply
1 #!/usr/bin/perl -w
2
3 # Copyright (C) 2005, 2006 Apple Computer, Inc.  All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions
7 # are met:
8 #
9 # 1.  Redistributions of source code must retain the above copyright
10 #     notice, this list of conditions and the following disclaimer. 
11 # 2.  Redistributions in binary form must reproduce the above copyright
12 #     notice, this list of conditions and the following disclaimer in the
13 #     documentation and/or other materials provided with the distribution. 
14 # 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 #     its contributors may be used to endorse or promote products derived
16 #     from this software without specific prior written permission. 
17 #
18 # THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 # DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 # "patch" script for Web Kit Open Source Project, used to apply patches.
30
31 # Differences from invoking "patch -p0 -R":
32 #
33 #   Handles added files (does a svn rm). 
34 #   Handles removed files (does a svn add). 
35 #   Paths from Index: lines are used rather than the paths on the patch lines, which
36 #       makes patches generated by "cvs diff" work (increasingly unimportant since we
37 #       use Subversion now).
38 #   ChangeLog patches use --fuzz=3 to prevent rejects.
39 #   Handles binary files (requires patches made by svn-create-patch).
40 #
41 # Missing features:
42 #
43 #   Handle property changes.
44 #   Handle file moves (requires patches made by svn-create-patch).
45 #   Use version numbers in the patch file and do a 3-way merge.
46 #   When reversing an addition, check that the file matches what's being removed.
47 #   Notice a patch that's being unapplied at the "wrong level" and make it work anyway.
48 #   Do a dry run on the whole patch and don't do anything if part of the patch is
49 #       going to fail (probably too strict unless we do the ChangeLog thing).
50
51 use strict;
52 use Cwd;
53
54 my $startDir = getcwd();
55
56 my $indexPath;
57 my $patch;
58 while (<>) {
59     s/\r//g;
60     chomp;
61     if (/^Index: (.*)/) {
62         $indexPath = $1;
63         if ($patch) {
64             patch($patch);
65             $patch = "";
66         }
67     }
68     if ($indexPath) {
69         # Fix paths on diff, ---, and +++ lines to match preceding Index: line.
70         s/^--- \S+/--- $indexPath/;
71         if (s/^\+\+\+ \S+/+++ $indexPath/) {
72             $indexPath = "";
73         }
74     }
75     $patch .= $_;
76     $patch .= "\n";
77 }
78 patch($patch);
79
80 sub unapplyPatch
81 {
82     my ($patch, $fullpath, $options) = @_;
83     $options = [] if (! $options);
84     my $command = "patch " . join(" ", "-p0", "-R", @{$options});
85     open PATCH, "| $command" or die "Failed to patch $fullpath\n";
86     print PATCH $patch;
87     close PATCH;
88 }
89
90 sub patch
91 {
92     my ($patch) = @_;
93     return if !$patch;
94
95     $patch =~ m|^Index: ((([^/\n]*/)*)([^/\n]+))| or die "Failed to find Index: in \"$patch\"\n";
96     my ($fullpath, $prefix, $base) = ($1, $2, $4);
97
98     my $deletion = 0;
99     my $addition = 0;
100     my $isBinary = 0;
101
102     $addition = 1 if $patch =~ /\n--- .+\(revision 0\)\n/;
103     $deletion = 1 if $patch =~ /\n@@ .* \+0,0 @@/;
104     $isBinary = 1 if $patch =~ /\nCannot display: file marked as a binary type\./;
105
106     if (!$addition && !$deletion && !$isBinary) {
107         # Standard patch, patch tool can handle this.
108         if ($base eq "ChangeLog") {
109             my $changeLogDotOrigExisted = -f "${fullpath}.orig";
110             unapplyPatch($patch, $fullpath, ["--fuzz=3"]);
111             unlink("${fullpath}.orig") if (! $changeLogDotOrigExisted);
112         } else {
113             unapplyPatch($patch, $fullpath);
114         }
115     } else {
116         # Either a deletion, an addition or a binary change.
117
118         # Change directory down into the directory in question.
119         if ($prefix) {
120             chdir $prefix or die "Failed to chdir to $prefix";
121         }
122
123         # Reverse change by deleting current copy if it exists first
124         unlink($base) if (-e $base);
125
126         # Then run svn revert
127         system "svn", "revert", "$base";
128
129         chdir $startDir or die;
130     }
131 }