App-SD
view release on metacpan or search on metacpan
lib/App/SD/Replica/trac/PullEncoder.pm view on Meta::CPAN
after transaction $num.
=cut
sub find_matching_transactions {
my $self = shift;
my %args = validate( @_, { ticket => 1, starting_transaction => 1 } );
my @raw_txns = @{$args{ticket}->history->entries};
my @txns;
# XXX TODO make this one loop.
for my $txn ( sort { $a->date cmp $b->date} @raw_txns) {
my $txn_date = $txn->date->epoch;
# Skip things we know we've already pulled
next if $txn_date < ( $args{'starting_transaction'} ||0 );
# Skip things we've pushed
next if ($self->sync_source->foreign_transaction_originated_locally($txn_date, $args{'ticket'}->id) );
# ok. it didn't originate locally. we might want to integrate it
push @txns, { timestamp => $txn->date,
serial => $txn->date->epoch,
object => $txn};
}
$self->sync_source->log_debug('Done looking at pulled txns');
return \@txns;
}
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 transcode_create_txn {
my $self = shift;
my $txn = shift;
my $create_data = shift;
my $final_data = shift;
my $ticket = $txn->ticket;
# this sequence_no only works because trac tickets only allow one update
# per ticket per second.
# we decrement by 1 on the off chance that someone created and
# updated the ticket in the first second
my $changeset = Prophet::ChangeSet->new(
{ original_source_uuid => $self->sync_source->uuid_for_remote_id( $ticket->id ),
original_sequence_no => ( $ticket->created->epoch-1),
creator => $self->resolve_user_id_to( email_address => $create_data->{reporter} ),
created => $ticket->created->ymd ." ".$ticket->created->hms
}
);
my $change = Prophet::Change->new(
{ record_type => 'ticket',
record_uuid => $self->sync_source->uuid_for_remote_id( $ticket->id ),
change_type => 'add_file'
}
);
for my $prop ( keys %$create_data ) {
next unless defined $create_data->{$prop};
next if $prop =~ /^(?:patch)$/;
$change->add_prop_change( name => $prop, old => '', new => $create_data->{$prop} );
}
$changeset->add_change( { change => $change } );
if ( my $att = $txn->attachment ) {
$self->_recode_attachment_create(
ticket => $ticket,
txn => $txn,
changeset => $changeset,
attachment => $att,
);
}
return $changeset;
}
# we might get return:
# 0 changesets if it was a null txn
# 1 changeset if it was a normal txn
# 2 changesets if we needed to to some magic fixups.
sub transcode_one_txn {
my ( $self, $txn_wrapper, $ticket, $ticket_final ) = (@_);
my $txn = $txn_wrapper->{object};
if ($txn->is_create) {
return $self->transcode_create_txn($txn,$ticket,$ticket_final);
}
my $ticket_uuid = $self->sync_source->uuid_for_remote_id( $ticket->{ $self->sync_source->uuid . '-id' } );
my $changeset = Prophet::ChangeSet->new(
{ original_source_uuid => $ticket_uuid,
original_sequence_no => $txn->date->epoch, # see comment on ticket
# create changeset
creator => $self->resolve_user_id_to( email_address => $txn->author ),
created => $txn->date->ymd . " " . $txn->date->hms
}
);
my $change = Prophet::Change->new(
{ record_type => 'ticket',
( run in 1.185 second using v1.01-cache-2.11-cpan-39bf76dae61 )