[Bps-public-commit] r12167 - in sd/trunk: . bin lib/App/SD/Model lib/App/SD/Replica/RT t
jesse at bestpractical.com
jesse at bestpractical.com
Thu May 8 17:47:49 EDT 2008
Author: jesse
Date: Thu May 8 17:47:48 2008
New Revision: 12167
Modified:
sd/trunk/ (props changed)
sd/trunk/bin/sd
sd/trunk/lib/App/SD/Model/Attachment.pm
sd/trunk/lib/App/SD/Replica/RT.pm
sd/trunk/lib/App/SD/Replica/RT/PullEncoder.pm
sd/trunk/t/attachment-content.t
sd/trunk/t/sd-attachments.t
sd/trunk/t/sd-rt.t
Log:
r30665 at 106 (orig r12158): jesse | 2008-05-08 17:37:08 -0400
- Merged from local
r30662 at 106: jesse | 2008-05-08 17:36:57 -0400
* Added support for round-tripping attachments to rt.
Modified: sd/trunk/bin/sd
==============================================================================
--- sd/trunk/bin/sd (original)
+++ sd/trunk/bin/sd Thu May 8 17:47:48 2008
@@ -27,6 +27,8 @@
}
# override args to feed in that ticket's uuid as an argument to the comment
+
+
package App::SD::CLI::Command::Attachment;
use constant record_class => 'App::SD::Model::Attachment';
@@ -38,8 +40,9 @@
my $self = shift;
if (my $file = file(delete $self->args->{'file'})) {
- $self->args->{'tricksy'} = 'abc';
- $self->args->{'content'} = $file->slurp();
+ my $content = $file->slurp();
+ chomp $content;
+ $self->args->{'content'} = $content;
$self->args->{'name'} = $file->basename;
}
@@ -128,24 +131,6 @@
}
-package App::SD::CLI::Command::Ticket::Attachments;
-use base qw/App::SD::CLI::Command::Ticket/;
-
-sub run {
- my $self = shift;
- my $record = $self->_get_record();
- $record->load( uuid => $self->cli->uuid );
- unless (@{$record->attachments}) {
- print "No attachments found\n";
- }
-
- for (@{$record->attachments}) {
- print "attachment id: ".$_->uuid."\n";
- print "name: ".$_->prop('name')."\n";
- print "content_type: ".$_->prop('content_type')."\n";
- }
-
-}
package App::SD::CLI::Command::Merge;
use base qw/App::SD::CLI::Command Prophet::CLI::Command::Merge/;
Modified: sd/trunk/lib/App/SD/Model/Attachment.pm
==============================================================================
--- sd/trunk/lib/App/SD/Model/Attachment.pm (original)
+++ sd/trunk/lib/App/SD/Model/Attachment.pm Thu May 8 17:47:48 2008
@@ -8,7 +8,7 @@
use constant collection_class => 'App::SD::Collection::Attachment';
use constant record_type => 'attachment';
-use constant summary_format => '%u %s';
+use constant summary_format => '%u %s %s';
use constant summary_props => qw(name content_type);
__PACKAGE__->register_reference( ticket => 'App::SD::Model::Ticket');
Modified: sd/trunk/lib/App/SD/Replica/RT.pm
==============================================================================
--- sd/trunk/lib/App/SD/Replica/RT.pm (original)
+++ sd/trunk/lib/App/SD/Replica/RT.pm Thu May 8 17:47:48 2008
@@ -5,15 +5,15 @@
use base qw/Prophet::ForeignReplica/;
use Params::Validate qw(:all);
use UNIVERSAL::require;
+ use File::Temp ();
+ use Path::Class;
use Prophet::ChangeSet;
-
use Memoize;
use constant scheme => 'rt';
__PACKAGE__->mk_accessors(qw/rt rt_url rt_queue rt_query/);
-
=head1 NOTES ON PUSH
If the remote storage (RT) can not represent a whole changeset along with the prophet changeset uuid, then we need to
@@ -71,14 +71,12 @@
sub setup {
my $self = shift;
-
+
# Require rather than use to defer load
- require RT::Client::REST ;
- require RT::Client::REST::User ;
+ require RT::Client::REST;
+ require RT::Client::REST::User;
require RT::Client::REST::Ticket;
-
-
my ( $server, $type, $query ) = $self->{url} =~ m/^(.*?)\|(.*?)\|(.*)$/
or die "Can't parse rt server spec";
my $uri = URI->new($server);
@@ -92,17 +90,19 @@
$self->rt_query( $query . " AND Queue = '$type'" );
$self->rt( RT::Client::REST->new( server => $server ) );
- ( $username, $password ) = $self->prompt_for_login( $uri, $username ) unless $password;
+ ( $username, $password ) = $self->prompt_for_login( $uri, $username )
+ unless $password;
$self->rt->login( username => $username, password => $password );
- $self->SUPER::setup(@_);
+ $self->SUPER::setup(@_);
}
sub record_pushed_transactions {
my $self = shift;
- my %args = validate( @_, { ticket => 1, changeset => { isa => 'Prophet::ChangeSet' } } );
+ my %args = validate( @_,
+ { ticket => 1, changeset => { isa => 'Prophet::ChangeSet' } } );
for my $txn (
reverse RT::Client::REST::Ticket->new(
@@ -111,8 +111,14 @@
)->transactions->get_iterator->()
)
{
- last if $txn->id <= $self->last_changeset_from_source( $args{changeset}->original_source_uuid );
- $self->record_pushed_transaction( transaction => $txn->id, changeset => $args{'changeset'} );
+ last
+ if $txn->id <= $self->last_changeset_from_source(
+ $args{changeset}->original_source_uuid
+ );
+ $self->record_pushed_transaction(
+ transaction => $txn->id,
+ changeset => $args{'changeset'}
+ );
}
}
@@ -136,7 +142,8 @@
sub _txn_storage {
my $self = shift;
- return $self->state_handle->metadata_storage( $TXN_METATYPE, 'prophet-txn-source' );
+ return $self->state_handle->metadata_storage( $TXN_METATYPE,
+ 'prophet-txn-source' );
}
sub prophet_has_seen_transaction {
@@ -147,11 +154,14 @@
sub record_pushed_transaction {
my $self = shift;
- my %args = validate( @_, { transaction => 1, changeset => { isa => 'Prophet::ChangeSet' } } );
+ my %args = validate( @_,
+ { transaction => 1, changeset => { isa => 'Prophet::ChangeSet' } } );
$self->_txn_storage->(
$self->uuid . '-txn-' . $args{transaction},
- join( ':', $args{changeset}->original_source_uuid, $args{changeset}->original_sequence_no )
+ join( ':',
+ $args{changeset}->original_source_uuid,
+ $args{changeset}->original_sequence_no )
);
}
@@ -163,34 +173,53 @@
sub remote_id_for_uuid {
my ( $self, $uuid_for_remote_id ) = @_;
+
# XXX: should not access CLI handle
- my $ticket = Prophet::Record->new( handle => Prophet::CLI->new->handle, type => 'ticket' );
+ my $ticket = Prophet::Record->new(
+ handle => Prophet::CLI->new->app_handle->handle,
+ type => 'ticket'
+ );
$ticket->load( uuid => $uuid_for_remote_id );
- return $ticket->prop( $self->uuid . '-id' );
+ my $id = $ticket->prop( $self->uuid . '-id' );
+ return $id;
+}
+
+sub _set_remote_id_for_uuid {
+ my $self = shift;
+ my %args = validate(
+ @_,
+ { uuid => 1,
+ remote_id => 1
+ }
+ );
+
+ # XXX: should not access CLI handle
+ my $ticket = Prophet::Record->new(
+ handle => Prophet::CLI->new->app_handle->handle,
+ type => 'ticket'
+ );
+ $ticket->load( uuid => $args{'uuid'});
+ $ticket->set_props( props => { $self->uuid.'-id' => $args{'remote_id'}});
+
}
+
sub uuid_for_remote_id {
my ( $self, $id ) = @_;
- return $self->_lookup_remote_id($id) || $self->uuid_for_url( $self->rt_url . "/ticket/$id" );
+ return $self->_lookup_uuid_for_remote_id($id) || $self->uuid_for_url( $self->rt_url . "/ticket/$id" );
}
-sub _lookup_remote_id {
+sub _lookup_uuid_for_remote_id {
my $self = shift;
my ($id) = validate_pos( @_, 1 );
return $self->_remote_id_storage( $self->uuid_for_url( $self->rt_url . "/ticket/$id" ) );
}
-sub _set_remote_id {
+sub _set_uuid_for_remote_id {
my $self = shift;
- my %args = validate(
- @_,
- { uuid => 1,
- remote_id => 1
- }
- );
- return $self->_remote_id_storage( $self->uuid_for_url( $self->rt_url . "/ticket/" . $args{'remote_id'} ),
- $args{uuid} );
+ my %args = validate( @_, { uuid => 1, remote_id => 1 });
+ return $self->_remote_id_storage( $self->uuid_for_url( $self->rt_url . "/ticket/" . $args{'remote_id'} ), $args{uuid});
}
sub record_pushed_ticket {
@@ -201,21 +230,37 @@
remote_id => 1
}
);
- $self->_set_remote_id(%args);
+ $self->_set_uuid_for_remote_id(%args);
+ $self->_set_remote_id_for_uuid(%args);
}
sub _integrate_change {
my $self = shift;
- my ( $change, $changeset ) = validate_pos( @_, { isa => 'Prophet::Change' }, { isa => 'Prophet::ChangeSet' } );
+ my ( $change, $changeset ) = validate_pos(
+ @_,
+ { isa => 'Prophet::Change' },
+ { isa => 'Prophet::ChangeSet' }
+ );
my $id;
eval {
- if ( $change->record_type eq 'ticket' and $change->change_type eq 'add_file' )
+ if ( $change->record_type eq 'ticket'
+ and $change->change_type eq 'add_file'
+ )
{
$id = $self->integrate_ticket_create( $change, $changeset );
- $self->record_pushed_ticket( uuid => $change->record_uuid, remote_id => $id );
-
- } elsif ( $change->record_type eq 'comment' ) {
-
+ $self->record_pushed_ticket(
+ uuid => $change->record_uuid,
+ remote_id => $id
+ );
+
+ } elsif ( $change->record_type eq 'attachment'
+ and $change->change_type eq 'add_file'
+
+ ) {
+ $id = $self->integrate_attachment( $change, $changeset );
+ } elsif ( $change->record_type eq 'comment'
+ and $change->change_type eq 'add_file'
+ ) {
$id = $self->integrate_comment( $change, $changeset );
} elsif ( $change->record_type eq 'ticket' ) {
$id = $self->integrate_ticket_update( $change, $changeset );
@@ -224,7 +269,10 @@
return undef;
}
- $self->record_pushed_transactions( ticket => $id, changeset => $changeset );
+ $self->record_pushed_transactions(
+ ticket => $id,
+ changeset => $changeset
+ );
};
warn $@ if $@;
@@ -233,7 +281,11 @@
sub integrate_ticket_update {
my $self = shift;
- my ( $change, $changeset ) = validate_pos( @_, { isa => 'Prophet::Change' }, { isa => 'Prophet::ChangeSet' } );
+ my ( $change, $changeset ) = validate_pos(
+ @_,
+ { isa => 'Prophet::Change' },
+ { isa => 'Prophet::ChangeSet' }
+ );
# Figure out the remote site's ticket ID for this change's record
my $remote_ticket_id = $self->remote_id_for_uuid( $change->record_uuid );
@@ -248,7 +300,11 @@
sub integrate_ticket_create {
my $self = shift;
- my ( $change, $changeset ) = validate_pos( @_, { isa => 'Prophet::Change' }, { isa => 'Prophet::ChangeSet' } );
+ my ( $change, $changeset ) = validate_pos(
+ @_,
+ { isa => 'Prophet::Change' },
+ { isa => 'Prophet::ChangeSet' }
+ );
# Build up a ticket object out of all the record's attributes
my $ticket = RT::Client::REST::Ticket->new(
@@ -262,26 +318,45 @@
sub integrate_comment {
my $self = shift;
- my ($change) = validate_pos( @_, { isa => 'Prophet::Change' } );
+ my ($change, $changeset) = validate_pos( @_, { isa => 'Prophet::Change' }, {isa => 'Prophet::ChangeSet'} );
# Figure out the remote site's ticket ID for this change's record
my %props = map { $_->name => $_->new_value } $change->prop_changes;
- my $id = $self->remote_id_for_uuid( $props{'ticket'} );
- my $ticket = RT::Client::REST::Ticket->new(
- rt => $self->rt,
- id => $id
- );
- if ( $props{'type'} eq 'comment' ) {
- $ticket->comment( message => $props{'content'} );
- } else {
- $ticket->correspond( message => $props{'content'} );
+ my $ticket_id = $self->remote_id_for_uuid( $props{'ticket'} );
+ my $ticket = RT::Client::REST::Ticket->new( rt => $self->rt, id => $ticket_id);
+ my %content = ( message => $props{'content'},
+ );
+
+ if ( ($props{'type'} ||'') eq 'comment' ) {
+ $ticket->comment( %content);
+ } else {
+ $ticket->correspond(%content);
}
- return $id;
+ return $ticket_id;
+}
+
+sub integrate_attachment {
+ my ($self, $change, $changeset ) = validate_pos( @_, { isa => 'App::SD::Replica::RT'}, { isa => 'Prophet::Change' }, { isa => 'Prophet::ChangeSet' });
+
+
+ my %props = map { $_->name => $_->new_value } $change->prop_changes;
+ my $ticket_id = $self->remote_id_for_uuid( $props{'ticket'});
+ my $ticket = RT::Client::REST::Ticket->new( rt => $self->rt, id => $ticket_id );
+
+ my $tempdir = File::Temp::tempdir( CLEANUP => 1 );
+ my $file = file( $tempdir => ( $props{'name'} || 'unnamed' ) );
+ my $fh = $file->openw;
+ print $fh $props{content};
+ close $fh;
+ my %content = ( message => '(See attachments)', attachments => ["$file"]);
+ $ticket->correspond(%content);
+ return $ticket_id;
}
+
sub _recode_props_for_integrate {
my $self = shift;
my ($change) = validate_pos( @_, { isa => 'Prophet::Change' } );
@@ -326,7 +401,8 @@
my $first_rev = ( $args{'after'} + 1 ) || 1;
require App::SD::Replica::RT::PullEncoder;
- my $recoder = App::SD::Replica::RT::PullEncoder->new( { sync_source => $self } );
+ my $recoder
+ = App::SD::Replica::RT::PullEncoder->new( { sync_source => $self } );
for my $id ( $self->find_matching_tickets ) {
# XXX: _recode_transactions should ignore txn-id <= $first_rev
@@ -334,7 +410,11 @@
for @{
$recoder->run(
ticket => $self->rt->show( type => 'ticket', id => $id ),
- transactions => $self->find_matching_transactions( ticket => $id, starting_transaction => $first_rev )
+ transactions => $self->find_matching_transactions(
+ ticket => $id,
+ starting_transaction => $first_rev
+ ),
+
)
};
}
@@ -350,9 +430,26 @@
my %args = validate( @_, { ticket => 1, starting_transaction => 1 } );
my @txns;
for my $txn ( sort $self->rt->get_transaction_ids( parent_id => $args{ticket} ) ) {
- next if $txn < $args{'starting_transaction'}; # Skip things we've pushed
+ next if $txn < $args{'starting_transaction'}; # Skip things we've pushed
next if $self->prophet_has_seen_transaction($txn);
- push @txns, $self->rt->get_transaction( parent_id => $args{ticket}, id => $txn, type => 'ticket' );
+ my $txn_hash = $self->rt->get_transaction(
+ parent_id => $args{ticket},
+ id => $txn,
+ type => 'ticket'
+ );
+ if ( my $attachments = delete $txn_hash->{'Attachments'} ) {
+ foreach my $attach ( split( /\n/, $attachments ) ) {
+ next unless ( $attach =~ /^(\d+):/ );
+ my $id = $1;
+ my $a = $self->rt->get_attachment( parent_id => $args{'ticket'}, id => $id);
+
+ push( @{ $txn_hash->{_attachments} }, $a )
+ if ( $a->{Filename} );
+
+ }
+
+ }
+ push @txns, $txn_hash;
}
return \@txns;
}
Modified: sd/trunk/lib/App/SD/Replica/RT/PullEncoder.pm
==============================================================================
--- sd/trunk/lib/App/SD/Replica/RT/PullEncoder.pm (original)
+++ sd/trunk/lib/App/SD/Replica/RT/PullEncoder.pm Thu May 8 17:47:48 2008
@@ -14,7 +14,7 @@
sub run {
my $self = shift;
- my %args = validate( @_, { ticket => 1, transactions => 1 } );
+ my %args = validate( @_, { ticket => 1, transactions => 1, attachments => 0 } );
$args{'ticket'}->{'id'} =~ s/^ticket\///g;
@@ -26,8 +26,16 @@
my @changesets;
for my $txn ( sort { $b->{'id'} <=> $a->{'id'} } @{ $args{'transactions'} } ) {
- delete $txn->{'OldValue'} if ( $txn->{'OldValue'} eq '');
- delete $txn->{'NewValue'} if ( $txn->{'NewValue'} eq '');
+ my $changeset = $self->txn_to_changeset($txn, $ticket, $create_state);
+ unshift @changesets, $changeset unless $changeset->is_empty;
+ }
+
+ return \@changesets;
+}
+
+
+sub txn_to_changeset {
+ my ($self, $txn, $ticket, $create_state) = (@_);
if ( my $sub = $self->can( '_recode_txn_' . $txn->{'Type'} ) ) {
my $changeset = Prophet::ChangeSet->new(
@@ -41,25 +49,44 @@
next;
}
- $sub->(
- $self,
- ticket => $ticket,
- create_state => $create_state,
- txn => $txn,
- changeset => $changeset
- );
+ delete $txn->{'OldValue'} if ( $txn->{'OldValue'} eq '');
+ delete $txn->{'NewValue'} if ( $txn->{'NewValue'} eq '');
+
+ $sub->( $self, ticket => $ticket, create_state => $create_state, txn => $txn, changeset => $changeset);
$self->translate_prop_names($changeset);
- unshift @changesets, $changeset unless $changeset->is_empty;
+ if (my $attachments = delete $txn->{'_attachments'}) {
+ foreach my $attach (@$attachments) {
+ $self->_recode_attachment_create( ticket => $ticket, txn => $txn, changeset =>$changeset, attachment => $attach);
+ }
+ }
+
+ return $changeset;
} else {
- warn "not handling txn type $txn->{Type} for $txn->{id} (Ticket $args{ticket}{id}) yet";
+ warn "not handling txn type $txn->{Type} for $txn->{id} yet";
die YAML::Dump($txn);
}
-
}
- return \@changesets;
+
+
+sub _recode_attachment_create {
+ my $self = shift;
+ my %args = validate( @_, { ticket => 1, txn => 1, changeset => 1, attachment => 1 } );
+ my $change = Prophet::Change->new(
+ { record_type => 'attachment',
+ record_uuid => $self->sync_source->uuid_for_url( $self->sync_source->rt_url . "/attachment/" . $args{'attachment'}->{'id'} ),
+ change_type => 'add_file'
+ }
+ );
+ $change->add_prop_change( name => 'content_type', old => undef, new => $args{'attachment'}->{'ContentType'});
+ $change->add_prop_change( name => 'creator', old => undef, new => $self->resolve_user_id_to( email => $args{'attachment'}->{'Creator'}));
+ $change->add_prop_change( name => 'content', old => undef, new => $args{'attachment'}->{'Content'});
+ $change->add_prop_change( name => 'name', old => undef, new => $args{'attachment'}->{'Filename'});
+ $change->add_prop_change( name => 'ticket', old => undef, new => $args{ticket}->{uuid},);
+ $args{'changeset'}->add_change( { change => $change } );
}
+
sub _recode_txn_CommentEmailRecord { return; }
sub _recode_txn_EmailRecord { return; }
@@ -189,32 +216,14 @@
my %args = validate( @_, { ticket => 1, txn => 1, create_state => 1, changeset => 1 } );
my $change = Prophet::Change->new(
{ record_type => 'comment',
- record_uuid =>
- $self->sync_source->uuid_for_url( $self->sync_source->rt_url . "/transaction/" . $args{'txn'}->{'id'} ),
+ record_uuid => $self->sync_source->uuid_for_url( $self->sync_source->rt_url . "/transaction/" . $args{'txn'}->{'id'} ),
change_type => 'add_file'
}
);
- $change->add_prop_change(
- name => 'type',
- old => undef,
- new => $args{'txn'}->{'Type'}
- );
-
- $change->add_prop_change(
- name => 'creator',
- old => undef,
- new => $args{'txn'}->{'Creator'}
- );
- $change->add_prop_change(
- name => 'content',
- old => undef,
- new => $args{'txn'}->{'Content'}
- );
- $change->add_prop_change(
- name => 'ticket',
- old => undef,
- new => $args{ticket}->{uuid},
- );
+ $change->add_prop_change( name => 'type', old => undef, new => $args{'txn'}->{'Type'});
+ $change->add_prop_change( name => 'creator', old => undef, new => $self->resolve_user_id_to( email => $args{'txn'}->{'Creator'}));
+ $change->add_prop_change( name => 'content', old => undef, new => $args{'txn'}->{'Content'});
+ $change->add_prop_change( name => 'ticket', old => undef, new => $args{ticket}->{uuid},);
$args{'changeset'}->add_change( { change => $change } );
}
Modified: sd/trunk/t/attachment-content.t
==============================================================================
--- sd/trunk/t/attachment-content.t (original)
+++ sd/trunk/t/attachment-content.t Thu May 8 17:47:48 2008
@@ -38,9 +38,8 @@
run_output_matches('sd', [qw/ticket attachment create --uuid/, $yatta_uuid, '--file', $file], [qr/Created attachment (.*?)(?{ $attachment_uuid = $1})$/], [], "Added a attachment");
ok($attachment_uuid);
-run_output_matches('sd', [qw/ticket attachments --uuid/, $yatta_uuid], [qr/^attachment id: $attachment_uuid/,
- 'name: paper_order.doc',
- 'content_type: text/plain' ], [], "Found the attachment, but doesn't show the content");
+run_output_matches('sd', [qw/ticket attachment list --uuid/, $yatta_uuid], [$attachment_uuid . " paper_order.doc text/plain"],
+ , [], "Found the attachment, but doesn't show the content");
run_output_matches('sd', [qw/attachment content --uuid/, $attachment_uuid], ['5 tonnes of hard white'],[], "We got the content");
@@ -53,7 +52,6 @@
run_output_matches('sd', [qw/ticket attachment create --uuid/, $yatta_uuid, '--file', $image_file], [qr/Created attachment (.*?)(?{ $image_attach = $1})$/], [], "Added a attachment");
my $image_data = file($image_file)->slurp;
-
my ($ret, $stdout, $stderr) = run_script('sd', [qw/attachment content --uuid/, $image_attach]);
ok($ret, "Ran the script ok");
is($stdout, $image_data, "We roundtripped some binary");
Modified: sd/trunk/t/sd-attachments.t
==============================================================================
--- sd/trunk/t/sd-attachments.t (original)
+++ sd/trunk/t/sd-attachments.t Thu May 8 17:47:48 2008
@@ -27,11 +27,7 @@
run_output_matches('sd', [qw/ticket attachment create --uuid/, $yatta_uuid, '--name', "paper_order.doc"], [qr/Created attachment (.*?)(?{ $attachment_uuid = $1})$/], [], "Added a attachment");
ok($attachment_uuid);
-run_output_matches('sd', [qw/ticket attachments --uuid/, $yatta_uuid], [qr/^attachment id: $attachment_uuid/,
-
- 'name: paper_order.doc',
-
- 'content_type: text/plain' ], [], "Found the attachment");
+run_output_matches('sd', [qw/ticket attachment list --uuid/, $yatta_uuid], [$attachment_uuid . ' paper_order.doc text/plain',], [], "Found the attachment");
run_output_matches(
'sd',
Modified: sd/trunk/t/sd-rt.t
==============================================================================
--- sd/trunk/t/sd-rt.t (original)
+++ sd/trunk/t/sd-rt.t Thu May 8 17:47:48 2008
@@ -6,12 +6,13 @@
use strict;
use Test::More;
+use Path::Class;
unless (eval 'use RT::Test; 1') {
diag $@;
plan skip_all => 'requires 3.7 or newer to run tests.';
}
-eval 'use Prophet::Test tests => 11';
+eval 'use Prophet::Test tests => 23';
no warnings 'once';
@@ -21,9 +22,13 @@
BEGIN {
require File::Temp;
$ENV{'PROPHET_REPO'} = $ENV{'SD_REPO'} = File::Temp::tempdir( CLEANUP => 0 ) . '/_svb';
- warn $ENV{'PROPHET_REPO'};
+ diag "export SD_REPO=".$ENV{'PROPHET_REPO'} ."\n";
}
+
+my $IMAGE_FILE = qw|t/data/bplogo.gif|;
+
+
my ( $url, $m ) = RT::Test->started_ok;
use RT::Client::REST;
@@ -32,7 +37,6 @@
$rt->login( username => 'root', password => 'password' );
$url =~ s|http://|http://root:password@|;
-warn $url;
my $sd_rt_url = "rt:$url|General|Status!='resolved'";
my $ticket = RT::Client::REST::Ticket->new(
@@ -45,7 +49,8 @@
my ( $ret, $out, $err );
( $ret, $out, $err ) = run_script( 'sd', [ 'pull', '--from', $sd_rt_url ] );
my ( $yatta_uuid, $flyman_uuid );
-run_output_matches( 'sd', [ 'ticket', 'list', '--regex', '.' ], [qr/(.*?)(?{ $flyman_uuid = $1 }) Fly Man new/] );
+run_output_matches( 'sd', [ 'ticket', 'list', '--regex', '.' ],
+ [qr/(.*?)(?{ $flyman_uuid = $1 }) Fly Man new/] );
RT::Client::REST::Ticket->new(
rt => $rt,
id => $ticket->id,
@@ -119,19 +124,11 @@
rt => $rt,
id => $tix[0])->retrieve;
-warn $tick->subject;
-warn $tick->status;
-my ($val,$msg) = $tick->comment( message => 'this is a comment', attachments => [qw|t/data/bplogo.gif|]);
-
- my $attachments = RT::Client::REST::Ticket->new( rt => $rt, id => $tix[0])->attachments();
- my $iterator = $attachments->get_iterator;
- my @attachments;
- while (my $att = &$iterator) {
- if ( $att->file_name eq 'bplogo.gif' ) {
- push @attachments, $att ;
- warn "goto ne";
- }
- }
+my ($val,$msg) = $tick->comment( message => 'this is a comment', attachments => [$IMAGE_FILE]);
+
+
+my @attachments = get_rt_ticket_attachments($tix[0]);
+
is (scalar @attachments, 1, "Found our one attachment");
@@ -143,12 +140,71 @@
);
diag("check to see if YATTA has an attachment");
+
+
+my $rt_attach_uuid;
+run_output_matches( sd => [qw/ticket attachment list --uuid/, $yatta_uuid], [qr/(.*?)(?{ $rt_attach_uuid = $1 }) bplogo.gif image\/gif/] );
+
+ok($rt_attach_uuid);
+
diag("Check to see if YATTA's attachment is binary-identical to the original one");
+
+my $image_data = file($IMAGE_FILE)->slurp;
+my ($contentret, $stdout, $stderr) = run_script('sd', [qw/attachment content --uuid/, $rt_attach_uuid]);
+ok($contentret, "Ran the script ok");
+is($stdout, $image_data, "We roundtripped some binary");
+is($stderr, '');
+
+
diag("Add an attachment to YATTA");
+
+my $MAKEFILE_CONTENT = file('Makefile.PL')->slurp;
+chomp($MAKEFILE_CONTENT);
+my $makefile_attach_uuid;
+run_output_matches('sd', [qw/ticket attachment create --uuid/, $yatta_uuid, '--file', 'Makefile.PL'], [qr/Created attachment (.*?)(?{ $makefile_attach_uuid = $1})$/], [], "Added a attachment");
+
+
+
+my ($makefileret, $makefileout, $makefilerr) = run_script('sd', [qw/attachment content --uuid/, $makefile_attach_uuid]);
+is($makefileout, $MAKEFILE_CONTENT, "We inserted the makefile correctly");
+
diag("Push the attachment to RT");
+
+( $ret, $out, $err ) = run_script( 'sd', [ 'push', '--to', $sd_rt_url ] );
+
diag("Check to see if the RT ticket has two attachments");
+my @two_attachments = sort { $a->file_name cmp $b->file_name } get_rt_ticket_attachments($tix[0]);
+is(scalar @two_attachments, 2, " I have two attachments on the RT side!");
+
+my $makefile = shift @two_attachments;
+my $logo = shift @two_attachments;
+
+
+is ($logo->file_name, 'bplogo.gif');
+is ($makefile->file_name, 'Makefile.PL');
+is($makefile->content, $MAKEFILE_CONTENT , " The makefile's content was ropundtripped ot rt ok");
+
+is($logo->content, file($IMAGE_FILE)->slurp, " The image's content was ropundtripped ot rt ok");
+
#diag $uuid;
+
+exit();
+
+
+sub get_rt_ticket_attachments {
+ my $ticket = shift;
+
+ my $attachments = RT::Client::REST::Ticket->new( rt => $rt, id => $ticket)->attachments();
+ my $iterator = $attachments->get_iterator;
+ my @attachments;
+ while (my $att = &$iterator) {
+ if ( $att->file_name ) {
+ push @attachments, $att ;
+ }
+ }
+ return @attachments
+}
1;
More information about the Bps-public-commit
mailing list