[Bps-public-commit] SD - A distributed issue tracker branch, master, updated. 5defd8e1dbed0a95900fd15d9b7d65176b40b1e4

jesse jesse at bestpractical.com
Wed Feb 4 20:16:06 EST 2009


The branch, master has been updated
       via  5defd8e1dbed0a95900fd15d9b7d65176b40b1e4 (commit)
      from  b8b80b38f040e0de79858a89c6610ac2d7872697 (commit)

Summary of changes:
 lib/App/SD/Replica/trac/PullEncoder.pm |  184 ++++++++++++++++++++-----------
 1 files changed, 119 insertions(+), 65 deletions(-)

- Log -----------------------------------------------------------------
commit 5defd8e1dbed0a95900fd15d9b7d65176b40b1e4
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Wed Feb 4 20:02:58 2009 -0500

    A first "basically working" pull encoder for the SD Trac replica type.

diff --git a/lib/App/SD/Replica/trac/PullEncoder.pm b/lib/App/SD/Replica/trac/PullEncoder.pm
index 853fb1b..a6a41e1 100644
--- a/lib/App/SD/Replica/trac/PullEncoder.pm
+++ b/lib/App/SD/Replica/trac/PullEncoder.pm
@@ -38,64 +38,67 @@ sub run {
         print $progress->report( "%30b %p Est: %E\r", $counter );
         $self->sync_source->log( "Fetching ticket @{[$ticket->id]} - $counter of " . scalar @tickets );
 
-        warn "Loading ticket " . $ticket->id . " " . $ticket->summary;
     
         $tickets->{ $ticket->id } = $ticket;
     }
 
     my @changesets;
 
-    my $ticket_state = { };
   
-    $self->_translate_final_ticket_state($ticket_state); 
 
     foreach my $ticket ( values %$tickets ) {
+        my $ticket_data = $self->_translate_final_ticket_state($ticket); 
+        #my $ticket_initial_data = $self->build_initial_ticket_state($ticket_data, $ticket);
+        my $ticket_initial_data = {%$ticket_data};
         my $txns = $self->skip_previously_seen_transactions( ticket => $ticket, transactions => $ticket->history->entries);
+        # Walk transactions newest to oldest.
         for my $txn ( sort { $b->date <=> $a->date } @$txns) { 
-            $self->sync_source->log("Transcoding transaction  {[$txn->date}]} ");
-            my $changeset = $self->transcode_one_txn( $txn, $ticket_state );
-            $changeset->created( $txn->date );
+            $self->sync_source->log($ticket->id." - Transcoding transaction  @{[$txn->date]} ");
+            my $changeset = $self->transcode_one_txn( $txn, $ticket_initial_data );
+            $changeset->created( $txn->date->ymd." ". $txn->date->hms );
             next unless $changeset->has_changes;
+            # the changeset is older than the one that came before it, so it goes first
             unshift @changesets, $changeset;
+            $counter++;
         }
+        # create is oldest of all
+        unshift @changesets, $self->build_create_changeset($ticket_initial_data, $ticket);
     }
 
