Subversion Repositories DevTools

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4270 alewis 1
#!/usr/bin/perl -w
2
#
3
# patch - apply a diff file to an original
4
#
5
# mail tgy@chocobo.org < bug_reports
6
#
7
# Copyright (c) 1999 Moogle Stuffy Software.  All rights reserved.
8
# You may play with this software in accordance with the Perl Artistic License.
9
 
10
use strict;
11
 
12
my $VERSION = '0.26';
13
 
14
$|++;
15
 
16
if (@ARGV && $ARGV[0] eq '-v') {
17
    print split /^    /m, qq[
18
        This is patch $VERSION written in Perl.
19
 
20
        Copyright (c) 1999 Moogle Stuffy Software.  All rights reserved.
21
 
22
        You may play with this software in accordance with the
23
        Perl Artistic License.
24
    ];
25
    exit;
26
}
27
 
28
my ($patchfile, @options);
29
 
30
if (@ARGV) {
31
    require Getopt::Long;
32
    Getopt::Long::Configure(qw/
33
        bundling
34
        no_ignore_case
35
    /);
36
 
37
    # List of supported options and acceptable arguments.
38
    my @desc = qw/
39
        suffix|b=s              force|f                 reject-file|r=s
40
        prefix|B=s              batch|t                 reverse|R
41
        context|c               fuzz|F=i                silent|quiet|s
42
        check|C                 ignore-whitespace|l     skip|S
43
        directory|d=s           normal|n                unified|u
44
        ifdef|D=s               forward|N               version|v
45
        ed|e                    output|o=s              version-control|V=s
46
        remove-empty-files|E    strip|p=i               debug|x=i
47
    /;
48
 
49
    # Each patch may have its own set of options.  These are separated by
50
    # a '+' on the command line.
51
    my @opts;
52
    for (@ARGV, '+') {  # Now '+' terminated instead of separated...
53
        if ($_ eq '+') {
54
            push @options, [splice @opts, 0];
55
        } else {
56
            push @opts, $_;
57
        }
58
    }
59
 
60
    # Parse each set of options into a hash.
61
    my $next = 0;
62
    for (@options) {
63
        local @ARGV = @$_;
64
        Getopt::Long::GetOptions(\my %opts, @desc);
65
        $opts{origfile} = shift;
66
        $_ = \%opts;
67
        $patchfile = shift unless $next++;
68
    }
69
}
70
 
71
$patchfile = '-' unless defined $patchfile;
72
 
73
my $patch = Patch->new(@options);
74
 
75
tie *PATCH, Pushback => $patchfile or die "Can't open '$patchfile': $!";
76
 
77
# Extract patches from patchfile.  We unread/pushback lines by printing to
78
# the PATCH filehandle:  'print PATCH'
79
PATCH:
80
while (<PATCH>) {
81
    if (/^(\s*)(\@\@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? \@\@\n)/) {
82
        # UNIFIED DIFF
83
        my ($space, $range, $i_start, $i_lines, $o_start, $o_lines) =
84
           ($1,     $2,     $3,       $4 || 1,  $5,       $6 || 1);
85
        $patch->bless('unified') or next PATCH;
86
        my @hunk;
87
        my %saw = map {$_, 0} split //, ' +-';
88
        my $re = qr/^$space([ +-])/;
89
        while (<PATCH>) {
90
            unless (s/$re/$1/) {
91
                $patch->note("Short hunk ignored.\n");
92
                $patch->reject($range, @hunk);
93
                print PATCH;
94
                next  PATCH;
95
            }
96
            push @hunk, $_;
97
            $saw{$1}++;
98
            last if $saw{'-'} + $saw{' '} == $i_lines
99
                 && $saw{'+'} + $saw{' '} == $o_lines;
100
        }
101
        $patch->apply($i_start, $o_start, @hunk)
102
            or $patch->reject($range, @hunk);
103
    } elsif (/^(\s*)\*{15}$/) {
104
        # CONTEXT DIFF
105
        my $space = $1;
106
        $_ = <PATCH>;
107
        unless (/^$space(\*\*\* (\d+)(?:,(\d+))? \*\*\*\*\n)/) {
108
            print PATCH;
109
            next  PATCH;
110
        }
111
        my ($i_range, $i_start, $i_end, @i_hunk) = ($1, $2, $3 || $2);
112
        my ($o_range, $o_start, $o_end, @o_hunk);
113
        $patch->bless('context') or next PATCH;
114
        my $o_hunk = qr/^$space(--- (\d+)(?:,(\d+))? ----\n)/;
115
        my $re = qr/^$space([ !-] )/;
116
        $_ = <PATCH>;
117
        if (/$o_hunk/) {
118
            ($o_range, $o_start, $o_end) = ($1, $2, $3 || $2);
119
        } else {
120
            print PATCH;
121
            for ($i_start..$i_end) {
122
                $_ = <PATCH>;
123
                unless (s/$re/$1/) {
124
                    $patch->note("Short hunk ignored.\n");
125
                    $patch->reject($i_range, @i_hunk);
126
                    print PATCH;
127
                    next  PATCH;
128
                }
129
                push @i_hunk, $_;
130
            }
131
            $_ = <PATCH>;
132
            unless (/$o_hunk/) {
133
                $patch->note("Short hunk ignored...no second line range.\n");
134
                $patch->reject($i_range, @i_hunk);
135
                print PATCH;
136
                next  PATCH;
137
            }
138
            ($o_range, $o_start, $o_end) = ($1, $2, $3 || $2);
139
        }
140
        $re = qr/^$space([ !+] )/;
141
        $_ = <PATCH>;
142
        if (/^$space\*{15}$/) {
143
            print PATCH;
144
        } else {
145
            print PATCH;
146
            for ($o_start..$o_end) {
147
                $_ = <PATCH>;
148
                unless (s/$re/$1/) {
149
                    $patch->note("Short hunk ignored.\n");
150
                    $patch->reject($i_range, @i_hunk, $o_range, @o_hunk);
151
                    print PATCH;
152
                    next  PATCH;
153
                }
154
                push @o_hunk, $_;
155
            }
156
        }
157
        $patch->apply($i_start, $o_start, \@i_hunk, \@o_hunk)
158
            or $patch->reject($i_range, @i_hunk, $o_range, @o_hunk);
159
    } elsif (/^(\s*)((\d+)(?:,(\d+))?([acd])(\d+)(?:,(\d+))?\n)/) {
160
        # NORMAL DIFF
161
        my ($space, $range, $i_start, $i_end, $cmd, $o_start, $o_end) =
162
           ($1,     $2,     $3,     $4 || $3, $5,   $6,       $7 || $6);
163
        $patch->bless('normal') or next PATCH;
164
        my (@d_hunk, @a_hunk);
165
        my $d_re = qr/^$space< /;
166
        my $a_re = qr/^$space> /;
167
        if ($cmd eq 'c' || $cmd eq 'd') {
168
            for ($i_start..$i_end) {
169
                $_ = <PATCH>;
170
                unless (s/$d_re//) {
171
                    $patch->note("Short hunk ignored.\n");
172
                    $patch->reject($range, @d_hunk);
173
                    print PATCH;
174
                    next  PATCH;
175
                }
176
                push @d_hunk, $_;
177
            }
178
        }
179
        if ($cmd eq 'c') {
180
            $_ = <PATCH>;
181
            unless ($_ eq "---\n") {
182
                $patch->note("Short hunk ignored...no '---' separator.\n");
183
                $patch->reject($range, @d_hunk);
184
                print PATCH;
185
                next  PATCH;
186
            }
187
        }
188
        if ($cmd eq 'c' || $cmd eq 'a') {
189
            for ($o_start..$o_end) {
190
                $_ = <PATCH>;
191
                unless (s/$a_re//) {
192
                    $patch->note("Short hunk ignored.\n");
193
                    $patch->reject($range, @d_hunk, "---\n", @a_hunk);
194
                    print PATCH;
195
                    next  PATCH;
196
                }
197
                push @a_hunk, $_;
198
            }
199
        }
200
        $patch->apply($i_start, $o_start, $cmd, \@d_hunk, \@a_hunk)
201
            or $patch->reject($range, @d_hunk, "---\n", @a_hunk);
202
    } elsif (/^(\s*)\d+(?:,\d+)?[acd]$/) {
203
        # ED SCRIPT
204
        my $space = qr/^$1/;
205
        $patch->bless('ed') or next PATCH;
206
        print PATCH;
207
        my @cmd;
208
        ED:
209
        while (<PATCH>) {
210
            unless (s/$space// && m!^\d+(?:,\d+)?([acd]|s\Q/^\.\././\E)$!) {
211
                print PATCH;
212
                last ED;
213
            }
214
            push @cmd, [$_];
215
            $1 =~ /^[ac]$/ or next;
216
            while (<PATCH>) {
217
                unless (s/$space//) {
218
                    print PATCH;
219
                    last ED;
220
                }
221
                push @{$cmd[-1]}, $_;
222
                last if /^\.$/;
223
            }
224
        }
225
        $patch->apply(@cmd) or $patch->reject(map @$_, @cmd);
226
    } else {
227
        # GARBAGE
228
        $patch->garbage($_);
229
    }
230
}
231
 
