Break LCS diffing to its own function. Minor style tweaks.
FossilOrigin-Name: bbd2a789cb94c5ac0a88f470734d6abfe4b1cbb38c6c17113f0e2430a6663630
This commit is contained in:
parent
b1ff94c067
commit
897837b463
1 changed files with 111 additions and 98 deletions
209
shelldap
209
shelldap
|
|
@ -1238,6 +1238,113 @@ sub unwrap_line {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
### Given an LDAP Entry object $e, an array reference to it's LDIF original
|
||||||
|
### content, and another array reference to updated LDIF content, run an LCS
|
||||||
|
### comparison, modifying the Entry object in place.
|
||||||
|
###
|
||||||
|
sub diff {
|
||||||
|
my $self = shift;
|
||||||
|
my $e = shift;
|
||||||
|
my $orig = shift;
|
||||||
|
my $new = shift;
|
||||||
|
|
||||||
|
$self->unwrap_line( $orig );
|
||||||
|
$self->unwrap_line( $new );
|
||||||
|
|
||||||
|
# parser subref
|
||||||
|
#
|
||||||
|
my $parse = sub {
|
||||||
|
my $line = shift || $_;
|
||||||
|
return if $line =~ /^\#/; # ignore comments
|
||||||
|
my ( $attr, $val ) = ( $1, $2 ) if $line =~ /^(.+?): (.*)$/;
|
||||||
|
return unless $attr;
|
||||||
|
return if index($attr, ':') != -1; # ignore base64
|
||||||
|
return ( $attr, $val );
|
||||||
|
};
|
||||||
|
|
||||||
|
my $diff = Algorithm::Diff->new( $orig, $new );
|
||||||
|
HUNK:
|
||||||
|
while ( $diff->Next() ) {
|
||||||
|
next if $diff->Same();
|
||||||
|
my $diff_bit = $diff->Diff();
|
||||||
|
my %seen_attr;
|
||||||
|
|
||||||
|
# attr removal hunk
|
||||||
|
#
|
||||||
|
if ( $diff_bit == 1 ) {
|
||||||
|
foreach ( $diff->Items(1) ) {
|
||||||
|
my ( $attr, $val ) = $parse->( $_ ) or next;
|
||||||
|
$self->debug("DELETE: $_");
|
||||||
|
$e->delete( $attr => [ $val ] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# attr insertion hunk
|
||||||
|
#
|
||||||
|
if ( $diff_bit == 2 ) {
|
||||||
|
foreach ( $diff->Items(2) ) {
|
||||||
|
my ( $attr, $val ) = $parse->( $_ ) or next;
|
||||||
|
$self->debug("INSERT: $_");
|
||||||
|
$e->add( $attr => $val );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# attr change hunk
|
||||||
|
#
|
||||||
|
if ( $diff_bit == 3 ) {
|
||||||
|
|
||||||
|
# modification to existing line
|
||||||
|
#
|
||||||
|
foreach ( $diff->Items(2) ) {
|
||||||
|
my ( $attr, $val ) = $parse->( $_ ) or next;
|
||||||
|
$self->debug("MODIFY: $_");
|
||||||
|
|
||||||
|
my $cur_vals = $e->get_value( $attr, asref => 1 ) || [];
|
||||||
|
my $cur_valcount = scalar @$cur_vals;
|
||||||
|
next if $cur_valcount == 0; # should have been an 'add'
|
||||||
|
|
||||||
|
# replace immediately
|
||||||
|
#
|
||||||
|
if ( $cur_valcount == 1 ) {
|
||||||
|
$e->replace( $attr => $val );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
# retain attributes that allow multiples, so updating
|
||||||
|
# one attribute doesn't inadvertently remove others with
|
||||||
|
# the same name.
|
||||||
|
#
|
||||||
|
next if $seen_attr{ $attr };
|
||||||
|
my @new_vals;
|
||||||
|
foreach my $line ( @$new ) {
|
||||||
|
my ( $new_attr, $new_val ) = $parse->( $line ) or next;
|
||||||
|
next unless $new_attr eq $attr;
|
||||||
|
$seen_attr{ $attr }++;
|
||||||
|
push @new_vals, $new_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
$e->replace( $attr => \@new_vals );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# deletion within the same hunk
|
||||||
|
#
|
||||||
|
foreach ( $diff->Items(1) ) {
|
||||||
|
my ( $attr, $val ) = $parse->( $_ ) or next;
|
||||||
|
my $cur_vals = $e->get_value( $attr, asref => 1 ) || [];
|
||||||
|
my $cur_valcount = scalar @$cur_vals;
|
||||||
|
|
||||||
|
next if $cur_valcount == 1;
|
||||||
|
next if $seen_attr{ $attr };
|
||||||
|
$self->debug("DELETE: $_");
|
||||||
|
$e->delete( $attr => [ $val ] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
########################################################################
|
||||||
### S H E L L M E T H O D S
|
### S H E L L M E T H O D S
|
||||||
########################################################################
|
########################################################################
|
||||||
|
|
@ -1628,11 +1735,9 @@ sub run_edit
|
||||||
# checksum it, then open it in an editor
|
# checksum it, then open it in an editor
|
||||||
#
|
#
|
||||||
my $hash_orig = $self->chksum( $self->{'ldif_fname'} );
|
my $hash_orig = $self->chksum( $self->{'ldif_fname'} );
|
||||||
my @edit_args = split(' ',$self->{'editor'});
|
my @edit_args = split /\s+/, $self->{'editor'};
|
||||||
push(@edit_args,$self->{'ldif_fname'});
|
push @edit_args, $self->{'ldif_fname'};
|
||||||
# system( $self->{'editor'}, $self->{'ldif_fname'} ) &&
|
system( @edit_args ) && die "Unable to launch editor: $!\n";
|
||||||
system( @edit_args ) &&
|
|
||||||
die "Unable to launch editor: $!\n";
|
|
||||||
|
|
||||||
# detect a total lack of change
|
# detect a total lack of change
|
||||||
#
|
#
|
||||||
|
|
@ -1663,99 +1768,7 @@ sub run_edit
|
||||||
my @new_ldif = <LDIF>;
|
my @new_ldif = <LDIF>;
|
||||||
close LDIF;
|
close LDIF;
|
||||||
|
|
||||||
# parser subref
|
$self->diff( $e, \@orig_ldif, \@new_ldif );
|
||||||
#
|
|
||||||
my $parse = sub {
|
|
||||||
my $line = shift || $_;
|
|
||||||
return if $line =~ /^\#/; # ignore comments
|
|
||||||
my ( $attr, $val ) = ( $1, $2 ) if $line =~ /^(.+?): (.*)$/;
|
|
||||||
return unless $attr;
|
|
||||||
return if index($attr, ':') != -1; # ignore base64
|
|
||||||
return ( $attr, $val );
|
|
||||||
};
|
|
||||||
|
|
||||||
$self->unwrap_line( \@orig_ldif );
|
|
||||||
$self->unwrap_line( \@new_ldif );
|
|
||||||
|
|
||||||
my $diff = Algorithm::Diff->new( \@orig_ldif, \@new_ldif );
|
|
||||||
HUNK:
|
|
||||||
while ( $diff->Next() ) {
|
|
||||||
next if $diff->Same();
|
|
||||||
my $diff_bit = $diff->Diff();
|
|
||||||
my %seen_attr;
|
|
||||||
|
|
||||||
# attr removal hunk
|
|
||||||
#
|
|
||||||
if ( $diff_bit == 1 ) {
|
|
||||||
foreach ( $diff->Items(1) ) {
|
|
||||||
my ( $attr, $val ) = $parse->( $_ ) or next;
|
|
||||||
$self->debug("DELETE: $_");
|
|
||||||
$e->delete( $attr => [ $val ] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# attr insertion hunk
|
|
||||||
#
|
|
||||||
if ( $diff_bit == 2 ) {
|
|
||||||
foreach ( $diff->Items(2) ) {
|
|
||||||
my ( $attr, $val ) = $parse->( $_ ) or next;
|
|
||||||
$self->debug("INSERT: $_");
|
|
||||||
$e->add( $attr => $val );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# attr change hunk
|
|
||||||
#
|
|
||||||
if ( $diff_bit == 3 ) {
|
|
||||||
|
|
||||||
# modification to existing line
|
|
||||||
#
|
|
||||||
foreach ( $diff->Items(2) ) {
|
|
||||||
my ( $attr, $val ) = $parse->( $_ ) or next;
|
|
||||||
$self->debug("MODIFY: $_");
|
|
||||||
|
|
||||||
my $cur_vals = $e->get_value( $attr, asref => 1 ) || [];
|
|
||||||
my $cur_valcount = scalar @$cur_vals;
|
|
||||||
next if $cur_valcount == 0; # should have been an 'add'
|
|
||||||
|
|
||||||
# replace immediately
|
|
||||||
#
|
|
||||||
if ( $cur_valcount == 1 ) {
|
|
||||||
$e->replace( $attr => $val );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
# retain attributes that allow multiples, so updating
|
|
||||||
# one attribute doesn't inadvertently remove others with
|
|
||||||
# the same name.
|
|
||||||
#
|
|
||||||
next if $seen_attr{ $attr };
|
|
||||||
my @new_vals;
|
|
||||||
foreach my $line ( @new_ldif ) {
|
|
||||||
my ( $new_attr, $new_val ) = $parse->( $line ) or next;
|
|
||||||
next unless $new_attr eq $attr;
|
|
||||||
$seen_attr{ $attr }++;
|
|
||||||
push @new_vals, $new_val;
|
|
||||||
}
|
|
||||||
|
|
||||||
$e->replace( $attr => \@new_vals );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# deletion within the same hunk
|
|
||||||
#
|
|
||||||
foreach ( $diff->Items(1) ) {
|
|
||||||
my ( $attr, $val ) = $parse->( $_ ) or next;
|
|
||||||
my $cur_vals = $e->get_value( $attr, asref => 1 ) || [];
|
|
||||||
my $cur_valcount = scalar @$cur_vals;
|
|
||||||
|
|
||||||
next if $cur_valcount == 1;
|
|
||||||
next if $seen_attr{ $attr };
|
|
||||||
$self->debug("DELETE: $_");
|
|
||||||
$e->delete( $attr => [ $val ] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
my $update = sub { return $e->update( $self->ldap ); };
|
my $update = sub { return $e->update( $self->ldap ); };
|
||||||
my $rv = $self->with_retry( $update );
|
my $rv = $self->with_retry( $update );
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue