bdfe5854b3a9bf7c253277726ca766540ee1e12f
[WebKit-https.git] / WebKitTools / Scripts / svn-create-patch
1 #!/usr/bin/perl -w
2
3 # Copyright (C) 2005 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 # Simplified and improved "svn diff" script for WebKit Open Source Project, used to make patches.
30
31 # Differences from standard "svn diff":
32 #
33 #   Uses the real diff, not svn's built-in diff.
34 #   Always passes "-p" to diff so it will try to include function names.
35 #
36 # Missing features:
37 #
38 #   Sort the diffs, since svn emits them in a seemingly-random order.
39 #   Handle binary files (some text form of the binary file).
40 #   Handle moved files.
41
42 use strict;
43 use Cwd;
44 use Getopt::Long;
45 use Time::gmtime;
46 use File::stat;
47 use POSIX qw(:errno_h);
48 use Config;
49
50 my $startDir = getcwd();
51 my %paths;
52
53 # Create list of paths to diff.
54 if (!@ARGV) {
55     $paths{"."} = 1;
56 } else {
57     for my $file (@ARGV) {
58         die "can't handle absolute paths like \"$file\"\n" if $file =~ m|^/|;
59         die "can't handle empty string path\n" if $file eq "";
60         die "can't handle path with ' in the name like \"$file\"\n" if $file =~ /'/; # ' (keep Xcode syntax highlighting happy)
61
62         my $untouchedFile = $file;
63         
64         # Add a leading and trailing slash to simplify logic below.
65         $file = "/$file/";
66
67         # Remove repeated slashes.
68         $file =~ s|//+|/|g;
69
70         # Remove meaningless sequences involving ".".
71         $file =~ s|/\./|/|g;
72
73         # Remove meaningless sequences involving "..".
74         $file =~ s|/[^./]/\.\./|/|g;
75         $file =~ s|/[^/]+[^./]/\.\./|/|g;
76         $file =~ s|/[^./][^/]+/\.\./|/|g;
77         die "can't handle paths with .. like \"$untouchedFile\"\n" if $file =~ m|/\.\./|;
78
79         # Remove the leading and trailing slash.
80         $file =~ s|^/(.*)/$|$1|;
81
82         $paths{$file} = 1;
83     }
84 }
85
86 # Remove any paths that also have a parent listed.
87 for my $path (keys %paths) {
88     my $parent = $path;
89     while ($parent =~ s|/+[^/]+$||) {
90         if ($paths{$parent}) {
91             delete $paths{$path};
92             last;
93         }
94     }
95 }
96
97 sub getDirAndBase
98 {
99     my ($path) = @_;
100     if (-d $path) {
101         $path =~ s|/+$||;
102         return ($path, ".");
103     }
104     return ($1, $2) if $path =~ m|^(.+)/([^/]+)$|;
105     $path !~ m|/| or die "Could not parse path name $path.\n";
106     return (".", $path);
107 }
108
109 # Function to generate a diff.
110 sub diff
111 {
112     my ($path) = @_;
113     my ($dir, $base) = getDirAndBase($path);
114     my $errors = "";
115     chdir $dir or die;
116     open DIFF, "svn diff --diff-cmd diff -x -uNp '$base' |" or die;
117     my $indexPath;
118     while (<DIFF>) {
119         if (/^Index: (.*)/) {
120             $indexPath = $1;
121             if ($dir ne ".") {
122                 $indexPath = "$dir/$indexPath";
123                 s/Index: .*/Index: $indexPath/;
124             }
125         }
126         if ($indexPath) {
127             # Fix paths on diff, ---, and +++ lines to match preceding Index: line.
128             s/\S+$/$indexPath/ if /^diff/;
129             s/^--- \S+/--- $indexPath/;
130             s/^\+\+\+ \S+/+++ $indexPath/;
131         }
132         print;
133     }
134     close DIFF;
135     chdir $startDir or die;
136     print STDERR $errors;
137 }
138
139 # Generate the diff for each passed file or directory.
140 for my $path (sort keys %paths) {
141     diff($path);
142 }