The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Text::Patch::Rred - Safely apply diff --ed style patches

VERSION

This is version 0.06

USAGE

Command Line:

rred file.old file.new file.patch1 [ file.patch2 ... ]

Functional Interface (preferred, faster, type checked)

    my @lines = <ORIGINAL>;
    my $edState = Text::Patch::Rred::Init(@lines);
            # or &Text::Patch::Rred::Init(\@lines);
    while (<EDSCRIPTS>) { Text::Patch::Rred::Do1($edState, $_); }
    @lines = Text::Patch::Rred::Result($edState);
    $edState = undef; # free memory
    print PATCHED @lines;

Object Interface:

    my @lines = <ORIGINAL>;
    my $edState = Text::Patch::Rred->new(\@lines);
    while (<EDSCRIPTS>) { $edState->Do1($_); }
    @lines = $edState->Result;
    $edState = undef; # free memory
    print PATCHED @lines;

Example:

    $ diff --ed file.v1 file.v2 >file.patch1
    $ diff --ed file.v2 file.v3 >file.patch2
    $ rred file.v1 file.new file.patch1 [ file.patch2 ... ]
    $ # Now file.new is the same as file.v3
    $ # Alternative:
    $ cat file.patch1 file.patch2 | rred file.v1 file.new -

DESCRIPTION

This module and program safely and securely applies one or more ed-style patches as produced by the command diff --ed oldfile newfile. It does exactly what you tell it to and no more, even with wildly bad or evil input.

Unlike the traditional programs patch, ed, red and sed, Rred does not allow the data in the patch to run arbitrary commands, read or write files or otherwise cause havoc. Only the handful of safe "commands" actually used by diff are recognized and processed.

Unlike the patch program and the perl modules Text::Patch, PatchReader and Meta::Development::Patch, this module does NOT try to doubleguess what kind of data it is given or which file to process.

(Note that the other perl modules just mentioned cannot actually apply an ed-style patch, though some can parse it).

The name rred is short for "Really Restricted ED" (as compared to red). This is the name given to a similar utility used inside the Debian projects apt facility.

REQUIRED ARGUMENTS

file.old

Original file whose contents is to be patch. This file should be identical to the first file passed to diff -e when the patches were made. In this implementation, perl magics are supported for this file name.

file.new

Output file where the fully patched contents is to be written. This file will become identical to the last file passed to diff -e when the patches were made. This file can be the same file as any of the input files. In this implementation, perl magics are not supported for this file name.

file.patch1 [ file.patch2 ... ]

One or more --ed style patch files to be applied (in sequence) to the contents of file.old to produce file.new. These files should be identical to the output of one or more invocations of diff -e on file.old and file.new plus optionally any intermediary files. The patch files may optionally be concatenated before being passed to rred, the result will be the same as passing them individually. In this implementation, perl magics are supported for these file names.

EXPORT

Init, Do1, Do, Result and main can be exported. :all is short for Init, Do1 and Result. Nothing is exported by default.

FUNCTIONS and METHODS

new \@lines
Init @lines

Initializes a new patch state and sets the initial file content to a copy of the lines of text (each a string) supplied. Returns a new Text::Patch::Rred object if successful, undef on error (there are no current error scenarios).

Lines in @lines must use the same line endings (none or "\n") as lines passed to Do1 and Do

Result $edState
$edState->Result

Returns the lines of the patched file as a list of strings, does not destroy $edState so you can apply more patches later.

Do1 $edState, $patchline
$edState->Do1($patchline)

Applies one line from a patch file to $edState. Returns a true value if the line was understood. Carps and returns undef if an unsupported command is input.

Do $edState, @lines
$edState->Do(@lines)

Simply calls Do1 for each element of @lines, returns a true value if all calls were successful or @lines was empty. Otherwise returns undef.

main @ARGV

The main program code of rred as a function, accepting the command line syntax in the SYNOPSIS above. Returns the program exit code (0 ok, 1 error, 2 bad syntax). Running rred args is the same as running

    perl -MText::Patch::Rred \
        -e 'exit Text::Patch::Rred::main @ARGV' args

ED COMMANDS

Unfortunately, the GNU diff documentation (info -f diff -n 'Detailed ed' or http://www.gnu.org/software/diffutils/manual/html_node/Detailed-ed.html) is sloppy about specifying exactly which subset of the ed editor command language might appear in diff --ed output.

Currently the ed "commands" actually used by various versions of diff --ed and diff -e are believed to be (these are the ones supported by this module, and also the ones emitted by GNU diff according to a cursory inspection of its source code):

   a
   ###a
   ###,###a
   c
   ###c
   ###,###c
   d
   ###d
   ###,###d
   s/.//
   w

OPTIONS

None.

CONFIGURATION AND ENVIRONMENT

None.

BUGS AND LIMITATIONS

There seems to be no formal specification for the subset of ed(1) commands used by diff -e, thus this program is limited to the subset of ed(1) commands listed above, which may or may not be sufficient to apply the patch files you encounter in practice.

Although steps have been taken to limit memory consumption, perl still uses a lot of memory when running this module, as much as 5 times the file size has been observed in tests.

DIAGNOSTICS

rred: Printing usage: error message

When running rred or Text::Patch::Rred::main with less than 3 args, it should have printed its usage help message to stderr, but this somehow failed.

Loading 'file.old': error message

When loading the original unpatched file from file.old, something went wrong at the file I/O level.

Saving 'file.new': error message

When saving the completely patched file to file.new, something went wrong at the file I/O level.

Reading 'file.patch': error message

When loading one of the patch files from file.patch, something went wrong at the File I/O level.

Unexpected non-patch ed command: 'text'

'text' was found in one of the patch files but is not an ed command supported by rred.

DEPENDENCIES

Text::Patch::Rred only needs perl itself (at least version 5.6) and the standard Carp, Exporter and base modules.

INCOMPATIBILITIES

None known.

SEE ALSO

diff(1), info -f diff -n 'Detailed ed', patch(1), ed(1), red(1), Text::Patch, http://www.gnu.org/software/diffutils/manual/html_node/Detailed-ed.html

AUTHOR

Jakob Bohm, <ehekikkeptiehewdur@jbohm.dk>

Always include the full module name (with double colons and all) in the subject line to get past my "spam" filters.

LICENSE AND COPYRIGHT

Copyright (C) ©2006-2009 by Jakob Bohm. All Rights Reserved.

This library and program is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.6.0 or, at your option, any later version of Perl 5 you may have available.