232
close PATCH;
233
 
234
if (ref $patch eq 'Patch') {
235
    $patch->note("Hmm...  I can't seem to find a patch in there anywhere.\n");
236
} else {
237
    $patch->end;
238
}
239
 
240
$patch->note("done\n");
241
exit $patch->error ? 1 : 0;
242
 
243
END {
244
    close STDOUT || die "$0: can't close stdout: $!\n";
245
    $? = 1 if $? == 255;  # from die
246
}
247
 
248
 
249
 
250
 
251
 
252
package Patch;
253
 
254
use vars qw/$ERROR/;
255
 
256
# Class data.
257
BEGIN {
258
    $ERROR = 0;
259
}
260
 
261
sub import {
262
    no strict 'refs';
263
    *{caller() . '::throw'} = \&throw;
264
    @{caller() . '::ISA'}   = 'Patch';
265
}
266
 
267
# Simple throw/catch error handling.
268
sub throw {
269
    $@ = join '', @_;
270
    $@ .= sprintf " at %s line %d\n", (caller)[1..2] unless $@ =~ /\n\z/;
271
    goto CATCH;
272
}
273
 
274
# Prints a prompt message and returns response.
275
sub prompt {
276
    print @_;
277
    local $_ = <STDIN>;
278
    chomp;
279
    $_;
280
}
281
 
282
# Constructs a Patch object.
283
sub new {
284
    my $class = shift;
285
    my %copy = %{$_[0]} if ref $_[0];
286
    bless {
287
        %copy,
288
        options => [@_],
289
        garbage => [],
290
        rejects => [],
291
    }, $class;
292
}
293
 
294
# Blesses object into a subclass.
295
sub bless {
296
    my $type = pop;
297
    my $class = "Patch::\u$type";
298
 
299
    my ($options, $garbage) = @{$_[0]}{'options', 'garbage'};
300
 
301
    # New hunk, same patch.
302
    $_[0]{hunk}++, return 1 if $_[0]->isa($class) && ! @$garbage;
303
 
304
    # Clean up previous Patch object first.
305
    $_[0]->end;
306
 
307
    # Get options/switches for new patch.
308
    my $self = @$options > 1    ? shift @$options :
309
               @$options == 1   ? { %{$options->[0]} } :
310
               {};
311
    bless $self, $class;
312
 
313
    # 'options' and 'garbage'  are probably better off as class
314
    # data.  Why didn't I do that before?  But it's not broken
315
    # so I'm not fixing it.
316
    $self->{options} = $options;    # @options 
317
    $self->{garbage} = [];          # garbage lines
318
    $self->{i_pos}   = 0;           # current position in 'in' file
319
    $self->{o_pos}   = 0;           # just for symmetry
320
    $self->{i_lines} = 0;           # lines read in 'in' file
321
    $self->{o_lines} = 0;           # lines written to 'out' file
322
    $self->{hunk}    = 1;           # current hunk number
323
    $self->{rejects} = [];          # save rejected hunks here
324
    $self->{fuzz}    = 2  unless defined $self->{fuzz} && $self->{fuzz} >= 0;
325
    $self->{ifdef}   = '' unless defined $self->{ifdef};
326
 
327
    # Skip patch?
328
    $self->{skip} and $self->skip;
329
 
330
    # -c, -e, -n, -u
331
    $self->{$_} and $type eq $_ || $self->skip("Not a $_ diff!\n")
332
        for qw/context ed normal unified/;
333
 
334
    # Speculate to user.
335
    my $n = $type eq 'ed' ? 'n' : '';
336
    $self->note("Hmm...  Looks like a$n $type diff to me...\n");
337
 
338
    # Change directories.
339
    for ($self->{directory}) {
340
        defined or last;
341
        chdir $_ or $self->skip("Can't chdir '$_': $!\n");
342
    }
343
 
344
    # Get original file to patch...
345
    my $orig = $self->{origfile};                   # ...from -o
346
 
347
    unless (defined $orig) {
348
        $orig = $self->rummage($garbage);           # ...from leading garbage
349
        if (defined $orig) {
350
            $self->note(
351
                "The text leading up to this was:\n",
352
                "--------------------------\n",
353
                map("|$_", @$garbage),
354
                "--------------------------\n",
355
            );
356
        } else {
357
            $self->skip if $self->{force} || $self->{batch};
358
            $orig = prompt ('File to patch: ');     # ...from user
359
        }
360
    }
361
 
362
    # Make sure original file exists.
363
    if ($self->{force} || $self->{batch}) {
364
        -e $orig or $self->skip;
365
    } else {
366
        until (-e $orig) {
367
            $self->skip unless prompt (
368
                'No file found--skip this patch? [n] '
369
            ) =~ /^[yY]/;
370
            $orig = prompt (
371
                'File to patch: '
372
            );
373
        }
374
    }
375
 
376
    my ($in, $out);
377
 
378
    # Create backup file.  I have no clue what Plan A is really supposed to be.
379
    if ($self->{check}) {
380
        $self->note("Checking patch against file $orig using Plan C...\n");
381
        ($in, $out) = ($orig, '');
382
    } elsif (defined $self->{output}) {
383
        $self->note("Patching file $orig using Plan B...\n");
384
        local $_ = $self->{output};
385
        $self->skip if -e && not rename $_, $self->backup($_) and
386
            $self->{force} || $self->{batch} || prompt (
387
                'Failed to backup output file--skip this patch? [n] '
388
            ) =~ /^[yY]/;
389
        ($in, $out) = ($orig, $self->{output});
390
    } else {
391
        $self->note("Patching file $orig using Plan A...\n");
392
        my $back = $self->backup($orig);
393
        if (rename $orig, $back) {
394
            ($in, $out) = ($back, $orig);
395
        } else {
396
            $self->skip unless $self->{force} || $self->{batch} or prompt (
397
                'Failed to backup original file--skip this patch? [n] '
398
            ) !~ /^[yY]/;
399
            ($in, $out) = ($orig, $orig);
400
        }
401
    }
402
 
403
    # Open original file.
404
    local *IN;
405
    open IN, "< $in" or $self->skip("Couldn't open INFILE: $!\n");
406
    binmode IN;
407
    $self->{i_fh} = *IN;    # input filehandle
408
    $self->{i_file} = $in;  # input filename
409
 
410
    # Like /dev/null
411
    local *NULL;
412
    tie *NULL, 'Dev::Null';
413
 
414
    # Open output file.
415
    if ($self->{check}) {
416
        $self->{o_fh} = \*NULL;     # output filehandle
417
        $self->{d_fh} = \*NULL;     # ifdef filehandle
418
    } else {
419
        local *OUT;
420
        open OUT, "+> $out" or $self->skip("Couldn't open OUTFILE: $!\n");
421
        binmode OUT;
422
        $|++, select $_ for select OUT;
423
        $self->{o_fh}   = *OUT;
424
        $self->{o_file} = $out;
425
        $self->{d_fh}   = length $self->{ifdef} ? *OUT : \*NULL;
426
    }
427
 
428
    $self->{'reject-file'} = "$out.rej" unless defined $self->{'reject-file'};
429
 
430
    # Check for 'Prereq:' line.
431
    unless ($self->{force}) {
432
        my $prereq = (map /^Prereq:\s*(\S+)/, @$garbage)[-1];
433
        if (defined $prereq) {
434
            $prereq = qr/\b$prereq\b/;
435
            my $found;
436
            while (<IN>) {
437
                $found++, last if /$prereq/;
438
            }
439
            seek IN, 0, 0 or $self->skip("Couldn't seek INFILE: $!\n");
440
            $self->skip if not $found and $self->{batch} || prompt (
441
                'File does not match "Prereq: $1"--skip this patch? [n] '
442
            ) =~ /^[yY]/;
443
        }
444
    }
445
 
446
    SKIP:
447
    $_[0] = $self;
448
}
449
 
