Got rid of extra comparisons in compare_targets().
[rsync/rsync-patches.git] / verify-patches
CommitLineData
3a849c85
WD
1#!/usr/bin/perl
2
3use strict;
4
5chdir('patches') if -d 'patches';
6
7if (!-f 'verify-patches') {
8 die <<EOT;
9Please run this script from the root of the rsync dir or
10from inside the patches subdir.
11EOT
12}
13
b1a4cc32
WD
14$ENV{'TZ'} = 'UTC';
15my $CONF_OPTS = '-C';
3a849c85 16
b1a4cc32 17my($has_dependencies, @new, @rejects);
3a849c85
WD
18
19END {
20 &restore_cvsdir;
b1a4cc32 21 system "rsync -a --delete cvsdir/ workdir/" if -d 'cvsdir';
3a849c85
WD
22};
23
24my $root;
25open(IN, '../CVS/Root') or die $!;
26chomp($root = <IN>);
27close IN;
28
b1a4cc32
WD
29mkdir('tmp', 0777) unless -d 'tmp';
30chdir('tmp') or die "Unable to chdir to 'tmp'";
3a849c85
WD
31
32mkdir('workdir') unless -d 'workdir';
33open(OUT, '>exclude') or die $!;
34print OUT <<EOT;
b1a4cc32 35CVS
3a849c85
WD
36proto.h
37configure
38config.h.in
39rsync.1
40rsyncd.conf.5
41EOT
42close OUT;
43
b1a4cc32 44print "Using CVS to update the tmp/cvsdir copy of the source.\n";
3a849c85
WD
45system qq|cvs -d "$root" co -d cvsdir rsync|;
46
47@ARGV = glob('../*.diff') unless @ARGV;
48
49DIFF:
50foreach my $diff (@ARGV) {
51 next unless $diff =~ /\.diff$/;
52 next if $diff =~ /gzip-rsyncable\.diff$/;
53 $diff =~ s#^(patches|\.\.)/##;
54
55 open(IN, "../$diff") or die $!;
56 while (<IN>) {
57 last if /^--- /;
58 if (/^Depends-On-Patch: (\S+.diff)$/) {
59 my $dep = $1;
60 $has_dependencies = 1;
61 print "\nApplying dependency patch $dep\n";
b1a4cc32 62 if (system("patch -d cvsdir -p0 -b -Vt -Zf <../$dep") != 0) {
3a849c85
WD
63 print "Unable to cleanly apply depenency patch -- skipping $diff\n";
64 &restore_cvsdir;
65 next DIFF;
66 }
67 }
68 }
69 close IN;
70
b1a4cc32
WD
71 my $default = apply_patch($diff);
72
3a849c85 73 while (1) {
b1a4cc32
WD
74 print "\n----------- $diff ------------\n",
75 "\nFix rejects, Diff create, Edit both diffs, Update patch,\n",
76 "Apply patch again, !(CMD), Build rsync, Next, Quit: [$default] ";
3a849c85
WD
77 my $ans = <STDIN>;
78 chomp $ans;
b1a4cc32
WD
79 $ans = $default if $ans eq '';
80 if ($ans =~ /^!(.*)/) {
81 my $cmd = $1 || $ENV{'SHELL'};
3a849c85 82 chdir('workdir') or die $!;
b1a4cc32 83 system $cmd;
3a849c85 84 chdir('..') or die $!;
b1a4cc32
WD
85 $default = 'D,E';
86 next;
87 }
88 if ($ans =~ /^\S*F/i) {
3a849c85
WD
89 chdir('workdir') or die $!;
90 system "vim @rejects";
91 chdir('..') or die $!;
b1a4cc32
WD
92 $default = 'D,E';
93 }
94 if ($ans =~ /^\S*D/i) {
95 $default = generate_new_patch($diff);
96 }
97 if ($ans =~ /^\S*E/i) {
98 chdir('workdir') or die $!;
99 system "vim -d ../../$diff ../new.patch";
100 chdir('..') or die $!;
101 $default = 'U,A';
102 }
103 if ($ans =~ /^\S*U/i) {
3a849c85
WD
104 system "cp -p new.patch ../$diff";
105 print "\nUpdated $diff from new.patch\n";
106 $default = 'A';
b1a4cc32
WD
107 }
108 if ($ans =~ /^\S*A/i) {
109 $default = apply_patch($diff);
110 }
111 if ($ans =~ /^\S*B/i) {
112 if (!-f 'workdir/Makefile') {
113 open(IN, '../../Makefile') or die $!;
114 open(OUT, '>workdir/Makefile') or die $!;
115 print OUT "srcdir=.\n\n";
116 while (<IN>) {
117 last if /^gen:/;
118 }
119 print OUT $_;
120 while (<IN>) {
121 last if /^clean:/;
122 print OUT $_;
123 }
124 close IN;
125 close OUT;
126 }
127 chdir('workdir') or die $!;
128 system "make gen; ./configure $CONF_OPTS; make";
129 chdir('..') or die $!;
130 $default = '!make test';
131 }
132 if ($ans =~ /^\S*Q/i) {
3a849c85
WD
133 exit;
134 }
b1a4cc32
WD
135 if ($ans =~ /^\S*N/i) {
136 last;
137 }
3a849c85
WD
138 }
139
140 &restore_cvsdir;
141}
142
143exit;
144
145
b1a4cc32
WD
146sub apply_patch
147{
148 my($diff) = @_;
149
150 undef @new;
151 my $def = 'N';
152 system "rsync -a --delete cvsdir/ workdir/";
153 print "\n";
154 open(IN, "patch -d workdir -p0 --no-backup-if-mismatch -Zf <../$diff |") or die $!;
155 while (<IN>) {
156 print $_;
157 chomp;
158 if (s/^patching file //) {
159 push(@new, $_) unless -f "cvsdir/$_";
160 } elsif (s/.* saving rejects to file //) {
161 push(@rejects, $_);
162 } elsif (/^Hunk #\d+ FAILED/) {
163 $def = 'F';
164 } elsif (/^Hunk #\d+ succeeded/) {
165 $def = 'E' unless $def eq 'F,D,E';
166 }
167 }
168 close IN;
169 if ($def eq 'N') {
170 generate_new_patch($diff);
171 }
172 $def;
173}
174
3a849c85
WD
175sub generate_new_patch
176{
177 my($diff) = @_;
178
179 foreach (@new) {
180 system "touch -r workdir/$_ cvsdir/$_";
181 }
182 open(IN, "../$diff") or die $!;
183 open(OUT, '>new.patch') or die $!;
184 while (<IN>) {
185 last if /^--- /;
186 print OUT $_;
187 }
188 close IN;
189 open(IN, 'diff --exclude-from=exclude -upr cvsdir workdir |') or die $!;
190 while (<IN>) {
191 next if /^(diff -|Index: |Only in )/;
192 s#^\Q--- cvsdir/\E#--- orig/#;
193 s#^\Q+++ workdir/\E#+++ #;
194 s#(\.000000000)? \+0000$##;
195 print OUT $_;
196 }
197 close IN;
198 close OUT;
199 foreach (@new) {
200 unlink("cvsdir/$_");
201 }
b1a4cc32
WD
202 if (system("diff ../$diff new.patch >/dev/null") == 0) {
203 print "\n(New patch is identical to old.)\n";
204 return 'N';
205 }
206 'E';
3a849c85
WD
207}
208
209sub restore_cvsdir
210{
211 return unless $has_dependencies;
212 $has_dependencies = 0;
213
214 foreach (glob('*.~[1-9]~'), glob('*/*.~[1-9]~')) {
215 my $fn;
216 ($fn = $_) =~ s/\.~1~$//;
217 if ($fn eq $_) {
218 unlink($_);
219 } elsif (-r $fn) {
220 rename($_, $fn);
221 } else {
222 unlink($_);
223 unlink($fn);
224 }
225 }
226}