-    my $cs_counter = 0;
-    for (@changesets) {
-        $self->sync_source->log( "Applying changeset " . ++$cs_counter . " of " . scalar @changesets );
-        $args{callback}->($_);
+    my $cs_counter = 1;
+    for  my $changeset (@changesets) {
+        $changeset->original_sequence_no($cs_counter++);
+        $self->sync_source->log( "Applying changeset " . $changeset->original_sequence_no . " of " . scalar @changesets );
+        $args{callback}->($changeset);
     }
 }
 
 sub _translate_final_ticket_state {
     my $self   = shift;
-    my $ticket = shift;
-
-    # undefine empty fields, we'll delete after cleaning
-    $ticket->{$_} = undef for grep defined $ticket->{$_} && $ticket->{$_} eq '', keys %$ticket;
-
-    $ticket->{'id'} =~ s/^ticket\///g;
-    $ticket->{ $self->sync_source->uuid . '-' . lc($_) } = delete $ticket->{$_} for qw(Queue id);
-    delete $ticket->{'Owner'} if lc($ticket->{'Owner'}) eq 'nobody';
-    $ticket->{'Owner'} = $self->resolve_user_id_to( email_address => $ticket->{'Owner'} ) if $ticket->{'Owner'};
-
-    # normalize names of watchers to variant with suffix 's'
-    foreach my $field (qw(Requestor Cc AdminCc)) {
-        if ( defined $ticket->{$field} && defined $ticket->{$field .'s'} ) {
-            die "It's impossible! Ticket has '$field' and '${field}s'";
-        } elsif ( defined $ticket->{$field} ) {
-            $ticket->{$field .'s'} = delete $ticket->{$field};
-        }
-    }
-
-    $ticket->{$_} = $self->unix_time_to_iso( $ticket->{$_} ) for grep defined $ticket->{$_}, qw(Created Resolved Told LastUpdated Due Starts Started);
-    $ticket->{$_} =~ s/ minutes$// for grep defined $ticket->{$_}, qw(TimeWorked TimeLeft TimeEstimated);
-    $ticket->{'Status'} =~ $self->translate_status($ticket->{'Status'});
+    my $ticket_object = shift;
+
+    my $ticket_data = {
+
+        $self->sync_source->uuid . '-id' => $ticket_object->id,
+
+        owner       => ($ticket_object->owner ||''),
+        created     => ($ticket_object->created->ymd . " " . $ticket_object->created->hms),
+        reporter    => ($ticket_object->reporter ||''),
+        status      => $self->translate_status( $ticket_object->status ),
+        summary     => ($ticket_object->summary||''),
+        description => ($ticket_object->description ||''),
+        tags        => ( $ticket_object->keywords || '' ),
+        component   => ($ticket_object->component ||''),
+        milestone   => ($ticket_object->milestone ||''),
+        priority    => ($ticket_object->priority || ''),
+        severity    => ($ticket_object->severity ||''),
+        cc          => ($ticket_object->cc || ''),
+    };
 
     # delete undefined and empty fields
-    delete $ticket->{$_} for grep !defined $ticket->{$_} || $ticket->{$_} eq '', keys %$ticket;
+    delete $ticket_data->{$_} for grep !defined $ticket_data->{$_} || $ticket_data->{$_} eq '', keys %$ticket_data;
 
-    return $ticket;
+    return $ticket_data;
 }
 
 =head2 find_matching_tickets QUERY
@@ -107,7 +110,7 @@ Returns a Trac::TicketSearch collection for all tickets found matching your QUER
 sub find_matching_tickets {
     my $self   = shift;
     my %query  = (@_);
-    my $search = Net::Trac::TicketSearch->new( connection => $self->sync_source->trac, limit => 2 );
+    my $search = Net::Trac::TicketSearch->new( connection => $self->sync_source->trac, limit => 50 );
     $search->query(%query);
     return $search->results;
 }
@@ -128,53 +131,97 @@ sub skip_previously_seen_transactions {
         #next if $txn < $args{'starting_transaction'}; 
         
         # Skip things we've pushed
-        next if $self->sync_source->foreign_transaction_originated_locally($txn, $args{'ticket'});
+        #next if $self->sync_source->foreign_transaction_originated_locally($txn, $args{'ticket'});
         push @txns, $txn;
     }
     return \@txns;
 }
 