450
# Skip current patch.
451
sub skip {
452
    my $self = shift;
453
    $self->note(@_) if @_;
454
    $self->note("Skipping patch...\n");
455
    $self->{skip}++;
456
    goto SKIP;
457
}
458
 
459
# Let user know what's happening.
460
sub note {
461
    my $self = shift;
462
    print @_ unless $self->{silent} || $self->{skip};
463
}
464
 
465
# Add to lines of leading garbage.
466
sub garbage {
467
    push @{shift->{garbage}}, @_;
468
}
469
 
470
# Add to rejected hunks.
471
sub reject {
472
    push @{shift->{rejects}}, [@_];
473
}
474
 
475
# Total number of hunks rejected.
476
sub error {
477
    $ERROR;
478
}
479
 
480
# End of patch clean up.
481
sub end {
482
    my $self = shift;
483
 
484
    return if $self->{skip} || ref $self eq 'Patch';
485
 
486
    $self->print_tail;
487
    $self->print_rejects;
488
    $self->remove_empty_files;
489
}
490
 
491
# Output any lines left in input handle.
492
sub print_tail {
493
    my $self = shift;
494
    print {$self->{o_fh}} readline $self->{i_fh};
495
}
496
 
497
# Output rejected hunks to reject file.
498
sub print_rejects {
499
    my $self = shift;
500
    my @rej = @{$self->{rejects}};
501
 
502
    $ERROR += @rej;
503
 
504
    @rej or return;
505
 
506
    $self->note(
507
        @rej . " out of $self->{hunk} hunks ignored--saving rejects to ",
508
        "$self->{'reject-file'}\n\n"
509
    );
510
    if (open REJ, "> $self->{'reject-file'}") {
511
        print REJ map @$_, @rej;
512
        close REJ;
513
    } else {
514
        $self->note("Couldn't open reject file: $!\n");
515
    }
516
}
517
 
518
# Remove empty files... d'uh
519
sub remove_empty_files {
520
    my $self = shift;
521
    $self->{'remove-empty-files'} or return;
522
    close $self->{o_fh};
523
    defined && -z and $self->note(
524
        unlink($_)
525
        ? "Removed empty file '$_'.\n"
526
        : "Can't remove empty file '$_': $!\n"
527
    ) for $self->{o_file};
528
}
529
 
530
# Go through leading garbage looking for name of file to patch.
531
sub rummage {
532
    my ($self, $garbage) = @_;
533
 
534
    for (reverse @$garbage) {
535
        /^Index:\s*(\S+)/ or next;
536
        my $file = $self->strip($1);
537
        -e $file or next;
538
        return $file;
539
    }
540
 
541
    return;
542
}
543
 
544
# Strip slashes from path.
545
sub strip {
546
    my $self = shift;
547
    my $path = shift;
548
    $path = $_ unless defined $path;
549
 
550
    local $^W;
551
    if (not exists $self->{strip}) {
552
        unless ($path =~ m!^/!) {
553
            $path =~ m!^(.*/)?(.+)$!;
554
            $path = $2 unless -e $1;
555
        }
556
    } elsif ($self->{strip} > 0) {
557
        my $i = $self->{strip};
558
        $path =~ s![^/]*/!! while $i--;
559
    }
560
 
561
    $path;
562
}
563
 
564
# Create a backup file from options.
565
sub backup {
566
    my ($self, $file) = @_;
567
    $file =
568
        $self->{prefix}                 ? "$self->{prefix}$file" :
569
        $self->{'version-control'}      ? $self->version_control_backup(
570
            $file, $self->{'version-control'}) :
571
        $self->{suffix}                 ? "$file$self->{suffix}" :
572
        $ENV{VERSION_CONTROL}           ? $self->version_control_backup(
573
            $file, $ENV{VERSION_CONTROL}) :
574
        $ENV{SIMPLE_BACKUP_SUFFIX}      ? "$file$ENV{SIMPLE_BACKUP_SUFFIX}" :
575
                                          "$file.orig";  # long filename
576
    my ($name, $extension) = $file =~ /^(.+)\.([^.]+)$/
577
        ? ($1, $2)
578
        : ($file, '');
579
    my $ext = $extension;
580
    while (-e $file) {
581
        if ($ext !~ s/([a-z])/\U$1/) {
582
            $ext = $extension;
583
            $name =~ s/.// or die "Couldn't create a good backup filename.\n";
584
        }
585
        $file = $name . $ext;
586
    }
587
    $file;
588
}
589
 
590
# Create a backup file using version control.
591
sub version_control_backup {
592
    my ($self, $file, $version) = @_;
593
    if ($version =~ /^(?:ne|s)/) {  # never|simple
594
        $file .= $self->suffix_backup;
595
    } else {
596
        opendir DIR, '.' or die "Can't open dir '.': $!";
597
        my $re = qr/^\Q$file\E\.~(\d+)~$/;
598
        my @files = map /$re/, readdir DIR;
599
        close DIR;
600
        if (@files) {               # version number already exists
601
            my $next = 1 + (sort {$a <=> $b} @files)[-1];
602
            $file .= ".~$next~";
603
        } else {                    # t|numbered   # nil|existing
604
            $file .= $version =~ /^(?:t|nu)/ ? '.~1~' : $self->suffix_backup;
605
        }
606
    }
607
    $file;
608
}
609
 
610
# Create a backup file using suffix.
611
sub suffix_backup {
612
    my $self = shift;
613
    return $self->{suffix}              if $self->{suffix};
614
    return $ENV{SIMPLE_BACKUP_SUFFIX}   if $ENV{SIMPLE_BACKUP_SUFFIX};
615
    return '.orig';
616
}
617
 
