NAME

Algorithm::Diff::Apply -- apply one or more Algorithm::Diff diffs

SYNOPSIS

	## Single-diff form:
	use Algorithm::Diff::Apply qw{apply_diff};
	my @ary = ...;
	my @diff = ...;   # some call to Algorithm::Diff::diff()

	my @changed_ary = apply_diff(\@ary, \@diff);
	my $changed_ary = apply_diff(\@ary, \@diff);

	
	## To apply >1 diff at once, use the plural form:
	use Algorithm::Applydiffs qw{apply_diffs};

        @newary = apply_diffs(\@ary,
                              diff1_name => \@diff1,
                              diff2_name => \@diff2,
	                      ...
                              diffN_name => \@diffN);

        # Alternatively:
        @newary = apply_diffs(\@ary, %named_diffs);

        # Scalar context:
        $newary = apply_diffs(\@ary, %named_diffs);

        # Extension argument syntax:
        $newary = apply_diffs(\@ary, {
                                  resolver => \&some_sub,
	                          opt1 => ...,
	                          opt2 => ...,
                              }, %named_diffs);

DESCRIPTION

This module contains subroutines for applying diff sequences generated by Algorithm::Diff to a target array in the hope of regenerating a new array incorporating all the changes described by the diff sequences.

If two hunks from different diff sequences happen to affect the same line, conflicts are detected and handed off to a helper subroutine for resolution.

apply_diff ARRAY,DIFFSEQ

Applies the changes described by a diff sequence to a copy of an array. DIFFSEQ must be a diff generated by Algorithm::Diff::diff(), and ARRAY must be an array of an appropriate length. Both parameters must be passed in as references.

In scalar context, apply_diff returns a reference to the permuted copy that's generated. In an array context, the permuted copy is returned as an array value.

This version of the algorithm is a little simpler and quicker than the full-blown plural form, and should be used if you're only ever going to be applying one diff at once.

apply_diffs ARRAY,HASH
apply_diffs ARRAY,OPTIONS,HASH

Applies more than one diff sequence to a copy of an array at once, manages conflicts, and returns the permuted copy as either a reference or an array depending on context. The HASH parameter contains diffs generated by Algorithm::Diff::diff(), keyed by arbitrary strings. ARRAY must be a reference to an array value. The array behind the passed refrence is not permuted.

The diffs sequences are passed in as a hash in order to provide a meaningful and unique label for each diff. This convention is also used by resolver callbacks (see below), and can make conflict output more understandable to humans if you don't provide a resolver. A label for a diff sequences can be any string you like, provided it's unique; Algorithm::Diff::Apply doesn't care about the exact syntax.

OPTIONS, if specified, must be a hash reference of option keywords and the corresponding parameters. The following options are recognised:

"resolver"

This option can be used to supply a subroutine which will be called when a conflict is detected. The job of this callback is to return some kind of resolution of the conflicting sub-arrays. The sub is called a little like this:

     @ret = $callback->(alt_txts => {
                            diff1_name => ['m', 'n', 'o'],
	                    diff3_name => [],
                        } );

The alt_txts parameter is a hash ref keyed by (some of the) names of the diffs being applied in the main apply_diffs() call, whose values are arrays containing alternative generated subsequences. Each of these subsequences is the result of applying a set of hunks from the corresponding diff to a copy of the slice of the source array where the conflict happened.

A resolver callback is expected to return an array which will be spliced into the array that apply_diffs() is going to return.

There are a scad of other options too, but these are undocumented because they're liable to change.

mark_conflicts HASH

This is the builtin resolver callback, used by apply_diffs() by default. See above for details of its interface. It causes apply_diffs() to return arrays looking a bit like:

[ @part_before_conflict,
  ">>>>>> diff1_name\n",
  @lines_1,              # Lines permuted by diff1 (only)
  ">>>>>> diff2_name\n"
  @lines_2,              # The same lines, permuted by diff2
  "<<<<<<\n",
  @part_after_conflict,
]

Which is probably the right thing to do if your array is going to be printed out one item per line.

BUGS AND TODO

This thing was going to be called Algorithm::Patch, but that's far too grandiose a description for the simplistic activity performed by this module. For one thing, Algorithm::Diff doesn't (yet) generate contexts, so fuzzing would be out of the question.

Algorithm::Diff::Apply does not yet optimise identical or similar change hunks from different diffs, although that is planned for the future.

The calling convention for options is ugly and confusing, and defeats prototyping. It's done like that to correspond with other modules in the Algorithm::{Diff,Patch} family.

AUTHOR

Andrew Chadwick, andrewc-algodiffaply@piffle.org.

LICENCE

Copyright (c) 2003 Andrew Chadwick. This program is free software; you may copy it, redistribute it, or modify it under the same terms as Perl itself.