-sub transcode_one_txn {
-    my ( $self, $txn, $ticket ) = (@_);
 
-    my $sub = $self->can( '_recode_txn_' . $txn->{'Type'} );
-    unless ($sub) {
-        die "Transaction type $txn->{Type} (for transaction $txn->{id}) not implemented yet";
+sub build_initial_ticket_state {
+    my $self          = shift;
+    my $final_state   = shift;
+    my $ticket_object = shift;
+
+    my %initial_state = %{$final_state};
+
+    for my $txn ( reverse @{ $ticket_object->history->entries } ) {
+        for my $pc ( values %{ $txn->prop_changes } ) {
+            unless ( $initial_state{ $pc->property } eq $pc->new_value ) {
+                warn "I was expecting " . $pc->property . " to be " . $pc->new_value . " but it was actually " . $initial_state{ $pc->property };
+            }
+            $initial_state{ $pc->property } = $pc->old_value;
+
+        }
     }
+    return \%initial_state;
+}
+
 
+sub build_create_changeset {
+    my $self = shift;
+    my $create_data = shift;
+    my $ticket = shift;
+    warn "My ticket id is ".$ticket->id;
     my $changeset = Prophet::ChangeSet->new(
-        {   original_source_uuid => $self->sync_source->uuid,
-            original_sequence_no => $txn->{'id'},
-            creator              => $self->resolve_user_id_to( email_address => $txn->{'Creator'} ),
+        {   original_source_uuid =>  $self->sync_source->uuid_for_remote_id( $ticket->id),
+            #original_sequence_no => 1, # XXX TODO THIS IS JNOT A VALID SEQUENCE NUMBER
+            creator              => $self->resolve_user_id_to( email_address => $ticket->reporter),
+        }
+    );
+
+
+    my $change = Prophet::Change->new(
+        {   record_type => 'ticket',
+            record_uuid => $self->sync_source->uuid_for_remote_id( $ticket->id), 
+            change_type => 'add_file'
         }
     );
 
-    if (   $txn->{'Ticket'} ne $ticket->{ $self->sync_source->uuid . '-id' }
-        && $txn->{'Type'} !~ /^(?:Comment|Correspond)$/ )
-    {
-        warn "Skipping a data change from a merged ticket"
-            . $txn->{'Ticket'} . ' vs '
-            . $ticket->{ $self->sync_source->uuid . '-id' };
-        next;
+    for my $prop (keys %$create_data) {
+        next unless defined $create_data->{$prop};
+        $change->add_prop_change(name => $prop, old => '', new => $create_data->{$prop});
     }
 
-    delete $txn->{'OldValue'} if ( $txn->{'OldValue'} eq '' );
-    delete $txn->{'NewValue'} if ( $txn->{'NewValue'} eq '' );
+    $changeset->add_change({change => $change});
+    return $changeset;
+}
+
 
-    $sub->( $self, ticket => $ticket, txn => $txn, changeset => $changeset );
-    $self->translate_prop_names($changeset);
 
-    if ( my $attachments = delete $txn->{'_attachments'} ) {
-        for my $attach (@$attachments) {
-            $self->_recode_attachment_create(
-                ticket     => $ticket,
-                txn        => $txn,
-                changeset  => $changeset,
-                attachment => $attach
-            );
+sub transcode_one_txn {
+    my ( $self, $txn, $ticket, $txn_number ) = (@_);
+    my $changeset = Prophet::ChangeSet->new(
+        {   original_source_uuid => $self->sync_source->uuid_for_remote_id( $ticket->{$self->sync_source->uuid . '-id' } ),
+            #        original_sequence_no => $txn_number, #XXX TODO THIS IS NOT A VALID SEQUENCE NUMBER
+            creator              => $self->resolve_user_id_to( email_address => $txn->author),
+        }
+    );
+
+    my $change = Prophet::Change->new(
+        {   record_type => 'ticket',
+            record_uuid => $self->sync_source->uuid_for_remote_id( $ticket->{$self->sync_source->uuid . '-id' } ),
+            change_type => 'update_file'
         }
+    );
+
+    foreach my $prop_change ( values %{$txn->prop_changes||{}}) {
+        my $new = $prop_change->new_value;
+        my $old = $prop_change->old_value;
+        my $property = $prop_change->property; 
+
+        $old = undef if ($old eq '');
+        $new = undef if ($new eq '');
+
+        # walk back $ticket's state
+        if ((!defined $new && !defined $ticket->{$property}) || ( defined $new && defined $ticket->{$property} && $ticket->{$property} eq $new)) { $ticket->{$property} = $old }; 
+
+        $change->add_prop_change(name => $property, old => $old, new => $new);
+
     }
 
+    $changeset->add_change({change =>$change});
+
     return $changeset;
 }
 
@@ -244,8 +291,6 @@ sub translate_status {
     my $status = shift;
 
     $status =~ s/^resolved$/closed/;
-    
-
     return $status;
 }
 
@@ -279,6 +324,15 @@ sub translate_prop_names {
     return $changeset;
 }
 
+sub resolve_user_id_to {
+    my $self = shift;
+    my $to = shift;
+    my $id = shift;
+    return $id.'@trac-instance.local';
+
+}
+
+
 __PACKAGE__->meta->make_immutable;
 no Moose;
 1;

-----------------------------------------------------------------------



More information about the Bps-public-commit mailing list