618
# Apply a patch hunk.  The default assumes a unified diff.
619
sub apply {
620
    my ($self, $i_start, $o_start, @hunk) = @_;
621
 
622
    $self->{skip} and throw 'SKIP...ignore this patch';
623
 
624
    if ($self->{reverse}) {
625
        my $not = { qw/ + - - + / };
626
        s/^([+-])/$not->{$1}/ for @hunk;
627
    }
628
 
629
    my @context = map /^[ -](.*)/s, @hunk;
630
    my $position;
631
    my $fuzz = 0;
632
 
633
    if (@context) {
634
        # Find a place to apply hunk where context matches.
635
        for (0..$self->{fuzz}) {
636
            my ($pos, $lines) = ($self->{i_pos}, 0);
637
            while (1) {
638
                ($pos, $lines) = $self->index(\@context, $pos, $lines) or last;
639
                my $line = $self->{i_lines} + $lines + 1;
640
                if ($line >= $i_start) {
641
                    my $off = $line - $i_start;
642
                    $position = [$lines, $off]
643
                        unless $position && $position->[-1] < $off;
644
                    last;
645
                }
646
                $position = [$lines, $i_start - $line];
647
                $pos++, $lines = 1;
648
            }
649
            last if $position;
650
            last unless $hunk[0]  =~ /^ / && shift @hunk
651
                     or $hunk[-1] =~ /^ / && pop @hunk;
652
            @context = map /^[ -](.*)/s, @hunk or last;
653
            $fuzz++;
654
        }
655
        # If there's nowhere to apply the first hunk, we check if it is
656
        # a reversed patch.
657
        if ($self->{hunk} == 1) {
658
            if ($self->{reverse_check}) {
659
                $self->{reverse_check} = 0;
660
                if ($position) {
661
                    unless ($self->{batch}) {
662
                        local $_ = prompt (
663
                            'Reversed (or previously applied) patch detected!',
664
                            '  Assume -R? [y] '
665
                        );
666
                        if (/^[nN]/) {
667
                            $self->{reverse} = 0;
668
                            $position = 0;
669
                            prompt ('Apply anyway? [n] ') =~ /^[yY]/
670
                                or throw 'SKIP...ignore this patch';
671
                        }
672
                    }
673
                } else {
674
                    throw 'SKIP...ignore this patch' if $self->{forward};
675
                }
676
            } else {
677
                unless ($position || $self->{reverse} || $self->{force}) {
678
                    $self->{reverse_check} = 1;
679
                    $self->{reverse} = 1;
680
                    shift;
681
                    return $self->apply(@_);
682
                }
683
            }
684
        }
685
        $position or throw "Couldn't find anywhere to put hunk.\n";
686
    } else {
687
        # No context.  Use given position.
688
        $position = [$i_start - $self->{i_lines} - 1]
689
    }
690
 
691
    my $in  = $self->{i_fh};
692
    my $out = $self->{o_fh};
693
    my $def = $self->{d_fh};
694
    my $ifdef = $self->{ifdef};
695
 
696
    # Make sure we're where we left off.
697
    seek $in, $self->{i_pos}, 0 or throw "Couldn't seek INFILE: $!";
698
 
699
    my $line = $self->{o_lines} + $position->[0] + 1;
700
    my $off  = $line - $o_start;
701
 
702
    # Set to new position.
703
    $self->{i_lines} += $position->[0];
704
    $self->{o_lines} += $position->[0];
705
 
706
    print $out scalar <$in> while $position->[0]--;
707
 
708
    # Apply hunk.
709
    my $was = ' ';
710
    for (@hunk) {
711
        /^([ +-])(.*)/s;
712
        my $cmd = substr $_, 0, 1, '';
713
        if ($cmd eq '-') {
714
            $cmd eq $was or print $def "#ifndef $ifdef\n";
715
            print $def scalar <$in>;
716
            $self->{i_lines}++;
717
        } elsif ($cmd eq '+') {
718
            $cmd eq $was or print $def $was eq ' ' ?
719
                "#ifdef $ifdef\n" :
720
                "#else\n";
721
            print $out $_;
722
            $self->{o_lines}++;
723
        } else {
724
            $cmd eq $was or print $def "#endif /* $ifdef */\n";
725
            print $out scalar <$in>;
726
            $self->{i_lines}++;
727
            $self->{o_lines}++;
728
        }
729
        $was = $cmd;
730
    }
731
    $was eq ' ' or print $def "#endif /* $ifdef */\n";
732
 
733
    # Keep track of where we leave off.
734
    $self->{i_pos} = tell $in;
735
 
736
    # Report success to user.
737
    $self->note("Hunk #$self->{hunk} succeeded at $line.\n");
738
    $self->note("    Offset: $off\n") if $off;
739
    $self->note("    Fuzz: $fuzz\n") if $fuzz;
740
 
741
    return 1;
742
 
743
    # Or report failure.
744
    CATCH:
745
    $self->{skip}++ if $@ =~ /^SKIP/;
746
    $self->note( $self->{skip}
747
        ? "Hunk #$self->{hunk} ignored at $o_start.\n"
748
        : "Hunk #$self->{hunk} failed--$@"
749
    );
750
    return;
751
}
752
 
753
# Find where an array of lines matches in a file after a given position.
754
#   $match  => [array of lines]
755
#   $pos    => search after this position and...
756
#   $lines  => ...after this many lines after $pos
757
# Returns the position of the match and the number of lines between the
758
# starting and matching positions.
759
sub index {
760
    my ($self, $match, $pos, $lines) = @_;
761
    my $in = $self->{i_fh};
762
 
763
    seek $in, $pos, 0 or throw "Couldn't seek INFILE [$in, 0, $pos]: $!";
764
    <$in> while $lines--;
765
 
766
    if ($self->{'ignore-whitespace'}) {
767
        s/\s+/ /g for @$match;
768
    }
769
 
770
    my $tell = tell $in;
771
    my $line = 0;
772
 
773
    while (<$in>) {
774
        s/\s+/ /g if $self->{'ignore-whitespace'};
775
        if ($_ eq $match->[0]) {
776
            my $fail;
777
            for (1..$#$match) {
778
                my $line = <$in>;
779
                $line =~ s/\s+/ /g if $self->{'ignore-whitespace'};
780
                $line eq $match->[$_] or $fail++, last;
781
            }
782
            if ($fail) {
783
                seek $in, $tell, 0 or throw "Couldn't seek INFILE: $!";
784
                <$in>;
785
            } else {
786
                return ($tell, $line);
787
            }
788
        }
789
        $line++;
790
        $tell = tell $in;
791
    }
792
 
793
    return;
794
 
795
    CATCH: $self->note($@), return;
796
}
797
 
798
 
799
 
800
 
801
package Patch::Context;
802
 
803
BEGIN { Patch->import }
804
 
805
# Convert hunk to unified diff, then apply.
806
sub apply {
807
    my ($self, $i_start, $o_start, $i_hunk, $o_hunk) = @_;
808
 
809
    my @hunk;
810
    my @i_hunk = @$i_hunk;
811
    my @o_hunk = @$o_hunk;
812
 
813
    s/^(.) /$1/ for @i_hunk, @o_hunk;
814
 
815
    while (@i_hunk and @o_hunk) {
816
        my ($i, $o) = (shift @i_hunk, shift @o_hunk);
817
        if ($i eq $o) {
818
            push @hunk, $i;
819
            next;
820
        }
821
        while ($i =~ s/^[!-]/-/) {
822
            push @hunk, $i;
823
            $i = shift @i_hunk;
824
        }
825
        while ($o =~ s/^[!+]/+/) {
826
            push @hunk, $o;
827
            $o = shift @o_hunk;
828
        }
829
        push @hunk, $i;
830
    }
831
    push @hunk, @i_hunk, @o_hunk;
832
 
833
    $self->SUPER::apply($i_start, $o_start, @hunk);
834
}
835
 
