Algorithm-Merge

 view release on metacpan or  search on metacpan

Merge.pm  view on Meta::CPAN

$abc_s[(A|B)*8+B] = AB_B;
$abc_s[(A|C)*8+A] = AC_A;
$abc_s[(A|C)*8+C] = AC_C;
$abc_s[(B|C)*8+B] = BC_B;
$abc_s[(B|C)*8+C] = BC_C;

sub traverse_sequences3 {
    my $adoc      = shift;                                  # array ref
    my $bdoc      = shift;                                  # array ref
    my $cdoc      = shift;                                  # array ref
    my $callbacks = shift || {};
    my $keyGen    = shift;
    my $a_diff     = $callbacks->{'A_DIFF'} || sub { };
    my $b_diff     = $callbacks->{'B_DIFF'} || sub { };
    my $c_diff     = $callbacks->{'C_DIFF'} || sub { };
    my $no_change = $callbacks->{'NO_CHANGE'} || sub { };
    my $conflict  = $callbacks->{'CONFLICT'} || sub { };

    my $b_len = scalar(@{$bdoc});
    my $c_len = scalar(@{$cdoc});
    my $target_len = $b_len < $c_len ? $b_len : $c_len;
    my $bc_different_lengths = $b_len != $c_len;

    my(@bdoc_save, @cdoc_save);

    # make these into traverse_sequences calls
    my($left, $right);
    my %diffs;

    my $ts_callbacks = {
        DISCARD_A => sub { # discard left
            push @{$diffs{$left}}, $_[0];
        },
        DISCARD_B => sub { # discard right
            push @{$diffs{$right}}, $_[1];
        },
    };

    @diffs{(AB_A, AB_B)} = ([], []);
    $left = AB_A; $right = AB_B;
    Algorithm::Diff::traverse_sequences( $adoc, $bdoc, $ts_callbacks, $keyGen, @_);

    @diffs{(AC_A, AC_C)} = ([], []);
    $left = AC_A; $right = AC_C;
    Algorithm::Diff::traverse_sequences( $adoc, $cdoc, $ts_callbacks, $keyGen, @_);

    if($bc_different_lengths) {
        
        @diffs{(CB_C, CB_B)} = ([], []);
        $left = CB_C; $right = CB_B;
        Algorithm::Diff::traverse_sequences( $cdoc, $bdoc, $ts_callbacks, $keyGen, @_);

        @diffs{(BC_B, BC_C)} = ([], []);  
        $left = BC_B; $right = BC_C; 
        Algorithm::Diff::traverse_sequences( $bdoc, $cdoc, $ts_callbacks, $keyGen, @_);

        if(join(",", @{$diffs{&CB_B}}) ne join(",", @{$diffs{&BC_B}}) ||
           join(",", @{$diffs{&CB_C}}) ne join(",", @{$diffs{&BC_C}}))
        {
            @bdoc_save = splice @{$bdoc}, $target_len;
            @cdoc_save = splice @{$cdoc}, $target_len;
            
            carp "Algorithm::Diff::diff is not symmetric for second and third sequences - results might not be correct";
        }

        @diffs{(BC_B, BC_C)} = ([], []);
        $left = BC_B; $right = BC_C;
        Algorithm::Diff::traverse_sequences( $bdoc, $cdoc, $ts_callbacks, $keyGen, @_);

        if(scalar(@bdoc_save) || scalar(@cdoc_save)) {
            push @{$diffs{&BC_B}}, ($target_len .. $b_len) if $target_len < $b_len;
            push @{$diffs{&BC_C}}, ($target_len .. $c_len) if $target_len < $c_len;
        
            push @{$bdoc}, @bdoc_save; undef @bdoc_save;
            push @{$cdoc}, @cdoc_save; undef @cdoc_save;
        }
    }
    else {
        @diffs{(BC_B, BC_C)} = ([], []);
        $left = BC_B; $right = BC_C;
        Algorithm::Diff::traverse_sequences( $bdoc, $cdoc, $ts_callbacks, $keyGen, @_);
    }

    my @pos;
    @pos[A, B, C] = (0, 0, 0);

    my @sizes;
    @sizes[A, B, C] = ( scalar(@{$adoc}), scalar(@{$bdoc}), scalar(@{$cdoc}) );

    my @matches;
    $#matches = 32;

Merge.pm  view on Meta::CPAN

        #main::diag(join"", "  match: $match");
        &{$Callback_Map[$switch][0]}(@args)
            if $Callback_Map[$switch];
    }
}

