[Bps-public-commit] r16115 - in Prophet/branches/dispatcher: . lib/Prophet/CLI

sartak at bestpractical.com sartak at bestpractical.com
Sat Sep 27 15:40:33 EDT 2008


Author: sartak
Date: Sat Sep 27 15:40:32 2008
New Revision: 16115

Removed:
   Prophet/branches/dispatcher/lib/Prophet/CLI/Command/Merge.pm
Modified:
   Prophet/branches/dispatcher/   (props changed)
   Prophet/branches/dispatcher/lib/Prophet/CLI/Dispatcher.pm

Log:
 r72978 at onn:  sartak | 2008-09-27 15:40:24 -0400
 Most of merge


Modified: Prophet/branches/dispatcher/lib/Prophet/CLI/Dispatcher.pm
==============================================================================
--- Prophet/branches/dispatcher/lib/Prophet/CLI/Dispatcher.pm	(original)
+++ Prophet/branches/dispatcher/lib/Prophet/CLI/Dispatcher.pm	Sat Sep 27 15:40:32 2008
@@ -163,6 +163,42 @@
 
 };
 
+on merge => sub {
+    my $self = shift;
+
+    my (@alt_from, @alt_to);
+
+    if ($self->context->has_arg('db_uuid')) {
+        push @alt_from, join '/',
+                            $self->context->arg('from'),
+                            $self->context->arg('db_uuid');
+        push @alt_to, join '/',
+                          $self->context->arg('to'),
+                          $self->context->arg('db_uuid');
+    }
+
+    my $source = Prophet::Replica->new(
+        url        => $self->context->arg('from'),
+        app_handle => $self->context->app_handle,
+        _alt_urls  => \@alt_from,
+    );
+
+    my $target = Prophet::Replica->new(
+        url        => $self->context->arg('to'),
+        app_handle => $self->context->app_handle,
+        _alt_urls  => \@alt_to,
+    );
+
+    $target->import_resolutions_from_remote_replica(
+        from  => $source,
+        force => $self->context->has_arg('force'),
+    );
+
+    my $changesets = $self->_do_merge( $source, $target );
+
+    $self->print_merge_report($changesets);
+};
+
 
 # catch-all. () makes sure we don't hit the annoying historical feature of
 # the empty regex meaning the last-used regex
@@ -221,6 +257,117 @@
         . $change->record_uuid . ")\n";
 }
 
+sub print_merge_report {
+    my $self = shift;
+    my $changesets = shift;
+    if ($changesets == 0) {
+        print "No new changesets.\n";
+    }
+    elsif ($changesets == 1) {
+        print "Merged one changeset.\n";
+    }
+    else {
+        print "Merged $changesets changesets.\n";
+    }
+}
+
+=head2 _do_merge $source $target
+
+Merges changesets from the source replica into the target replica.
+
+Fails fatally if the source and target are the same, or the target is
+not writable.
+
+Conflicts are resolved by either the resolver specified in the
+C<PROPHET_RESOLVER> environmental variable, the C<prefer> argument
+(can be set to C<to> or C<from>, in which case Prophet will
+always prefer changesets from one replica or the other), or by
+using a default resolver.
+
+Returns the number of changesets merged.
+
+=cut
+
+sub _do_merge {
+    my ( $self, $source, $target ) = @_;
+
+    my %import_args = (
+        from  => $source,
+        resdb => $self->cli->resdb_handle,
+        force => $self->context->has_arg('force'),
+    );
+
+    local $| = 1;
+
+    $self->validate_merge_replicas($source => $target);
+
+    $import_args{resolver_class} = $self->merge_resolver();
+
+    my $changesets = 0;
+
+    my $source_latest = $source->latest_sequence_no() || 0;
+    my $source_last_seen = $target->last_changeset_from_source($source->uuid) || 0;
+
+    if( $self->context->has_arg('verbose') ) {
+        print "Integrating changes from ".$source_last_seen . " to ". $source_latest."\n";
+    }
+
+
+    if( $self->context->has_arg('verbose') ) {
+        $import_args{reporting_callback} = sub {
+            my %args = @_;
+            print $args{changeset}->as_string;
+            $changesets++;
+        };
+    } else {
+        require Time::Progress;
+        my $progress = Time::Progress->new();
+        $progress->attr( max => ($source_latest - $source_last_seen));
+
+        $import_args{reporting_callback} = sub {
+            my %args = @_;
+            $changesets++;
+            print $progress->report( "%30b %p %E // ". ($args{changeset}->created || 'Undated'). " " .(sprintf("%-12s",$args{changeset}->creator||'')) ."\r" , $changesets);
+
+        };
+    }
+
+    $target->import_changesets(%import_args);
+    return $changesets;
+}
+
+
+sub validate_merge_replicas {
+    my $self = shift;
+    my $source = shift;
+    my $target = shift;
+
+    if ( $target->uuid eq $source->uuid ) {
+        $self->fatal_error(
+                  "You appear to be trying to merge two identical replicas. "
+                . "Either you're trying to merge a replica to itself or "
+                . "someone did a bad job cloning your database." );
+    }
+
+    if ( !$target->can_write_changesets ) {
+        $self->fatal_error(
+            $target->url
+            . " does not accept changesets. Perhaps it's unwritable."
+        );
+    }
+}
+
+sub merge_resolver {
+    my $self = shift;
+
+    my $prefer = $self->context->arg('prefer') || 'none';
+
+    my $resolver = $ENV{'PROPHET_RESOLVER'} ? 'Prophet::Resolver::' . $ENV{'PROPHET_RESOLVER'}
+        : $prefer eq 'to'   ? 'Prophet::Resolver::AlwaysTarget'
+        : $prefer eq 'from' ? 'Prophet::Resolver::AlwaysSource'
+        :                     ();
+    return $resolver;
+}
 
 no Moose;
 __PACKAGE__->meta->make_immutable;



More information about the Bps-public-commit mailing list