836
# Check for filename in diff header, then in 'Index:' line.
837
sub rummage {
838
    my ($self, $garbage) = @_;
839
 
840
    my @files = grep -e, map $self->strip,
841
        map /^\s*(?:\*\*\*|---) (\S+)/, @$garbage[-1, -2];
842
 
843
    my $file =
844
        @files == 1 ? $files[0] :
845
        @files == 2 ? $files[length $files[0] > length $files[1]] :
846
        $self->SUPER::rummage($garbage);
847
 
848
    return $file;
849
}
850
 
851
 
852
 
853
 
854
package Patch::Ed;
855
 
856
BEGIN { Patch->import }
857
 
858
# Pipe ed script to ed or try to manually process.
859
sub apply {
860
    my ($self, @cmd) = @_;
861
 
862
    $self->{skip} and throw 'SKIP...ignore this patch';
863
 
864
    my $out = $self->{o_fh};
865
 
866
    $self->{check} and goto PLAN_J;
867
 
868
    # We start out by adding a magic line to our output.  If this line
869
    # is still there after piping to ed, then ed failed.  We do this
870
    # because win32 will silently fail if there is no ed program.
871
    my $magic = "#!/i/want/a/moogle/stuffy\n";
872
    print $out $magic;
873
 
874
    # Pipe to ed.
875
    eval {
876
        local $SIG{PIPE} = sub { die 'Pipe broke...' };
877
        local $SIG{CHLD} = sub { die 'Bad child...' };
878
        open ED, "| ed - -s $self->{i_file}" or die "Couldn't fork ed: $!";
879
        print ED map @$_, @cmd               or die "Couldn't print ed: $!";
880
        print ED "1,\$w $self->{o_file}"     or die "Couldn't print ed: $!";
881
        close ED                             or die "Couldn't close ed: $?";
882
    };
883
 
884
    # Did pipe to ed work?
885
    unless ($@ or <$out> ne $magic) {
886
        $self->note("Hunk #$self->{hunk} succeeded at 1.\n");
887
        return 1;
888
    }
889
 
890
    # Erase any trace of magic line.
891
    truncate $out, 0 or throw "Couldn't truncate OUT: $!";
892
    seek $out, 0, 0  or throw "Couldn't seek OUT: $!";
893
 
894
    # Try to apply ed script by hand.
895
    $self->note("Pipe to ed failed.  Switching to Plan J...\n");
896
 
897
    PLAN_J:
898
 
899
    # Pre-process each ed command.  Ed diffs are reversed (so that each
900
    # command doesn't end up changing the line numbers of subsequent
901
    # commands).  But we need to apply diffs in a forward direction because
902
    # our filehandles are oriented that way.  So we calculate the @offset
903
    # in line number that this will cause as we go.
904
    my @offset;
905
    for (my $i = 0; $i < @cmd; $i++) {
906
        my @hunk = @{$cmd[$i]};
907
 
908
        shift(@hunk) =~ m!^(\d+)(?:,(\d+))?([acds])!
909
            or throw "Unable to parse ed script.";
910
 
911
        my ($start, $end, $cmd) = ($1, $2 || $1, $3);
912
 
913
        # We don't parse substitution commands and assume they all mean
914
        # s/\.\././ even if they really mean s/\s+// or such.  And we
915
        # blindly apply the command to the previous hunk.
916
        if ($cmd eq 's') {
917
            $cmd[$i] = '';
918
            s/\.\././ for @{$cmd[$i-1][3]};
919
            next;
920
        }
921
 
922
        # Remove '.' line used to terminate hunks.
923
        pop @hunk if $cmd =~ /^[ac]/;
924
 
925
        # Calculate where we actually start and end by removing any offsets.
926
        my ($s, $e) = ($start, $end);
927
        for (@offset) {
928
            $start > $_->[0] or next;
929
            $s -= $_->[1];
930
            $e -= $_->[1];
931
        }
932
 
933
        # Add to the total offset.
934
        push @offset, [$start, map {
935
            /^c/ ? scalar @hunk - ($end + 1 - $start) :
936
            /^a/ ? scalar @hunk :
937
            /^d/ ? $end + 1 - $start :
938
 
939
        } $cmd];
940
 
941
        # Post-processed command.
942
        $cmd[$i] = [$s, $e, $cmd, \@hunk, $i];
943
    }
944
 
945
    # Sort based on calculated start positions or on original order.
946
    # Substitution commands have already been applied and are ignored.
947
    @cmd = sort {
948
        $a->[0] <=> $b->[0] || $a->[-1] <=> $b->[-1]
949
    } grep ref, @cmd;
950
 
951
    my $in  = $self->{i_fh};
952
    my $def = $self->{d_fh};
953
    my $ifdef = $self->{ifdef};
954
 
955
    # Apply each command.
956
    for (@cmd) {
957
        my ($start, $end, $cmd, $hunk) = @$_;
958
        if ($cmd eq 'a') {
959
            my $diff = $start - $self->{i_lines};
960
            print $out scalar <$in> while $diff--;
961
            print $def "#ifdef $ifdef\n";
962
            print $out @$hunk;
963
            $self->{i_lines} = $start;
964
        } elsif ($cmd eq 'd') {
965
            my $diff = $start - $self->{i_lines} - 1;
966
            print $out scalar <$in> while $diff--;
967
            print $def "#ifndef $ifdef\n";
968
            print $def scalar <$in> for $start..$end;
969
            $self->{i_lines} = $end;
970
        } elsif ($cmd eq 'c') {
971
            my $diff = $start - $self->{i_lines} - 1;
972
            print $out scalar <$in> while $diff--;
973
            print $def "#ifndef $ifdef\n";
974
            print $def scalar <$in> for $start..$end;
975
            print $def "#else\n";
976
            print $out @$hunk;
977
            $self->{i_lines} = $end;
978
        }
979
        print $def "#endif /* $ifdef */\n";
980
    }
981
 
982
    # Output any lines left in input handle.
983
    print $out readline $in;
984
 
985
    # Report success to user.
986
    for (my $i = 0; $i < @cmd; $i++) {
987
        $self->note(
988
            'Hunk #', $i+1, ' succeeded at ',
989
            $cmd[$i - not ref $cmd[$i]][0], "\n",
990
        );
991
    }
992
 
993
    return 1;
994
 
995
    # Or report failure.
996
    CATCH:
997
    $self->{skip}++ if $@ =~ /^SKIP/;
998
    $self->note( $self->{skip}
999
        ? "Hunk #$self->{hunk} ignored at 1.\n"
1000
        : "Hunk #$self->{hunk} failed--$@"
1001
    );
1002
    return;
1003
}
1004
 
1005
# End of patch clean up.  $self->print_tail is omitted because ed diffs are
1006
# applied all at once rather than one hunk at a time.
1007
sub end {
1008
    my $self = shift;
1009
 
1010
    return if $self->{skip};
1011
 
1012
    $self->print_rejects;
1013
    $self->remove_empty_files;
1014
}
1015
 
1016
 
1017
 
1018
 
1019
package Patch::Normal;
1020
 
1021
BEGIN { Patch->import }
1022
 