sub merge {
    my $pivot             = shift;                                  # array ref
    my $doca              = shift;                                  # array ref
    my $docb              = shift;                                  # array ref
    my $callbacks         = shift || {};
    my $keyGen            = shift;

    my $conflictCallback  = $callbacks -> {'CONFLICT'} || sub ($$) { (
        q{<!-- ------ START CONFLICT ------ -->},
        (@{$_[0]}),
        q{<!-- ---------------------------- -->},
        (@{$_[1]}),
        q{<!-- ------  END  CONFLICT ------ -->},
    ) };

    my $diff = diff3($pivot, $doca, $docb, $keyGen, @_);

#    print Data::Dumper -> Dump([$diff]), "\n";

Merge.pm  view on Meta::CPAN


 @diff   = diff3(\@ancestor, \@a, \@b);

 @diff   = diff3(\@ancestor, \@a, \@b, $key_generation_function);

 $diff   = diff3(\@ancestor, \@a, \@b);

 $diff   = diff3(\@ancestor, \@a, \@b, $key_generation_function);

 @trav   = traverse_sequences3(\@ancestor, \@a, \@b, { 
               # callbacks
           });

 @trav   = traverse_sequences3(\@ancestor, \@a, \@b, { 
               # callbacks
           }, $key_generation_function);

 $trav   = traverse_sequences3(\@ancestor, \@a, \@b, { 
               # callbacks
           });

 $trav   = traverse_sequences3(\@ancestor, \@a, \@b, { 
               # callbacks
           }, $key_generation_function);


=head1 USAGE

This module complements L<Algorithm::Diff|Algorithm::Diff> by 
providing three-way merge and diff functions.

In this documentation, the first list to C<diff3>, C<merge>, and 
C<traverse_sequences3> is 

Merge.pm  view on Meta::CPAN

 (@left),
 q{<!-- ---------------------------- -->},
 (@right),
 q{<!-- ------  END  CONFLICT ------ -->},

=head2 traverse_sequences3

This is the workhorse function that goes through the three sequences 
and calls the callback functions.

The following callbacks are supported.

=over 4

=item NO_CHANGE

This is called if all three sequences have the same element at the 
current position.  The arguments are the current positions within each 
sequence, the first argument being the current position within the 
first sequence.

README  view on Meta::CPAN


     @diff   = diff3(\@ancestor, \@a, \@b);

     @diff   = diff3(\@ancestor, \@a, \@b, $key_generation_function);

     $diff   = diff3(\@ancestor, \@a, \@b);

     $diff   = diff3(\@ancestor, \@a, \@b, $key_generation_function);

     @trav   = traverse_sequences3(\@ancestor, \@a, \@b, { 
                   # callbacks
               });

     @trav   = traverse_sequences3(\@ancestor, \@a, \@b, { 
                   # callbacks
               }, $key_generation_function);

     $trav   = traverse_sequences3(\@ancestor, \@a, \@b, { 
                   # callbacks
               });

     $trav   = traverse_sequences3(\@ancestor, \@a, \@b, { 
                   # callbacks
               }, $key_generation_function);

USAGE
    This module complements Algorithm::Diff by providing three-way merge and
    diff functions.

    In this documentation, the first list to "diff3", "merge", and
    "traverse_sequences3" is called the `original' list. The second list is
    the `left' list. The third list is the `right' list.

README  view on Meta::CPAN

     q{<!-- ------ START CONFLICT ------ -->},
     (@left),
     q{<!-- ---------------------------- -->},
     (@right),
     q{<!-- ------  END  CONFLICT ------ -->},

  traverse_sequences3
    This is the workhorse function that goes through the three sequences and
    calls the callback functions.

    The following callbacks are supported.

    NO_CHANGE
        This is called if all three sequences have the same element at the
        current position. The arguments are the current positions within
        each sequence, the first argument being the current position within
        the first sequence.

    A_DIFF
        This is called if the first sequence is different than the other two
        sequences at the current position. This callback will be called with



( run in 0.876 second using v1.01-cache-2.11-cpan-10033ea8487 )