[Bps-public-commit] r11288 - in SVN-PropDB: . lib/Prophet lib/Prophet/Sync/Source t
jesse at bestpractical.com
jesse at bestpractical.com
Mon Mar 31 03:44:28 EDT 2008
Author: jesse
Date: Mon Mar 31 03:44:28 2008
New Revision: 11288
Modified:
SVN-PropDB/ (props changed)
SVN-PropDB/lib/Prophet/Change.pm
SVN-PropDB/lib/Prophet/Conflict.pm
SVN-PropDB/lib/Prophet/Handle.pm
SVN-PropDB/lib/Prophet/Sync/Source.pm
SVN-PropDB/lib/Prophet/Sync/Source/SVN.pm
SVN-PropDB/t/simple-conflicting-merge.t
Log:
r28827 at 99-205-68-110: jesse | 2008-03-30 21:44:12 -1000
debugging a phantom commit
Modified: SVN-PropDB/lib/Prophet/Change.pm
==============================================================================
--- SVN-PropDB/lib/Prophet/Change.pm (original)
+++ SVN-PropDB/lib/Prophet/Change.pm Mon Mar 31 03:44:28 2008
@@ -41,7 +41,7 @@
sub prop_changes {
my $self = shift;
- return @{$self->{prop_changes}};
+ return @{$self->{prop_changes}||[]};
}
Modified: SVN-PropDB/lib/Prophet/Conflict.pm
==============================================================================
--- SVN-PropDB/lib/Prophet/Conflict.pm (original)
+++ SVN-PropDB/lib/Prophet/Conflict.pm Mon Mar 31 03:44:28 2008
@@ -8,7 +8,7 @@
use Prophet::ConflictingPropChange;
use Prophet::ConflictingChange;
-__PACKAGE__->mk_accessors(qw/prophet_handle nullification_changeset resolution_changeset autoresolved/);
+__PACKAGE__->mk_accessors(qw/prophet_handle resolvers nullification_changeset resolution_changeset autoresolved/);
=head2 analyze_changeset Prophet::ChangeSet
@@ -26,10 +26,40 @@
return unless (@{$self->conflicting_changes});
$self->generate_nullification_changeset;
- $self->attempt_automatic_conflict_resolution;
-
+
return 1;
+}
+sub _resolution_failed {
+
+ return sub { die "conflict not resolved." };
+}
+
+
+sub generate_resolution {
+ my $self = shift;
+
+ my @resolvers = (
+
+ sub { $self->attempt_automatic_conflict_resolution(@_) },
+ @{$self->resolvers || []},
+ $self->_resolution_failed);
+
+
+ my $resolutions = Prophet::ChangeSet->new( { is_resolution => 1 } );
+ for my $conflict ( @{ $self->conflicting_changes } ) {
+ for (@resolvers) {
+ if (my $resolution = $_->($conflict)) {
+ warn $_;
+ $resolutions->add_change(change => $resolution);
+ last;
+ }
+ }
+ }
+
+ $self->resolution_changeset($resolutions);
+
+ return 1;
}
=head2 attempt_automatic_conflict_resolution
@@ -64,14 +94,29 @@
sub attempt_automatic_conflict_resolution {
my $self = shift;
+ my $conflict = shift;
+ # for everything from the changeset that is the same as the old value of the target replica
+ # we can skip applying
+warn "attempting to resolve conflict automatically";
+warn Dumper(@_);use Data::Dumper;
+ return 0 if $conflict->file_op_conflict;
+
+ my $resolution = Prophet::Change->new( { is_resolution => 1,
+ node_type => $conflict->node_type,
+ node_uuid => $conflict->node_uuid });
- # for everything from the changeset that is the same as the old value of the target replica
- # we can skip applying
+ for my $prop_change ( @{$conflict->prop_conflicts} ) {
+ return 0 unless $prop_change->target_value eq $prop_change->source_new_value
+ }
- warn "have not implemented automatic conflict resolution yet";
+warn Dumper($resolution);
$self->autoresolved(1);
+ return $resolution;
+
+
+
@@ -208,7 +253,7 @@
sub generate_nullification_changeset {
my $self = shift;
- my $nullification = Prophet::ChangeSet->new();
+ my $nullification = Prophet::ChangeSet->new( {is_nullification => 1});
for my $conflict ( @{ $self->conflicting_changes } ) {
my $nullify_conflict = Prophet::Change->new( { node_type => $conflict->node_type, node_uuid => $conflict->node_uuid });
@@ -221,7 +266,11 @@
$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;
+ } else {
+ $nullify_conflict->change_type('update_file');
}
+
+
# 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 } ) {
Modified: SVN-PropDB/lib/Prophet/Handle.pm
==============================================================================
--- SVN-PropDB/lib/Prophet/Handle.pm (original)
+++ SVN-PropDB/lib/Prophet/Handle.pm Mon Mar 31 03:44:28 2008
@@ -113,7 +113,8 @@
my $changeset = shift;
$self->begin_edit();
- $self->_integrate_change($_) for ($changeset->changes);
+ $self->record_changeset($changeset);
+
$self->_set_original_source_metadata($changeset);
warn "to commit... " if ($DEBUG);
my $changed = $self->current_edit->root->paths_changed;
@@ -122,6 +123,19 @@
$self->commit_edit();
}
+sub record_changeset {
+ my $self = shift;
+ my $changeset = shift;
+
+
+ my $inside_edit = $self->current_edit ? 1: 0;
+ warn "==> to record $changeset / $inside_edit";
+ $self->begin_edit() unless ($inside_edit);
+ $self->_integrate_change($_) for ($changeset->changes);
+ $self->commit_edit() unless ($inside_edit);
+
+}
+
sub _set_original_source_metadata {
my $self = shift;
my $change = shift;
@@ -137,7 +151,7 @@
my $change = shift;
my %new_props = map { $_->name => $_->new_value } $change->prop_changes;
-
+
if ( $change->change_type eq 'add_file' ) {
$self->create_node(
type => $change->node_type,
@@ -294,7 +308,8 @@
sub file_for {
my $self = shift;
my %args = validate( @_, { uuid => 1, type => 1 } );
- my $file = join( "/", $self->db_root, ,$args{'type'}, $args{'uuid'} );
+ Carp::cluck unless $args{uuid};
+ my $file = join( "/", $self->db_root ,$args{'type'}, $args{'uuid'} );
return $file;
}
Modified: SVN-PropDB/lib/Prophet/Sync/Source.pm
==============================================================================
--- SVN-PropDB/lib/Prophet/Sync/Source.pm (original)
+++ SVN-PropDB/lib/Prophet/Sync/Source.pm Mon Mar 31 03:44:28 2008
@@ -51,6 +51,7 @@
sub import_changesets {
my $self = shift;
my %args = validate( @_, { from => { isa => 'Prophet::Sync::Source'},
+ resolver => { optional => 1},
conflict_callback => { optional => 1 } } );
my $source = $args{'from'};
@@ -60,7 +61,7 @@
for my $changeset (@$changesets_to_integrate) {
next if ( $self->has_seen_changeset($changeset) );
- $self->integrate_changeset( changeset => $changeset, conflict_callback =>$args{conflict_callback});
+ $self->integrate_changeset( changeset => $changeset, conflict_callback => $args{conflict_callback}, resolver => $args{resolver});
}
}
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 Mon Mar 31 03:44:28 2008
@@ -199,7 +199,6 @@
my $conflict = Prophet::Conflict->new({ prophet_handle => $self->prophet_handle});
$conflict->analyze_changeset($changeset);
-
return undef unless @{$conflict->conflicting_changes};
@@ -219,6 +218,7 @@
sub integrate_changeset {
my $self = shift;
my %args = validate( @_, { changeset => {isa => 'Prophet::ChangeSet'},
+ resolver => { optional => 1},
conflict_callback => { optional => 1 }
}
);
@@ -250,15 +250,22 @@
if (my $conflict = $self->conflicts_from_changeset($changeset ) ) {
$args{conflict_callback}->($conflict) if $args{'conflict_callback'};
+ $conflict->resolver(sub { $args{resolver}->(@_) }) if $args{resolver};
+ my $resolutions = $conflict->generate_resolution;
Carp::cluck;
#figure out our conflict resolution
# IMPORTANT: these should be an atomic unit. dying here would be poor. BUT WE WANT THEM AS THREEDIFFERENT SVN REVS
- #integrate the nullification change
- # integrate the original change
- # integrate the conflict resolution change
+ # integrate the nullification change
+ $self->prophet_handle->record_changeset($conflict->nullification_changeset);
+
+ # integrate the original change
+ $self->prophet_handle->integrate_changeset($changeset);
+ # integrate the conflict resolution change
+ $self->prophet_handle->record_changeset($conflict->resolution_changeset);
+
} else {
$self->prophet_handle->integrate_changeset($changeset);
Modified: SVN-PropDB/t/simple-conflicting-merge.t
==============================================================================
--- SVN-PropDB/t/simple-conflicting-merge.t (original)
+++ SVN-PropDB/t/simple-conflicting-merge.t Mon Mar 31 03:44:28 2008
@@ -3,7 +3,7 @@
use warnings;
use strict;
-use Prophet::Test tests => 20;
+use Prophet::Test tests => 28;
as_alice {
run_ok('prophet-node-create', [qw(--type Bug --status new --from alice )], "Created a record as alice");
@@ -55,14 +55,18 @@
my $conflict_obj;
+my $repo = repo_uri_for('bob');
+diag `svn log -v $repo`;
+
eval {
$target->import_changesets(
from => $source,
conflict_callback => sub {
- $conflict_obj = shift; die }
+ $conflict_obj = shift;
+ }
);
};
-
+# warn $@;
isa_ok($conflict_obj, 'Prophet::Conflict');
my @conflicting_changes = @{$conflict_obj->conflicting_changes};
@@ -79,10 +83,27 @@
is($c->source_new_value,'stalled');
is($c->target_value,'stalled');
- # Throw away the return. we wanted to inspect the conflict but not apply anything
+ # Check to see if the nullification changeset worked out ok
+ my $nullification = $conflict_obj->nullification_changeset;
+ isa_ok($nullification, "Prophet::ChangeSet");
+ ok($nullification->is_nullification);
+ my @reverts = $nullification->changes;
+ is($#reverts, 0, "Found one change");
+ my $revert = shift @reverts;
+ is($revert->change_type, 'update_file');
+ my @prop_changes = $revert->prop_changes;
+ is ( $#prop_changes, 0, "Found one prop change");
+ is ($prop_changes[0]->name, 'status');
+ is($prop_changes[0]->old_value, 'stalled');
+ is($prop_changes[0]->new_value, 'new');
+
+
+ # Throw away the return. we wanted to inspect the conflict but not apply anything
+my $repo = repo_uri_for('bob');
+diag `svn log -v $repo`;
# at the first sign of conflict, we're going to call back to a routine we inject to see if the conflict object is as we expect it
More information about the Bps-public-commit
mailing list