1023
# Convert hunk to unified diff, then apply.
1024
sub apply {
1025
    my ($self, $i_start, $o_start, $cmd, $d_hunk, $a_hunk) = @_;
1026
 
1027
    $i_start++ if $cmd eq 'a';
1028
    $o_start++ if $cmd eq 'd';
1029
    my @hunk;
1030
    push @hunk, map "-$_", @$d_hunk;
1031
    push @hunk, map "+$_", @$a_hunk;
1032
 
1033
    $self->SUPER::apply($i_start, $o_start, @hunk);
1034
}
1035
 
1036
 
1037
 
1038
 
1039
package Patch::Unified;
1040
 
1041
BEGIN { Patch->import }
1042
 
1043
# Check for filename in diff header, then in 'Index:' line.
1044
sub rummage {
1045
    my ($self, $garbage) = @_;
1046
 
1047
    my @files = grep -e, map $self->strip,
1048
        map /^\s*(?:---|\+\+\+) (\S+)/, @$garbage[-1, -2];
1049
 
1050
    my $file =
1051
        @files == 1 ? $files[0] :
1052
        @files == 2 ? $files[length $files[0] > length $files[1]] :
1053
        $self->SUPER::rummage($garbage);
1054
 
1055
    return $file;
1056
}
1057
 
1058
 
1059
 
1060
 
1061
package Pushback;
1062
 
1063
# Create filehandles that can unread or push lines back into queue.
1064
 
1065
sub TIEHANDLE {
1066
    my ($class, $file) = @_;
1067
    local *FH;
1068
    open *FH, "< $file" or return;
1069
    bless [*FH], $class;
1070
}
1071
 
1072
sub READLINE {
1073
    my $self = shift;
1074
    @$self == 1 ? readline $self->[0] : pop @$self;
1075
}
1076
 
1077
sub PRINT {
1078
    my $self = shift;
1079
    $self->[1] = shift;
1080
}
1081
 
1082
sub CLOSE {
1083
    my $self = shift;
1084
    $self = undef;
1085
}
1086
 
1087
 
1088
 
1089
 
1090
package Dev::Null;
1091
 
1092
# Create filehandles that go nowhere.
1093
 
1094
sub TIEHANDLE { bless \my $null }
1095
sub PRINT {}
1096
sub PRINTF {}
1097
sub WRITE {}
1098
sub READLINE {''}
1099
sub READ {''}
1100
sub GETC {''}
1101
 
1102
 
1103
 
1104
 
1105
__END__
1106
 
1107
=head1 NAME
1108
 
1109
patch - apply a diff file to an original
1110
 
1111
=head1 SYNOPSIS
1112
 
1113
B<patch> [options] [origfile [patchfile]] [+ [options] [origfile]]...
1114
 
1115
but usually just
1116
 
1117
B<patch> E<lt>patchfile
1118
 
1119
=head1 DESCRIPTION
1120
 
1121
I<Patch> will take a patch file containing any  of  the  four
1122
forms  of  difference listing produced by the I<diff> program
1123
and apply those differences to an original file, producing
1124
a patched version.  By default, the patched version is put
1125
in place of the original, with the original file backed up
1126
to  the  same name with the extension ".orig" [see L<"note 1">],
1127
or as  specified
1128
by  the  B<-b>,  B<-B>,  or B<-V> switches.  The extension used for
1129
making backup files may also  be  specified  in  the
1130
B<SIMPLE_BACKUP_SUFFIX>  environment variable, which is overridden
1131
by above switches.
1132
 
1133
If the backup file already exists,  B<patch>  creates  a  new
1134
backup file name by changing the first lowercase letter in
1135
the last component of the file's name into uppercase.   If
1136
there  are  no  more  lowercase  letters  in  the name, it
1137
removes the first character from  the  name.   It  repeats
1138
this  process  until  it  comes up with a backup file that
1139
does not already exist.
1140
 
1141
You may also specify where you want the output to go  with
1142
a  B<-o> switch; if that file already exists, it is backed up
1143
first.
1144
 
1145
If I<patchfile> is omitted, or is a hyphen, the patch will be
1146
read from standard input.
1147
 
1148
Upon  startup, patch will attempt to determine the type of
1149
the diff listing, unless over-ruled by a B<-c>, B<-e>, B<-n>, or B<-u>
1150
switch.  Context diffs [see L<"note 2">], unified diffs,
1151
and normal diffs are applied by the I<patch> program  itself,
1152
while ed diffs are simply fed to the I<ed> editor via a pipe [see L<"note 3">].
1153
 
1154
I<Patch> will try to skip  any  leading  garbage,  apply  the
1155
diff,  and then skip any trailing garbage.  Thus you could
1156
feed an article or message containing a  diff  listing  to
1157
I<patch>, and it should work.  If the entire diff is indented
1158
by a consistent amount, this will be taken into account.
1159
 
1160
With context diffs, and to a  lesser  extent  with  normal
1161
diffs, I<patch> can detect when the line numbers mentioned in
1162
the patch are incorrect, and  will  attempt  to  find  the
1163
correct place to apply each hunk of the patch.  A linear search is made  for  a
1164
place  where  all  lines of the context match.
1165
The hunk is applied at the place nearest the line number mentioned in the
1166
diff [see L<"note 4">].
1167
If no such
1168
place is found, and it's a context diff, and  the  maximum
1169
fuzz  factor  is set to 1 or more, then another scan takes
1170
place ignoring the first and last  line  of  context.   If
1171
that  fails,  and  the  maximum fuzz factor is set to 2 or
1172
more, the first two and last  two  lines  of  context  are
1173
ignored,  and  another scan is made.  (The default maximum
1174
fuzz factor is 2.)   If  I<patch>  cannot  find  a  place  to
1175
install  that  hunk of the patch, it will put the hunk out
1176
to a reject file, which normally is the name of the output
1177
file  plus ".rej" [see L<"note 1">].  The format of the
1178
rejected hunk remains unchanged [see L<"note 5">]. 
1179
 
1180
As  each  hunk  is completed, you will be told whether the
1181
hunk succeeded or failed, and which line (in the new file)
1182
I<patch> thought the hunk should go on.  If this is different
1183
from the line number specified in the  diff  you  will  be
1184
told  the offset.  A single large offset MAY be an indication that a hunk was installed in the  wrong  place.   You
1185
will  also  be  told if a fuzz factor was used to make the
1186
match, in which case you should also  be  slightly  suspicious.
1187
 
1188
If  no  original  file  is  specified on the command line,
1189
I<patch> will try to figure out from the leading garbage what
1190
the  name of the file to edit is.  In the header of a context diff, the filename is found from lines beginning with
1191
"***" or "---", with the shortest name of an existing file
1192
winning.  Only context diffs have lines like that, but  if
1193
there  is  an  "Index:" line in the leading garbage, I<patch>
1194
will try to use the filename from that line.  The  context
1195
diff  header  takes  precedence over an Index line.  If no
1196
filename can be intuited from  the  leading  garbage,  you
1197
will be asked for the name of the file to patch.
1198
 
1199
No attempt is made to look up SCCS or RCS files [see L<"note 6">].
1200
 
1201
Additionally, if the leading garbage contains a "Prereq: "
1202
line,  I<patch>  will  take   the   first   word   from   the
1203
prerequisites  line  (normally a version number) and check
1204
the input file to see if that word can be found.  If  not,
1205
I<patch> will ask for confirmation before proceeding.
1206
 
1207
The  upshot of all this is that you should be able to say,
1208
while in a news interface, the following:
1209
 
