Alien-wxWidgets

 view release on metacpan or  search on metacpan

inc/bin/patch  view on Meta::CPAN

    while (<$in>) {
        s/\s+/ /g if $self->{'ignore-whitespace'};
        if ($_ eq $match->[0]) {
            my $fail;
            for (1..$#$match) {
                my $line = <$in>;
                $line =~ s/\s+/ /g if $self->{'ignore-whitespace'};
                $line eq $match->[$_] or $fail++, last;
            }
            if ($fail) {
                seek $in, $tell, 0 or throw "Couldn't seek INFILE: $!";
                <$in>;
            } else {
                return ($tell, $line);
            }
        }
        $line++;
        $tell = tell $in;
    }

    return;

    CATCH: $self->note($@), return;
}




package Patch::Context;

BEGIN { Patch->import }

# Convert hunk to unified diff, then apply.
sub apply {
    my ($self, $i_start, $o_start, $i_hunk, $o_hunk) = @_;

    my @hunk;
    my @i_hunk = @$i_hunk;
    my @o_hunk = @$o_hunk;

    s/^(.) /$1/ for @i_hunk, @o_hunk;

    while (@i_hunk and @o_hunk) {
        my ($i, $o) = (shift @i_hunk, shift @o_hunk);
        if ($i eq $o) {
            push @hunk, $i;
            next;
        }
        while ($i =~ s/^[!-]/-/) {
            push @hunk, $i;
            $i = shift @i_hunk;
        }
        while ($o =~ s/^[!+]/+/) {
            push @hunk, $o;
            $o = shift @o_hunk;
        }
        push @hunk, $i;
    }
    push @hunk, @i_hunk, @o_hunk;

    $self->SUPER::apply($i_start, $o_start, @hunk);
}

# Check for filename in diff header, then in 'Index:' line.
sub rummage {
    my ($self, $garbage) = @_;

    my @files = grep -e, map $self->strip,
        map /^\s*(?:\*\*\*|---) (\S+)/, @$garbage[-1, -2];

    my $file =
        @files == 1 ? $files[0] :
        @files == 2 ? $files[length $files[0] > length $files[1]] :
        $self->SUPER::rummage($garbage);

    return $file;
}




package Patch::Ed;

BEGIN { Patch->import }

# Pipe ed script to ed or try to manually process.
sub apply {
    my ($self, @cmd) = @_;

    $self->{skip} and throw 'SKIP...ignore this patch';

    my $out = $self->{o_fh};

    $self->{check} and goto PLAN_J;

    # We start out by adding a magic line to our output.  If this line
    # is still there after piping to ed, then ed failed.  We do this
    # because win32 will silently fail if there is no ed program.
    my $magic = "#!/i/want/a/moogle/stuffy\n";
    print $out $magic;

    # Pipe to ed.
    eval {
        local $SIG{PIPE} = sub { die 'Pipe broke...' };
        local $SIG{CHLD} = sub { die 'Bad child...' };
        open ED, "| ed - -s $self->{i_file}" or die "Couldn't fork ed: $!";
        print ED map @$_, @cmd               or die "Couldn't print ed: $!";
        print ED "1,\$w $self->{o_file}"     or die "Couldn't print ed: $!";
        close ED                             or die "Couldn't close ed: $?";
    };

    # Did pipe to ed work?
    unless ($@ or <$out> ne $magic) {
        $self->note("Hunk #$self->{hunk} succeeded at 1.\n");
        return 1;
    }

    # Erase any trace of magic line.
    truncate $out, 0 or throw "Couldn't truncate OUT: $!";
    seek $out, 0, 0  or throw "Couldn't seek OUT: $!";

    # Try to apply ed script by hand.
    $self->note("Pipe to ed failed.  Switching to Plan J...\n");

    PLAN_J:

    # Pre-process each ed command.  Ed diffs are reversed (so that each
    # command doesn't end up changing the line numbers of subsequent
    # commands).  But we need to apply diffs in a forward direction because
    # our filehandles are oriented that way.  So we calculate the @offset
    # in line number that this will cause as we go.
    my @offset;
    for (my $i = 0; $i < @cmd; $i++) {
        my @hunk = @{$cmd[$i]};

inc/bin/patch  view on Meta::CPAN

            print $def "#ifndef $ifdef\n";
            print $def scalar <$in> for $start..$end;
            print $def "#else\n";
            print $out @$hunk;
            $self->{i_lines} = $end;
        }
        print $def "#endif /* $ifdef */\n";
    }

    # Output any lines left in input handle.
    print $out readline $in;

    # Report success to user.
    for (my $i = 0; $i < @cmd; $i++) {
        $self->note(
            'Hunk #', $i+1, ' succeeded at ',
            $cmd[$i - not ref $cmd[$i]][0], "\n",
        );
    }

    return 1;

    # Or report failure.
    CATCH:
    $self->{skip}++ if $@ =~ /^SKIP/;
    $self->note( $self->{skip}
        ? "Hunk #$self->{hunk} ignored at 1.\n"
        : "Hunk #$self->{hunk} failed--$@"
    );
    return;
}

# End of patch clean up.  $self->print_tail is omitted because ed diffs are
# applied all at once rather than one hunk at a time.
sub end {
    my $self = shift;

    return if $self->{skip};

    $self->print_rejects;
    $self->remove_empty_files;
}




package Patch::Normal;

BEGIN { Patch->import }

# Convert hunk to unified diff, then apply.
sub apply {
    my ($self, $i_start, $o_start, $cmd, $d_hunk, $a_hunk) = @_;

    $i_start++ if $cmd eq 'a';
    $o_start++ if $cmd eq 'd';
    my @hunk;
    push @hunk, map "-$_", @$d_hunk;
    push @hunk, map "+$_", @$a_hunk;

    $self->SUPER::apply($i_start, $o_start, @hunk);
}




package Patch::Unified;

BEGIN { Patch->import }

# Check for filename in diff header, then in 'Index:' line.
sub rummage {
    my ($self, $garbage) = @_;

    my @files = grep -e, map $self->strip,
        map /^\s*(?:---|\+\+\+) (\S+)/, @$garbage[-1, -2];

    my $file =
        @files == 1 ? $files[0] :
        @files == 2 ? $files[length $files[0] > length $files[1]] :
        $self->SUPER::rummage($garbage);

    return $file;
}




package Pushback;

# Create filehandles that can unread or push lines back into queue.

sub TIEHANDLE {
    my ($class, $file) = @_;
    local *FH;
    open *FH, "< $file" or return;
    binmode FH;
    bless [*FH], $class;
}

sub READLINE {
    my $self = shift;
    @$self == 1 ? readline $self->[0] : pop @$self;
}

sub PRINT {
    my $self = shift;
    $self->[1] = shift;
}

sub CLOSE {
    my $self = shift;
    $self = undef;
}




package Dev::Null;

# Create filehandles that go nowhere.

sub TIEHANDLE { bless \my $null }
sub PRINT {}
sub PRINTF {}
sub WRITE {}
sub READLINE {''}
sub READ {''}
sub GETC {''}




__END__

=head1 NAME

patch - apply a diff file to an original

=head1 SYNOPSIS



( run in 2.491 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )