[Bps-public-commit] r11408 - in SVN-PropDB: . doc lib/Prophet/Sync/Source lib/Prophet/Test

jesse at bestpractical.com jesse at bestpractical.com
Wed Apr 2 21:48:03 EDT 2008


Author: jesse
Date: Wed Apr  2 21:48:02 2008
New Revision: 11408

Modified:
   SVN-PropDB/   (props changed)
   SVN-PropDB/doc/todo
   SVN-PropDB/lib/Prophet/Sync/Source.pm
   SVN-PropDB/lib/Prophet/Sync/Source/SVN.pm
   SVN-PropDB/lib/Prophet/Test/Participant.pm

Log:
 r29018 at 70-5-158-116:  jesse | 2008-04-02 15:45:39 -1000
 * checkpoint


Modified: SVN-PropDB/doc/todo
==============================================================================
--- SVN-PropDB/doc/todo	(original)
+++ SVN-PropDB/doc/todo	Wed Apr  2 21:48:02 2008
@@ -1,12 +1,21 @@
 
 Todo
 
-- test byzantine sync behaviour
 
-- handle conflicting conflict resolutions
+-  ::CLI should automatically discover an app's model class based on the type name
 
+- Creation of bug tracking model classes
+
+
+
+- validation on bug tracker fields (status/severity)
+
+- ability to add comments to a bug (visible history entries)
+
+- push to a remote prophet
+- pull from a remote RT by url and query
+- push to a remote RT
 
-- base bug tracking schema
 - Replace this todo list with a svb database
 - elegant support for large attachments
 - RESTy web server API to let third-parties build non-perl apps against a Prophet Depot
@@ -51,3 +60,7 @@
 - prompt for resolution of conflicts
 - handle file_conflict
 
+- test byzantine sync behaviour
+- handle conflicting conflict resolutions
+- base bug tracking schema
+

Modified: SVN-PropDB/lib/Prophet/Sync/Source.pm
==============================================================================
--- SVN-PropDB/lib/Prophet/Sync/Source.pm	(original)
+++ SVN-PropDB/lib/Prophet/Sync/Source.pm	Wed Apr  2 21:48:02 2008
@@ -55,7 +55,8 @@
             use_resdb         => { optional => 1 },
             resolver          => { optional => 1 },
             resolver_class    => { optional => 1 },
-            conflict_callback => { optional => 1 }
+            conflict_callback => { optional => 1 },
+			reporting_callback => { optional => 1 }
         }
     );
 
@@ -73,14 +74,183 @@
         $self->integrate_changeset(
             changeset         => $changeset,
             conflict_callback => $args{conflict_callback},
+ 			reporting_callback => $args{'reporting_callback'},
             resolver          => $args{resolver},
             resolver_class    => $args{'resolver_class'},
             resdb             => $resdb
         );
 
+
     }
 }
 
+=head2 integrate_changeset L<Prophet::ChangeSet>
+
+If there are conflicts, generate a nullification change, figure out a conflict resolution and apply the nullification, original change and resolution all at once (as three separate changes).
+
+If there are no conflicts, just apply the change.
+
+=cut
+
+sub integrate_changeset {
+    my $self = shift;
+    my %args = validate(
+        @_,
+        {   changeset         => { isa      => 'Prophet::ChangeSet' },
+            resolver          => { optional => 1 },
+            resolver_class    => { optional => 1 },
+            resdb             => { optional => 1 },
+            conflict_callback => { optional => 1 },
+            reporting_callback => {optional =>1}
+        }
+    );
+
+    my $changeset = $args{'changeset'};
+
+    # when we start to integrate a changeset, we need to do a bit of housekeeping
+    # We never want to merge in:
+    # merge tickets that describe merges from the local node
+
+    # When we integrate changes, sometimes we will get handed changes we already know about.
+    #   - changes from local
+    #   - changes from some other party we've merged from
+    #   - merge tickets for the same
+    # we'll want to skip or remove those changesets
+
+    return if $changeset->original_source_uuid eq $self->prophet_handle->uuid;
+
+    $self->remove_redundant_data($changeset);    #Things we have already seen
+
+    return if ( $changeset->is_empty or $changeset->is_nullification );
+
+    if ( my $conflict = $self->conflicts_from_changeset($changeset) ) {
+        $args{conflict_callback}->($conflict) if $args{'conflict_callback'};
+        $conflict->resolvers( [ sub { $args{resolver}->(@_) } ] ) if $args{resolver};
+        if ( $args{resolver_class} ) {
+            $args{resolver_class}->require || die $@;
+            $conflict->resolvers( [ sub { warn "CAlling ".$args{resolver_class};
+                $args{resolver_class}->new->run(@_); } ] )
+
+        }
+        my $resolutions = $conflict->generate_resolution( $args{resdb} );
+
+        #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
+        $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_resolutions( $conflict->resolution_changeset,
+            $self->ressource ? $self->ressource->prophet_handle : $self->prophet_handle );
+		$args{'reporting_callback'}->( changeset => $changeset, conflict => $conflict   ) 		if ($args{'reporting_callback'}) ;
+
+
+    } else {
+        $self->prophet_handle->integrate_changeset($changeset);
+		$args{'reporting_callback'}->( changeset => $changeset   ) 		if ($args{'reporting_callback'}) ;
+
+
+    }
+
+
+
+}
+
+
+=head2 accepts_changesets
+
+Returns true if this source is one we know how to write to (and have permission to write to)
+
+Returns false otherwise
+
+=cut
+
+sub accepts_changesets {
+    my $self = shift;
+
+    return 1 if $self->prophet_handle;
+    return undef;
+}
+
+=head2 has_seen_changeset Prophet::ChangeSet
+
+Returns true if we've previously integrated this changeset, even if we originally recieved it from a different peer
+
+=cut
+
+sub has_seen_changeset {
+    my $self = shift;
+    my ($changeset) = validate_pos( @_, { isa => "Prophet::ChangeSet" } );
+
+    # If the changeset originated locally, we never want it
+    return 1 if $changeset->original_source_uuid eq $self->uuid;
+
+    # Otherwise, if the we have a merge ticket from the source, we don't want the changeset
+    my $last = $self->last_changeset_from_source( $changeset->original_source_uuid );
+
+    # if the source's sequence # is >= the changeset's sequence #, we can safely skip it
+    return 1 if ( $last >= $changeset->original_sequence_no );
+    return undef;
+}
+
+=head2 changeset_will_conflict Prophet::ChangeSet
+
+Returns true if any change that's part of this changeset won't apply cleanly to the head of the current replica
+
+=cut
+
+sub changeset_will_conflict {
+    my $self = shift;
+    my ($changeset) = validate_pos( @_, { isa => "Prophet::ChangeSet" } );
+
+    return 1 if ( $self->conflicts_from_changeset($changeset) );
+
+    return undef;
+
+}
+
+=head2 conflicts_from_changeset Prophet::ChangeSet
+
+Returns a L<Prophet::Conflict/> object if the supplied L<Prophet::ChangeSet/>
+will generate conflicts if applied to the current replica.
+
+Returns undef if the current changeset wouldn't generate a conflict.
+
+=cut
+
+sub conflicts_from_changeset {
+    my $self = shift;
+    my ($changeset) = validate_pos( @_, { isa => "Prophet::ChangeSet" } );
+
+    my $conflict = Prophet::Conflict->new( { changeset => $changeset, prophet_handle => $self->prophet_handle } );
+
+    $conflict->analyze_changeset();
+
+    return undef unless @{ $conflict->conflicting_changes };
+
+    return $conflict;
+
+}
+
+sub remove_redundant_data {
+    my ( $self, $changeset ) = @_;
+
+    # XXX: encapsulation
+    $changeset->{changes} = [
+        grep { $self->is_resdb || $_->node_type ne '_prophet_resolution' } grep {
+            !( $_->node_type eq $Prophet::Handle::MERGETICKET_METATYPE && $_->node_uuid eq $self->prophet_handle->uuid )
+            } $changeset->changes
+    ];
+}
+
+
+
+
+
 sub fetch_resolutions {
     my $self = shift;
     my %args = validate(

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	Wed Apr  2 21:48:02 2008
@@ -144,157 +144,6 @@
     return $changeset;
 }
 
-=head2 accepts_changesets
-
-Returns true if this source is one we know how to write to (and have permission to write to)
-
-Returns false otherwise
-
-=cut
-
-sub accepts_changesets {
-    my $self = shift;
-
-    return 1 if $self->prophet_handle;
-    return undef;
-}
-
-=head2 has_seen_changeset Prophet::ChangeSet
-
-Returns true if we've previously integrated this changeset, even if we originally recieved it from a different peer
-
-=cut
-
-sub has_seen_changeset {
-    my $self = shift;
-    my ($changeset) = validate_pos( @_, { isa => "Prophet::ChangeSet" } );
-
-    # If the changeset originated locally, we never want it
-    return 1 if $changeset->original_source_uuid eq $self->uuid;
-
-    # Otherwise, if the we have a merge ticket from the source, we don't want the changeset
-    my $last = $self->last_changeset_from_source( $changeset->original_source_uuid );
-
-    # if the source's sequence # is >= the changeset's sequence #, we can safely skip it
-    return 1 if ( $last >= $changeset->original_sequence_no );
-    return undef;
-}
-
-=head2 changeset_will_conflict Prophet::ChangeSet
-
-Returns true if any change that's part of this changeset won't apply cleanly to the head of the current replica
-
-=cut
-
-sub changeset_will_conflict {
-    my $self = shift;
-    my ($changeset) = validate_pos( @_, { isa => "Prophet::ChangeSet" } );
-
-    return 1 if ( $self->conflicts_from_changeset($changeset) );
-
-    return undef;
-
-}
-
-=head2 conflicts_from_changeset Prophet::ChangeSet
-
-Returns a L<Prophet::Conflict/> object if the supplied L<Prophet::ChangeSet/>
-will generate conflicts if applied to the current replica.
-
-Returns undef if the current changeset wouldn't generate a conflict.
-
-=cut
-
-sub conflicts_from_changeset {
-    my $self = shift;
-    my ($changeset) = validate_pos( @_, { isa => "Prophet::ChangeSet" } );
-
-    my $conflict = Prophet::Conflict->new( { changeset => $changeset, prophet_handle => $self->prophet_handle } );
-
-    $conflict->analyze_changeset();
-
-    return undef unless @{ $conflict->conflicting_changes };
-
-    return $conflict;
-
-}
-
-=head2 integrate_changeset L<Prophet::ChangeSet>
-
-If there are conflicts, generate a nullification change, figure out a conflict resolution and apply the nullification, original change and resolution all at once (as three separate changes).
-
-If there are no conflicts, just apply the change.
-
-=cut
-
-sub integrate_changeset {
-    my $self = shift;
-    my %args = validate(
-        @_,
-        {   changeset         => { isa      => 'Prophet::ChangeSet' },
-            resolver          => { optional => 1 },
-            resolver_class    => { optional => 1 },
-            resdb             => { optional => 1 },
-            conflict_callback => { optional => 1 }
-        }
-    );
-
-    my $changeset = $args{'changeset'};
-
-    # when we start to integrate a changeset, we need to do a bit of housekeeping
-    # We never want to merge in:
-    # merge tickets that describe merges from the local node
-
-    # When we integrate changes, sometimes we will get handed changes we already know about.
-    #   - changes from local
-    #   - changes from some other party we've merged from
-    #   - merge tickets for the same
-    # we'll want to skip or remove those changesets
-
-    return if $changeset->original_source_uuid eq $self->prophet_handle->uuid;
-
-    $self->remove_redundant_data($changeset);    #Things we have already seen
-
-    return if ( $changeset->is_empty or $changeset->is_nullification );
-
-    if ( my $conflict = $self->conflicts_from_changeset($changeset) ) {
-        $args{conflict_callback}->($conflict) if $args{'conflict_callback'};
-        $conflict->resolvers( [ sub { $args{resolver}->(@_) } ] ) if $args{resolver};
-        if ( $args{resolver_class} ) {
-            $args{resolver_class}->require || die $@;
-            $conflict->resolvers( [ sub { $args{resolver_class}->run(@_); } ] )
-
-        }
-        my $resolutions = $conflict->generate_resolution( $args{resdb} );
-
-        #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
-        $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_resolutions( $conflict->resolution_changeset,
-            $self->ressource ? $self->ressource->prophet_handle : $self->prophet_handle );
-    } else {
-        $self->prophet_handle->integrate_changeset($changeset);
-
-    }
-}
-
-sub remove_redundant_data {
-    my ( $self, $changeset ) = @_;
-
-    # XXX: encapsulation
-    $changeset->{changes} = [
-        grep { $self->is_resdb || $_->node_type ne '_prophet_resolution' } grep {
-            !( $_->node_type eq $Prophet::Handle::MERGETICKET_METATYPE && $_->node_uuid eq $self->prophet_handle->uuid )
-            } $changeset->changes
-    ];
-}
 
 =head2 last_changeset_from_source $SOURCE_UUID
 
@@ -314,6 +163,8 @@
     # XXX TODO this is hacky as hell and violates abstraction barriers in the name of doing things over the RA
     # because we want to be able to sync to a remote replica someday.
 
+    
+
     return ( $props->{'last-changeset'} || 0 );
 
 }

Modified: SVN-PropDB/lib/Prophet/Test/Participant.pm
==============================================================================
--- SVN-PropDB/lib/Prophet/Test/Participant.pm	(original)
+++ SVN-PropDB/lib/Prophet/Test/Participant.pm	Wed Apr  2 21:48:02 2008
@@ -192,7 +192,8 @@
     my $ret;
     my $pool = SVN::Pool->new_default;
     if ( my $sub = $cli->can( 'do_' . $cmd ) ) {
-        in_gladiator { $ret = $sub->($cli) };
+        # in_gladiator
+         { $ret = $sub->($cli) }
     } else {
         die "I don't know how to do the $cmd";
     }



More information about the Bps-public-commit mailing list