1210
     | patch -d /usr/src/local/blurfl
1211
 
1212
and patch a file in the blurfl directory directly from the
1213
article containing the patch.
1214
 
1215
If the patch file contains more than one patch, I<patch> will
1216
try to apply each of them as if they  came  from  separate
1217
patch  files.   This means, among other things, that it is
1218
assumed that the name of the file to patch must be  determined  for  each diff listing, and that the garbage before
1219
each diff listing will be examined for interesting  things
1220
such  as filenames and revision level, as mentioned previously.  You can give switches (and another  original  file
1221
name)  for the second and subsequent patches by separating
1222
the corresponding argument lists by a '+'.  (The  argument
1223
list  for  a  second or subsequent patch may not specify a
1224
new patch file, however.)
1225
 
1226
I<Patch> recognizes the following switches:
1227
 
1228
=over
1229
 
1230
=item -b or --suffix
1231
 
1232
causes the next argument to  be  interpreted  as  the
1233
backup  extension,  to be used in place of ".orig" [see L<"note 1">].
1234
 
1235
=item -B or --prefix
1236
 
1237
causes the next argument to be interpreted as a  prefix  to  the  backup  file  name. If this argument is
1238
specified any argument from B<-b> will be ignored.
1239
 
1240
=item -c or --context
1241
 
1242
forces I<patch> to interpret the patch file as a context
1243
diff.
1244
 
1245
=item -C or --check
1246
 
1247
checks  that  the patch would apply cleanly, but does
1248
not modify anything.
1249
 
1250
=item -d or --directory
1251
 
1252
causes I<patch> to interpret  the  next  argument  as  a
1253
directory, and cd to it before doing anything else.
1254
 
1255
=item -D or --ifdef
1256
 
1257
causes  I<patch>  to use the "#ifdef...#endif" construct
1258
to mark changes.  The argument following will be used
1259
as the differentiating symbol.  [see L<"note 7">]
1260
 
1261
=item -e or --ed
1262
 
1263
forces  I<patch>  to  interpret  the patch file as an ed
1264
script.
1265
 
1266
=item -E or --remove-empty-files
1267
 
1268
causes I<patch> to remove output files  that  are  empty
1269
after the patches have been applied.
1270
 
1271
=item -f or --force
1272
 
1273
forces  I<patch>  to  assume that the user knows exactly
1274
what he or she is doing, and to  not  ask  any  questions.   It  assumes  the following: skip patches for
1275
which a file to patch can't  be  found;  patch  files
1276
even  though  they  have  the  wrong  version for the
1277
``Prereq:''  line  in  the  patch;  and  assume  that
1278
patches  are not reversed even if they look like they
1279
are.  This option does not suppress  commentary;  use
1280
B<-s> for that.
1281
 
1282
=item -t or --batch
1283
 
1284
similar  to  B<-f>, in that it suppresses questions, but
1285
makes some different assumptions:  skip  patches  for
1286
which  a  file  to  patch can't be found (the same as
1287
B<-f>); skip patches for which the file  has  the  wrong
1288
version  for  the  ``Prereq:'' line in the patch; and
1289
assume that patches are reversed if  they  look  like
1290
they are.
1291
 
1292
=item -Fnumber or --fuzz number
1293
 
1294
sets  the  maximum  fuzz  factor.   This  switch only
1295
applies to context diffs, and causes I<patch> to  ignore
1296
up  to  that  many  lines  in  looking  for places to
1297
install a hunk.   Note  that  a  larger  fuzz  factor
1298
increases  the  odds  of a faulty patch.  The default
1299
fuzz factor is 2, and it may not be set to more  than
1300
the  number  of lines of context in the context diff,
1301
ordinarily 3.
1302
 
1303
=item -l or --ignore-whitespace
1304
 
1305
causes the pattern matching to be  done  loosely,  in
1306
case  the  tabs  and  spaces have been munged in your
1307
input file.  Any sequence of whitespace in  the  pattern  line will match any sequence in the input file.
1308
Normal characters must  still  match  exactly.   Each
1309
line  of  the  context must still match a line in the
1310
input file.
1311
 
1312
=item -n or --normal
1313
 
1314
forces I<patch> to interpret the patch file as a  normal
1315
diff.
1316
 
1317
=item -N or --forward
1318
 
1319
causes  I<patch>  to  ignore  patches that it thinks are
1320
reversed or already applied.  See also B<-R .>
1321
 
1322
=item -o or --output
1323
 
1324
causes the next argument to  be  interpreted  as  the
1325
output file name.
1326
 
1327
=item -pnumber or --strip number
1328
 
1329
sets  the  pathname  strip  count, which controls how
1330
pathnames found in the patch  file  are  treated,  in
1331
case the you keep your files in a different directory
1332
than the person who sent out the  patch.   The  strip
1333
count  specifies  how many slashes are to be stripped
1334
from the front of  the  pathname.   (Any  intervening
1335
directory  names also go away.)  For example, supposing the filename in the patch file was
1336
 
1337
   /i/want/a/moogle/stuffy
1338
 
1339
setting B<-p> or B<-p0> gives the entire  pathname  unmodified, B<-p1> gives
1340
 
1341
   i/want/a/moogle/stuff
1342
 
1343
without the leading slash, B<-p4> gives
1344
 
1345
   moogle/stuffy
1346
 
1347
and   not   specifying  B<-p>  at  all  just  gives  you
1348
"stuffy", unless all  of  the  directories  in  the
1349
leading  path  (i/want/a/moogle)  exist  and that
1350
path is relative, in which case you  get  the  entire
1351
pathname  unmodified.   Whatever  you  end up with is
1352
looked for either in the current  directory,  or  the
1353
directory specified by the B<-d> switch.
1354
 
1355
=item -r or --reject-file
1356
 
1357
causes  the  next  argument  to be interpreted as the
1358
reject file name.
1359
 
1360
=item -R or --reverse
1361
 
1362
tells I<patch> that this patch was created with the  old
1363
and  new  files  swapped.  (Yes, I'm afraid that does
1364
happen occasionally, human nature being what it  is.)
1365
I<Patch>  will  attempt  to swap each hunk around before
1366
applying it.  Rejects will come out  in  the  swapped
1367
format.   The  B<-R>  switch  will not work with ed diff
1368
scripts because there is too  little  information  to
1369
reconstruct the reverse operation.
1370
 
1371
If  the  first  hunk  of  a  patch  fails, I<patch> will
1372
reverse the hunk to see if it  can  be  applied  that
1373
way.   If  it  can,  you will be asked if you want to
1374
have the B<-R> switch set.  If it can't, the patch  will
1375
continue  to be applied normally.  (Note: this method
1376
cannot detect a reversed patch if it is a normal diff
1377
and if the first command is an append (i.e. it should
1378
have been a delete) since appends always succeed, due
1379
to  the fact that a null context will match anywhere.
1380
Luckily, most patches add or change lines rather than
1381
delete them, so most reversed normal diffs will begin
1382
with  a  delete,  which  will  fail,  triggering  the
1383
heuristic.)
1384
 
1385
=item -s or --quiet or --silent
1386
 
1387
makes  I<patch>  do  its  work silently, unless an error
1388
occurs.
1389
 
1390
=item -S or --skip
1391
 
1392
causes I<patch> to ignore  this  patch  from  the  patch
1393
file,  but  continue on looking for the next patch in
1394
the file.  Thus
1395
 
1396
   patch -S + -S + < patchfile
1397
 
1398
will ignore the first and second of three patches.
1399
 
1400
=item -u or --unified
1401
 
