[Bps-public-commit] r11071 - in SVN-PropDB: . lib/Prophet
jesse at bestpractical.com
jesse at bestpractical.com
Fri Mar 14 17:26:46 EDT 2008
Author: jesse
Date: Fri Mar 14 17:26:44 2008
New Revision: 11071
Added:
SVN-PropDB/lib/Prophet/ConflictingChange.pm
SVN-PropDB/lib/Prophet/ConflictingPropChange.pm
Modified:
SVN-PropDB/ (props changed)
SVN-PropDB/lib/Prophet/ChangeSet.pm
SVN-PropDB/lib/Prophet/Conflict.pm
SVN-PropDB/lib/Prophet/Sync/Source/SVN.pm
Log:
r28275 at 31b: jesse | 2008-03-14 17:24:21 -0400
* now we generate nullification changesets. next up, RESOLUTIONS
Modified: SVN-PropDB/lib/Prophet/ChangeSet.pm
==============================================================================
--- SVN-PropDB/lib/Prophet/ChangeSet.pm (original)
+++ SVN-PropDB/lib/Prophet/ChangeSet.pm Fri Mar 14 17:26:44 2008
@@ -7,11 +7,11 @@
use base qw/Class::Accessor/;
-__PACKAGE__->mk_accessors(qw/sequence_no source_uuid original_source_uuid original_sequence_no/);
+__PACKAGE__->mk_accessors(qw/sequence_no source_uuid original_source_uuid original_sequence_no is_nullification is_resolution/);
sub add_change {
my $self = shift;
- my %args = validate( @_, { change => 1 } );
+ my %args = validate( @_, { change => { isa => 'Prophet::Change'} } );
push @{ $self->{changes} }, $args{change};
}
Modified: SVN-PropDB/lib/Prophet/Conflict.pm
==============================================================================
--- SVN-PropDB/lib/Prophet/Conflict.pm (original)
+++ SVN-PropDB/lib/Prophet/Conflict.pm Fri Mar 14 17:26:44 2008
@@ -4,8 +4,10 @@
package Prophet::Conflict;
use base qw/Class::Accessor/;
+use Prophet::ConflictingPropChange;
+use Prophet::ConflictingChange;
-__PACKAGE__->mk_accessors(qw/prophet_handle source_change target_change/);
+__PACKAGE__->mk_accessors(qw/prophet_handle source_change target_change nullification/);
=head2 analyze_changeset Prophet::ChangeSet
@@ -17,73 +19,84 @@
my $self = shift;
my ($changeset) = validate_pos( @_, { isa => 'Prophet::ChangeSet' } );
- # XXX TODO
+ $self->generate_changeset_conflicts($changeset);
+ $self->generate_nullification_changeset;
+ $self->generate_conflict_resolution;
-# - a ConflictingChange if there are any conflicts in the change
-# - for each conflictingchange, we need to create a conflicting change property for each and every property that conflicts
+ return 1;
+
+}
+
+sub generate_changeset_conflicts {
+ my $self = shift;
+ my ($changeset) = validate_pos( @_, { isa => 'Prophet::ChangeSet' } );
for my $change ( $changeset->changes ) {
- if ( my $change_conflicts = $self->generate_change_onflicts($change) ) {
- push @{ $self->{conflicting_changes} }, $change_conflicts;
+ if ( my $change_conflicts = $self->_generate_change_conflicts($change) ) {
+ push @{ $self->conflicting_changes }, $change_conflicts;
}
}
-
- return 0;
-
}
-sub generate_change_conflict {
+sub _generate_change_conflicts {
my $self = shift;
my ($change) = validate_pos( @_, { isa => "Prophet::Change" } );
-
my $current_state = $self->prophet_handle->get_node_props( uuid => $change->node_uuid, type => $change->node_type );
-
my $file_op_conflict = '';
# It's ok to delete a node that exists
if ( $change->change_type eq 'delete' && !keys %$current_state ) {
$file_op_conflict = "delete_missing_file";
+ } elsif ( $change->change_type eq 'update' && !keys %$current_state ) {
+ $file_op_conflict = "update_missing_file";
} elsif ( $change->change_type eq 'add_file' && keys %$current_state ) {
$file_op_conflict = "create_existing_file";
} elsif ( $change->change_type eq 'add_dir' && keys %$current_state ) {
$file_op_conflict = "create_existing_dir";
}
+ my $change_conflict = Prophet::ConflictingChange->new(
+ { node_type => $change->node_type,
+ node_uuid => $change->node_uuid,
+ target_node_exists => ( keys %$current_state ? 1 : 0 ),
+ change_type => $change->change_type,
+ file_op_conflict => $file_op_conflict
+ }
+ );
+
+ push @{ $change_conflict->prop_conflicts }, $self->_generate_prop_change_conflicts( $change, $current_state );
+
+ return ( $#{ $change_conflict->prop_conflicts } || $file_op_conflict ) ? $change_conflict : undef;
+}
+
+
+sub _generate_prop_change_conflicts {
+ my $self = shift;
+ my $change = shift;
+ my $current_state = shift;
my @prop_conflicts;
- for my $propchange ( $change->prop_changes ) {
+ for my $prop_change ( $change->prop_changes ) {
# skip properties added by the change
- next if ( !defined $current_state->{ $propchange->name } && !defined $propchange->old_value );
+ next if ( !defined $current_state->{ $prop_change->name } && !defined $prop_change->old_value );
# If either the old version didn't have a value or the delta didn't have a value, then we know there's a conflict
my $s = {
- source_old_value => $propchange->old_value,
- target_old_value => $current_state->{$propchange_name},
- source_new_value => $propchange->new_value
+ name => $prop_change->name,
+ source_old_value => $prop_change->old_value,
+ target_old_value => $current_state->{ $prop_change->name },
+ source_new_value => $prop_change->new_value
};
- if ( !exists $current_state->{ $propchange->name }
- || !defined $propchange->old_value
- || ( $current_state->{ $propchange->name } ne $propchange->old_value ) )
+ if ( !exists $current_state->{ $prop_change->name }
+ || !defined $prop_change->old_value
+ || ( $current_state->{ $prop_change->name } ne $prop_change->old_value ) )
{
push @prop_conflicts, Prophet::ConflictingPropChange->new($s);
-
}
}
-
- my $change_conflict = Prophet::ConflictingChange->new(
- { node_type => $change->node_type,
- node_uuid => $change->node_uuid,
- target_node_exists => ( keys %$current_state ? 1 : 0 ),
- change_type => $change->change_type,
- fileop_conflict => $fileop_conflict
- }
- );
- push @{ $change_conflict->prop_conflicts }, @prop_conflicts;
-
- return $change_conflict if ( $#prop_conflicts || $fileop_conflict );
- return undef;
+ return @prop_conflicts;
}
=head2 conflicting_changes
@@ -101,36 +114,34 @@
sub generate_nullification_changeset {
my $self = shift;
-
my $nullification = Prophet::ChangeSet->new();
- return $nullification;
-}
-
-package Prophet::ConflictingChange;
-
-use base qw/Class::Accessor/;
-
-# change_type is one of: create update delete
-__PACKAGE__->mk_accessors(qw/node_type node_uuid source_node_exists target_node_exists change_type fileop_conflict/);
-=head2 prop_conflicts
+ for my $conflict ( @{ $self->conflicting_changes } ) {
+ my $nullify_conflict = Prophet::Change->new( { node_type => $conflict->node_type, node_uuid => $conflict->node_uuid });
-Returns a reference to an array of Prophet::ConflictingPropChange objects
-
-=cut
-
-sub prop_conflicts {
- my $self = shift;
+ if ( $conflict->file_op_conflict eq "delete_missing_file" ) {
+ $nullify_conflict->change_type('create_file');
+ } elsif ( $conflict->file_op_conflict eq "update_missing_file" ) {
+ $nullify_conflict->change_type('create_file');
+ } elsif ( $conflict->file_op_conflict eq "create_existing_file" ) {
+ $nullify_conflict->change_type('delete');
+ } elsif ( $conflict->file_op_conflict ) {
+ die "We don't know how to deal with a conflict of type " . $conflict->file_op_conflict;
+ }
- $self->{'prop_conflicts'} ||= ();
- return $self->{prop_conflicts};
+ # now that we've sorted out all the file-level conflicts, we need to get properties in order
+ for my $prop_conflict ( @{ $conflict->prop_conflicts } ) {
+ $nullify_conflict->add_prop_change(
+ name => $prop_conflict->name,
+ old => $prop_conflict->target_value,
+ new => $prop_conflict->source_old_value
+ );
+ }
+ $nullification->add_change( change => $nullify_conflict );
+ }
+ $self->nullification_changeset($nullification);
}
-package Prophet::ConflictingPropChange;
-
-use base qw/Class::Accessor/;
-
-__PACKAGE__->mk_accessors(qw/source_old_value target_value source_new_value/);
-
1;
+
Added: SVN-PropDB/lib/Prophet/ConflictingChange.pm
==============================================================================
--- (empty file)
+++ SVN-PropDB/lib/Prophet/ConflictingChange.pm Fri Mar 14 17:26:44 2008
@@ -0,0 +1,27 @@
+
+use warnings;
+use strict;
+
+package Prophet::ConflictingChange;
+use Prophet::ConflictingPropChange;
+
+use base qw/Class::Accessor/;
+
+# change_type is one of: add_file add_dir update delete
+__PACKAGE__->mk_accessors(qw/node_type node_uuid source_node_exists target_node_exists change_type file_op_conflict/);
+
+=head2 prop_conflicts
+
+Returns a reference to an array of Prophet::ConflictingPropChange objects
+
+=cut
+
+sub prop_conflicts {
+ my $self = shift;
+
+ $self->{'prop_conflicts'} ||= ();
+ return $self->{prop_conflicts};
+
+}
+
+1;
Added: SVN-PropDB/lib/Prophet/ConflictingPropChange.pm
==============================================================================
--- (empty file)
+++ SVN-PropDB/lib/Prophet/ConflictingPropChange.pm Fri Mar 14 17:26:44 2008
@@ -0,0 +1,9 @@
+
+use warnings;
+use strict;
+package Prophet::ConflictingPropChange;
+use base qw/Class::Accessor/;
+
+__PACKAGE__->mk_accessors(qw/name source_old_value target_value source_new_value/);
+
+1;
Modified: SVN-PropDB/lib/Prophet/Sync/Source/SVN.pm
==============================================================================
--- SVN-PropDB/lib/Prophet/Sync/Source/SVN.pm (original)
+++ SVN-PropDB/lib/Prophet/Sync/Source/SVN.pm Fri Mar 14 17:26:44 2008
@@ -40,6 +40,15 @@
return $self->ra->get_uuid;
}
+=head2 fetch_changesets { after => SEQUENCE_NO }
+
+Fetch all changesets from the source.
+
+Returns a reference to an array of L<Prophet::ChangeSet> objects.
+
+
+=cut
+
sub fetch_changesets {
my $self = shift;
my %args = validate( @_, { after => 1});
@@ -77,8 +86,7 @@
original_source_uuid => $revprops->{original_source_uuid},
original_sequence_no => $revprops->{original_sequence_no},
- }
- );
+ });
# add each node's changes to the changeset
for my $path ( keys %{ $entry->{'paths'} } ) {
@@ -193,10 +201,8 @@
my ($changeset) = validate_pos(@_, { isa => 'Prophet::ChangeSet'});
if (my $conflict = $self->conflicts_from_changeset($changeset ) ) {
-
- if (there's a conflict ) {
- figure out our conflict resolution
- generate a nullification change
+ #figure out our conflict resolution
+ # generate a nullification change
# IMPORTANT: these should be an atomic unit. dying here would be poor.
# BUT WE WANT THEM AS THREEDIFFERENT SVN REVS
#integrate the nullification change
More information about the Bps-public-commit
mailing list