1402
forces I<patch> to interpret the patch file as a unified
1403
context diff (a unidiff).
1404
 
1405
=item -v or --version
1406
 
1407
causes  I<patch>  to  print  out its revision header and
1408
patch level.
1409
 
1410
=item -V or --version-control
1411
 
1412
causes the next  argument  to  be  interpreted  as  a
1413
method  for  creating backup file names.  The type of
1414
backups made can also be given in the B<VERSION>I<_>B<CONTROL>
1415
environment  variable,  which  is  overridden by this
1416
option.  The B<-B> option overrides this option, causing
1417
the  prefix  to always be used for making backup file
1418
names.  The value of the B<VERSION>I<_>B<CONTROL>  environment
1419
variable  and  the argument to the B<-V> option are like
1420
the GNU Emacs `version-control' variable;  they  also
1421
recognize  synonyms  that  are more descriptive.  The
1422
valid values are (unique abbreviations are accepted):
1423
 
1424
=over
1425
 
1426
=item `t' or `numbered'
1427
 
1428
Always make numbered backups.
1429
 
1430
=item `nil' or `existing'
1431
 
1432
Make  numbered  backups  of files that already
1433
have them, simple backups of the others.  This
1434
is the default.
1435
 
1436
=item `never' or `simple'
1437
 
1438
Always make simple backups.
1439
 
1440
=back
1441
 
1442
=item -xnumber or --debug number
1443
 
1444
sets  internal  debugging  flags,
1445
and is of no interest to I<patch> patchers [see L<"note 8">].
1446
 
1447
=back
1448
 
1449
=head1 ENVIRONMENT
1450
 
1451
B<SIMPLE_BACKUP_SUFFIX>
1452
Extension  to  use for backup file names instead of
1453
".orig" or "~".
1454
 
1455
B<VERSION_CONTROL>
1456
Selects when numbered backup files are made.
1457
 
1458
=head1 SEE ALSO
1459
 
1460
diff(1), ed(1)
1461
 
1462
=head1 NOTES FOR PATCH SENDERS
1463
 
1464
There are several things you should bear in  mind  if  you
1465
are  going to be sending out patches.  First, you can save
1466
people a lot of grief by keeping a patchlevel.h file which
1467
is  patched to increment the patch level as the first diff
1468
in the patch file you send out.  If you put a Prereq: line
1469
in  with the patch, it won't let them apply patches out of
1470
order without some  warning.   Second,  make  sure  you've
1471
specified  the  filenames  right, either in a context diff
1472
header, or with an Index: line.  If you are patching something in a subdirectory, be sure to tell the patch user to
1473
specify a B<-p> switch as needed.  Third, you  can  create  a
1474
file  by  sending  out a diff that compares a null file to
1475
the file you want to create.  This will only work  if  the
1476
file  you want to create doesn't exist already in the target directory.  Fourth, take care not to send out reversed
1477
patches, since it makes people wonder whether they already
1478
applied the patch.  Fifth, while you may be  able  to  get
1479
away  with  putting 582 diff listings into one file, it is
1480
probably wiser to  group  related  patches  into  separate
1481
files in case something goes haywire.
1482
 
1483
=head1 DIAGNOSTICS
1484
 
1485
Too many to list here, but generally indicative that I<patch>
1486
couldn't parse your patch file.
1487
 
1488
The message "Hmm..." indicates that there  is  unprocessed
1489
text  in  the  patch  file and that I<patch> is attempting to
1490
intuit whether there is a patch in that text and,  if  so,
1491
what kind of patch it is.
1492
 
1493
I<Patch> will exit with a non-zero status if any reject files
1494
were created.  When applying a set of patches in a loop it
1495
behooves  you to check this exit status so you don't apply
1496
a later patch to a partially patched file.
1497
 
1498
=head1 CAVEATS
1499
 
1500
I<Patch> cannot tell if the line numbers are  off  in  an  ed
1501
script,  and  can only detect bad line numbers in a normal
1502
diff when it finds a "change" or a  "delete"  command.   A
1503
context  diff  using fuzz factor 3 may have the same problem.  Until a suitable interactive interface is added, you
1504
should probably do a context diff in these cases to see if
1505
the changes made  sense.   Of  course,  compiling  without
1506
errors  is a pretty good indication that the patch worked,
1507
but not always.
1508
 
1509
I<Patch> usually produces the correct results, even  when  it
1510
has  to  do  a  lot of guessing.  However, the results are
1511
guaranteed to be correct only when the patch is applied to
1512
exactly  the  same  version of the file that the patch was
1513
generated from.
1514
 
1515
=head1 BUGS
1516
 
1517
Could  be  smarter  about  partial  matches,   excessively
1518
deviant  offsets  and swapped code, but that would take an
1519
extra pass.
1520
 
1521
Check patch mode ( B<-C>) will fail if you try to check  several  patches in succession that build on each other.  The
1522
whole code of I<patch> would have to be restructured to  keep
1523
temporary  files  around so that it can handle this situation.
1524
 
1525
If code has been duplicated (for instance with #ifdef OLDCODE  ... #else ...  #endif), I<patch> is incapable of patch-
1526
ing both versions, and, if it works at  all,  will  likely
1527
patch  the  wrong  one,  and tell you that it succeeded to
1528
boot.
1529
 
1530
If you apply a patch you've already  applied,  I<patch>  will
1531
think  it  is  a reversed patch, and offer to un-apply the
1532
patch.  This could be construed as a feature.
1533
 
1534
=head1 COMPATIBILITY
1535
 
1536
The perl implementation of patch is based on but not entire compatible with the
1537
documentation for GNU patch version 2.1:
1538
 
1539
=head2 note 1
1540
 
1541
On systems that do not support long filenames,
1542
GNU patch uses the extension "~" for backup files and the extension "#" for
1543
reject files.
1544
How to know if a system support long filenames?
1545
 
1546
=head2 note 2
1547
 
1548
Only new-style context diffs are supported.
1549
What does old-style context diff look like?
1550
 
1551
=head2 note 3
1552
 
1553
If the pipe to ed fails, B<patch> will attempt to apply the ed script on its
1554
own.
1555
 
1556
=head2 note 4
1557
 
1558
This algorithm differs from the one described in the documentation for GNU
1559
patch, which scans forwards and backwards from the line number mentioned in the
1560
diff (plus any offset used in applying the previous hunk).
1561
 
1562
=head2 note 5
1563
 
1564
Rejected hunks in GNU patch all come out as context diffs regardless of the
1565
input diff, and the lines numbers reflect the approximate location GNU patch
1566
thinks the failed hunks belong in the new file rather than the old one.
1567
 
1568
=head2 note 6
1569
 
1570
If the original file cannot be found or is read-only, but a suitable SCCS or RCS
1571
file is handy, GNU patch will attempt to get or check out the file.
1572
 
1573
=head2 note 7
1574
 
1575
GNU patch requires a space between the B<-D> and the argument.  This has been
1576
made optional.
1577
 
1578
=head2 note 8
1579
 
1580
There are currently no debugging flags to go along with B<-x>.
1581
 
1582
=head1 AUTHOR
1583
 
1584
Tim Gim Yee | tgy@chocobo.org | I want a moogle stuffy!
1585
 
1586
=head1 COPYRIGHT
1587
 
1588
Copyright (c) 1999 Moogle Stuffy Software.  All rights reserved.
1589
 
1590
You may play with this software in accordance with the Perl Artistic License.
1591
 
1592
You may use this documentation under the auspices of the GNU General Public
1593
License.
1594
 
1595
=cut
1596