[Bps-public-commit] r15218 - in sd/trunk: . lib/App/SD lib/App/SD/CLI lib/App/SD/CLI/Command/Ticket lib/App/SD/CLI/Command/Ticket/Comment lib/App/SD/CLI/Model lib/App/SD/Model t/scripts
spang at bestpractical.com
spang at bestpractical.com
Mon Aug 18 10:18:07 EDT 2008
Author: spang
Date: Mon Aug 18 10:18:05 2008
New Revision: 15218
Added:
sd/trunk/lib/App/SD/CLI/Command/Ticket/Comment/Update.pm
sd/trunk/lib/App/SD/CLI/Command/Ticket/Update.pm
sd/trunk/t/03-update-ticket-with-editor.t
sd/trunk/t/04-update-ticket-comment-with-editor.t
sd/trunk/t/scripts/
sd/trunk/t/scripts/ticket-comment-update-editor.pl (contents, props changed)
sd/trunk/t/scripts/ticket-create-editor.pl (contents, props changed)
sd/trunk/t/scripts/ticket-update-editor.pl (contents, props changed)
Removed:
sd/trunk/t/ticket-create-editor.pl
Modified:
sd/trunk/ (props changed)
sd/trunk/lib/App/SD/CLI/Command.pm
sd/trunk/lib/App/SD/CLI/Command/Ticket/Create.pm
sd/trunk/lib/App/SD/CLI/Model/Ticket.pm
sd/trunk/lib/App/SD/Model/Ticket.pm
sd/trunk/lib/App/SD/Test.pm
sd/trunk/t/02-create-with-editor.t
Log:
r48270 at loki: spang | 2008-08-14 17:25:24 +0100
re-add strangely missing test code, making a fix in the process
r48272 at loki: spang | 2008-08-14 22:15:22 +0100
use props_not_to_edit to determine which props not to present for editing
r48273 at loki: spang | 2008-08-14 22:47:08 +0100
patch Help.pm to Jesse's new version, which seems to have gotten mis-merged somewhere along the line
r48277 at loki: spang | 2008-08-15 15:56:08 +0100
add creator to props_not_to_edit
r48278 at loki: spang | 2008-08-15 15:57:28 +0100
add new create_new_comment method to consolidate code from ticket update / create
r48279 at loki: spang | 2008-08-15 15:58:25 +0100
bugfix the ticket comment parsing regex and a minor change to the comment separator
r48280 at loki: spang | 2008-08-15 15:59:20 +0100
use new create_new_comment method in ticket create command
r48281 at loki: spang | 2008-08-15 16:12:06 +0100
customize comment and ticket update commands for sd
r48419 at loki: spang | 2008-08-18 10:26:12 +0100
prophet doesn't like commands with incorrect package names
r48420 at loki: spang | 2008-08-18 11:48:14 +0100
tests for new update functionality
r48421 at loki: spang | 2008-08-18 11:49:09 +0100
support functions for new tests
r48422 at loki: spang | 2008-08-18 11:49:37 +0100
print success message after comment updated
Modified: sd/trunk/lib/App/SD/CLI/Command.pm
==============================================================================
--- sd/trunk/lib/App/SD/CLI/Command.pm (original)
+++ sd/trunk/lib/App/SD/CLI/Command.pm Mon Aug 18 10:18:05 2008
@@ -1,6 +1,7 @@
package App::SD::CLI::Command;
use Moose::Role;
use Path::Class;
+use Params::Validate qw(validate);
=head2 get_content %args
@@ -61,6 +62,30 @@
return $content;
}
+=head2 create_new_comment content => str, uuid => str
+
+A convenience method that takes a content string and a ticket uuid and creates
+a new comment record, for use in other commands (such as ticket create
+and ticket update).
+
+=cut
+
+sub create_new_comment {
+ my $self = shift;
+ validate(@_, { content => 1, uuid => 1 } );
+ my %args = @_;
+
+ use App::SD::CLI::Command::Ticket::Comment::Create;
+
+ $self->cli->change_attributes( args => \%args );
+ my $command = App::SD::CLI::Command::Ticket::Comment::Create->new(
+ uuid => $args{uuid},
+ cli => $self->cli,
+ type => 'comment',
+ );
+ $command->run();
+}
+
no Moose::Role;
1;
Added: sd/trunk/lib/App/SD/CLI/Command/Ticket/Comment/Update.pm
==============================================================================
--- (empty file)
+++ sd/trunk/lib/App/SD/CLI/Command/Ticket/Comment/Update.pm Mon Aug 18 10:18:05 2008
@@ -0,0 +1,27 @@
+package App::SD::CLI::Command::Ticket::Comment::Update;
+use Moose;
+
+extends 'Prophet::CLI::Command::Update';
+
+override run => sub {
+ my $self = shift;
+ $self->require_uuid;
+
+ my $record = $self->_load_record;
+ my @prop_set = $self->prop_set;
+
+ # we don't want to do prop: value editing by default for comments since
+ # it's just a blob of text
+ if (!@prop_set || $self->has_arg('edit')) {
+ my $updated_comment = $self->edit_text($record->prop('content'));
+ $record->set_prop(name => 'content', value => $updated_comment);
+ print "Updated comment " . $record->luid . " (" . $record->uuid . ")\n";
+ } else {
+ super();
+ }
+};
+
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
+1;
Modified: sd/trunk/lib/App/SD/CLI/Command/Ticket/Create.pm
==============================================================================
--- sd/trunk/lib/App/SD/CLI/Command/Ticket/Create.pm (original)
+++ sd/trunk/lib/App/SD/CLI/Command/Ticket/Create.pm Mon Aug 18 10:18:05 2008
@@ -1,8 +1,6 @@
package App::SD::CLI::Command::Ticket::Create;
use Moose;
-use App::SD::CLI::Command::Ticket::Comment::Create;
-
extends 'Prophet::CLI::Command::Create';
with 'App::SD::CLI::Model::Ticket';
with 'App::SD::CLI::Command';
@@ -17,7 +15,8 @@
# only invoke editor if no props specified on the commandline or edit arg
# specified
if (!@prop_set || $self->has_arg('edit')) {
- my @props = grep {!/^id$/} $record->props_to_show;
+ my $do_not_edit = $record->props_not_to_edit;
+ my @props = grep {!/$do_not_edit/} $record->props_to_show;
my %prefill_props;
# these props must exist in the hash, even if they have no value
@@ -47,7 +46,7 @@
foreach my $prop (keys %$props_ref) {
$self->set_prop($prop => $props_ref->{$prop})
- unless $prop eq 'id'; # don't let users create ids
+ unless $prop =~ /$do_not_edit/; # don't let users create ids
}
super();
@@ -55,16 +54,9 @@
# retrieve the created record from the superclass
$record = $self->record();
- if ($comment) {
- my $args = { content => $comment };
- $self->cli->change_attributes( args => $args );
- my $command = App::SD::CLI::Command::Ticket::Comment::Create->new(
- uuid => $record->uuid,
- cli => $self->cli,
- type => 'comment',
- );
- $command->run();
- }
+ $self->create_new_comment( content => $comment, uuid => $record->uuid )
+ if $comment;
+
} else {
super();
}
Added: sd/trunk/lib/App/SD/CLI/Command/Ticket/Update.pm
==============================================================================
--- (empty file)
+++ sd/trunk/lib/App/SD/CLI/Command/Ticket/Update.pm Mon Aug 18 10:18:05 2008
@@ -0,0 +1,77 @@
+package App::SD::CLI::Command::Ticket::Update;
+use Moose;
+
+extends 'Prophet::CLI::Command::Update';
+with 'App::SD::CLI::Model::Ticket';
+with 'App::SD::CLI::Command';
+
+# use an editor to edit if no props are specified on the commandline,
+# allowing the creation of a new comment in the process
+override run => sub {
+ my $self = shift;
+ $self->require_uuid;
+
+ my $record = $self->_load_record;
+ my $props = $record->get_props;
+
+ if (!@{$self->prop_set} || $self->has_arg('edit')) {
+ my $do_not_edit = $record->props_not_to_edit;
+
+ my @show_props;
+ if ($record->can('props_to_show')) {
+ @show_props = $record->props_to_show;
+ } else {
+ @show_props = sort keys %$props;
+ }
+
+ # props we want to show for editing
+ my %prefill_props = %{$record->get_props};
+ map { $prefill_props{$_} = '' if !exists $prefill_props{$_} } @show_props;
+
+ # add any other defined props onto the end of the ordering and remove
+ # unwanted props
+ my %tmp;
+ map { $tmp{$_} = 1 } @show_props;
+ map { push @show_props, $_ unless exists $tmp{$_} } keys %prefill_props;
+ @show_props = grep !/$do_not_edit/, @show_props;
+
+ my $updated = $self->get_content( type => 'ticket', default_edit => 1,
+ prefill_props => \%prefill_props,
+ props_order => \@show_props,
+ footer => comment_separator(),
+ );
+
+ die "Aborted.\n"
+ if length($updated) == 0;
+
+ my ($props_ref, $comment) = $self->parse_record($updated);
+
+ no warnings 'uninitialized';
+
+ foreach my $prop (keys %$props_ref) {
+ my $val = $props_ref->{$prop};
+ $record->set_prop(name => $prop, value => $val) unless
+ ($prop =~ /$do_not_edit/ or $val eq $prefill_props{$prop});
+ }
+
+ # if a formerly existing prop was removed from the output, delete it
+ foreach my $prop (keys %{$record->get_props}) {
+ unless ($prop =~ /$do_not_edit/) {
+ $record->delete_prop(name => $prop) if !exists $props_ref->{$prop};
+ }
+ }
+
+ print 'Updated ticket ' . $record->luid . ' (' . $record->uuid . ")\n";
+
+ $self->create_new_comment( content => $comment, uuid => $record->uuid )
+ if $comment;
+
+ } else {
+ super();
+ }
+};
+
+__PACKAGE__->meta->make_immutable;
+no Moose;
+
+1;
Modified: sd/trunk/lib/App/SD/CLI/Model/Ticket.pm
==============================================================================
--- sd/trunk/lib/App/SD/CLI/Model/Ticket.pm (original)
+++ sd/trunk/lib/App/SD/CLI/Model/Ticket.pm Mon Aug 18 10:18:05 2008
@@ -11,7 +11,7 @@
=cut
-sub comment_separator { "\n\n=== add ticket comment below ===\n"; }
+sub comment_separator { "\n\n=== add new ticket comment below ===\n"; }
=head2 parse_record $str
@@ -32,7 +32,7 @@
my @lines = split "\n", $new_props;
foreach my $line (@lines) {
# match prop: value pairs. whitespace in between is ignored.
- if ($line =~ m/^(.+):\s*(.*)$/) {
+ if ($line =~ m/^([^:]+):\s*(.*)$/) {
my $prop = $1;
my $val = $2;
$props{$prop} = $val unless !($val);
Modified: sd/trunk/lib/App/SD/Model/Ticket.pm
==============================================================================
--- sd/trunk/lib/App/SD/Model/Ticket.pm (original)
+++ sd/trunk/lib/App/SD/Model/Ticket.pm Mon Aug 18 10:18:05 2008
@@ -93,6 +93,16 @@
('id', 'summary', 'status', 'owner', 'created', 'due', 'creator', 'reported_by')
}
+=head2 props_not_to_edit
+
+A pattern of props not to show in an editor (when creating or updating a
+ticket, for example). Could also be used to determine which props shouldn't be
+user-modifiable.
+
+=cut
+
+sub props_not_to_edit { qr/^(id|created|creator)$/ }
+
=head2 is_overdue [$date]
Takes an ISO date (or uses the C<date> prop value if no date is given).
Modified: sd/trunk/lib/App/SD/Test.pm
==============================================================================
--- sd/trunk/lib/App/SD/Test.pm (original)
+++ sd/trunk/lib/App/SD/Test.pm Mon Aug 18 10:18:05 2008
@@ -103,3 +103,48 @@
return ( $ticket_luid, $ticket_uuid, $comment_luid, $comment_uuid );
}
+
+=head2 update_ticket_with_editor_ok TICKET_LUID, TICKET_UUID
+
+Updates the ticket given by TICKET_UUID using a spawned editor. It's
+expected that C<$ENV{VISUAL}> has been frobbed into something non-interactive,
+or this test will just hang forever.
+
+Returns the luid and uuid of the comment created during the update (both will
+be undef if none is created).
+
+=cut
+
+sub update_ticket_with_editor_ok {
+ my $self = shift;
+ my $ticket_luid = shift;
+ my $ticket_uuid = shift;
+ my ($comment_luid, $comment_uuid);
+
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+ Prophet::Test::run_output_matches( 'sd', [ 'ticket', 'update', $ticket_uuid ],
+ [ qr/Updated ticket (.*?)(?{ $ticket_luid })\s+\((.*)(?{ $ticket_uuid })\)/,
+ qr/Created comment (.*?)(?{ $comment_luid = $1 })\s+\((.*)(?{ $comment_uuid = $2 })\)/ ]
+ );
+
+ return ( $comment_luid, $comment_uuid );
+}
+
+=head2 update_ticket_comment_with_editor_ok COMMENT_LUID, COMMENT_UUID
+
+Updates the ticket comment given by COMMENT_UUID using a spawned editor. It's
+expected that C<$ENV{VISUAL}> has been frobbed into something non-interactive,
+or this test will just hang forever.
+
+=cut
+
+sub update_ticket_comment_with_editor_ok {
+ my $self = shift;
+ my ($comment_luid, $comment_uuid) = @_;
+
+ local $Test::Builder::Level = $Test::Builder::Level + 1;
+ Prophet::Test::run_output_matches( 'sd',
+ [ 'ticket', 'comment', 'update', $comment_uuid ],
+ [ qr/Updated comment (.*?)(?{ $comment_luid })\s+\((.*)(?{ $comment_uuid })\)/]
+ );
+}
Modified: sd/trunk/t/02-create-with-editor.t
==============================================================================
--- sd/trunk/t/02-create-with-editor.t (original)
+++ sd/trunk/t/02-create-with-editor.t Mon Aug 18 10:18:05 2008
@@ -0,0 +1,42 @@
+#!/usr/bin/perl -w
+use strict;
+
+use Prophet::Test tests => 4;
+use App::SD::Test;
+use Cwd;
+
+BEGIN {
+ require File::Temp;
+ $ENV{'PROPHET_REPO'} = $ENV{'SD_REPO'} = File::Temp::tempdir( CLEANUP => 0 ) . '/_svb';
+ diag 'export SD_REPO=' . $ENV{'PROPHET_REPO'} . "\n";
+ # frob the editor to use a perl script instead of spawning vi/emacs/etc.
+ $ENV{'VISUAL'} = File::Spec->catfile(getcwd(), 't', 'scripts', 'ticket-create-editor.pl');
+ diag 'export VISUAL=' . $ENV{'VISUAL'} . "\n";
+}
+
+my ($ticket_id, $ticket_uuid, $comment_id, $comment_uuid) = App::SD::Test::create_ticket_with_editor_ok();
+
+run_output_matches( 'sd', [ 'ticket',
+ 'list', '--regex', '.' ],
+ [ qr/(\d+) creating tickets with an editor is totally awesome new/]
+);
+
+run_output_matches( 'sd', [ 'ticket', 'show', '--batch', '--id', $ticket_id ],
+ [
+ "id: $ticket_id ($ticket_uuid)",
+ 'summary: creating tickets with an editor is totally awesome',
+ 'status: new',
+ qr/^created: \d{4}-\d{2}-\d{2}.+$/,
+ qr/^creator: .+ at .+$/,
+ ]
+);
+
+run_output_matches( 'sd', [ 'ticket', 'comment', 'show', '--batch', '--id', $comment_id ],
+ [
+ "id: $comment_id ($comment_uuid)",
+ 'content: We can create a comment at the same time.',
+ qr/^created: \d{4}-\d{2}-\d{2}.+$/,
+ qr/^creator: .+ at .+$/,
+ qr/^ticket: $ticket_uuid$/,
+ ]
+);
Added: sd/trunk/t/03-update-ticket-with-editor.t
==============================================================================
--- (empty file)
+++ sd/trunk/t/03-update-ticket-with-editor.t Mon Aug 18 10:18:05 2008
@@ -0,0 +1,55 @@
+#!/usr/bin/perl -w
+use strict;
+
+use Prophet::Test tests => 5;
+use App::SD::Test;
+use Cwd;
+
+BEGIN {
+ require File::Temp;
+ $ENV{'PROPHET_REPO'} = $ENV{'SD_REPO'} = File::Temp::tempdir( CLEANUP => 0 ) . '/_svb';
+ diag 'export SD_REPO=' . $ENV{'PROPHET_REPO'} . "\n";
+ # frob the editor to use a perl script instead of spawning vi/emacs/etc.
+ $ENV{'VISUAL'} = File::Spec->catfile(getcwd(), 't', 'scripts', 'ticket-update-editor.pl');
+ diag 'export VISUAL=' . $ENV{'VISUAL'} . "\n";
+}
+
+# create ticket
+my ($ticket_id, $ticket_uuid) = create_ticket_ok( '--summary', 'zomg!',
+ '--owner', 'foo at bar.com');
+
+# verify that it's correct (test prop won't be shown)
+run_output_matches( 'sd', [ 'ticket', 'show', '--batch', '--id', $ticket_id ],
+ [
+ "id: $ticket_id ($ticket_uuid)",
+ 'summary: zomg!',
+ 'status: new',
+ 'owner: foo at bar.com',
+ qr/^created: \d{4}-\d{2}-\d{2}.+$/,
+ qr/^creator: .+ at .+$/,
+ ]
+);
+
+# update it
+my ($comment_id, $comment_uuid) = App::SD::Test->update_ticket_with_editor_ok($ticket_id, $ticket_uuid);
+
+# check output
+run_output_matches( 'sd', [ 'ticket', 'show', '--batch', '--id', $ticket_id ],
+ [
+ "id: $ticket_id ($ticket_uuid)",
+ 'summary: summary changed',
+ 'status: new',
+ qr/^created: \d{4}-\d{2}-\d{2}.+$/,
+ qr/^creator: .+ at .+$/,
+ ]
+);
+
+run_output_matches( 'sd', [ 'ticket', 'comment', 'show', '--batch', '--id', $comment_id ],
+ [
+ "id: $comment_id ($comment_uuid)",
+ 'content: We can create a comment at the same time.',
+ qr/^created: \d{4}-\d{2}-\d{2}.+$/,
+ qr/^creator: .+ at .+$/,
+ qr/^ticket: $ticket_uuid$/,
+ ]
+);
Added: sd/trunk/t/04-update-ticket-comment-with-editor.t
==============================================================================
--- (empty file)
+++ sd/trunk/t/04-update-ticket-comment-with-editor.t Mon Aug 18 10:18:05 2008
@@ -0,0 +1,50 @@
+#!/usr/bin/perl -w
+use strict;
+
+use Prophet::Test tests => 5;
+use App::SD::Test;
+use Cwd;
+
+BEGIN {
+ require File::Temp;
+ $ENV{'PROPHET_REPO'} = $ENV{'SD_REPO'} = File::Temp::tempdir( CLEANUP => 0 ) . '/_svb';
+ diag 'export SD_REPO=' . $ENV{'PROPHET_REPO'} . "\n";
+ # frob the editor to use a perl script instead of spawning vi/emacs/etc.
+ $ENV{'VISUAL'} = File::Spec->catfile(getcwd(), 't', 'scripts', 'ticket-comment-update-editor.pl');
+ diag 'export VISUAL=' . $ENV{'VISUAL'} . "\n";
+}
+
+# create ticket
+my ($ticket_id, $ticket_uuid) = create_ticket_ok( '--summary', 'zomg!' );
+
+# create comment
+my ($comment_id, $comment_uuid) = create_ticket_comment_ok(
+ '--content' => 'a new comment', '--id' => $ticket_id
+);
+
+# verify that it's correct (test prop won't be shown)
+run_output_matches( 'sd',
+ [ 'ticket', 'comment', 'show', '--batch', '--id', $comment_id ],
+ [
+ "id: $comment_id ($comment_uuid)",
+ qr/a new comment/,
+ qr/^created: \d{4}-\d{2}-\d{2}.+$/,
+ qr/^creator: .+ at .+$/,
+ "ticket: $ticket_uuid",
+ ]
+);
+
+# update it
+App::SD::Test->update_ticket_comment_with_editor_ok($comment_id, $comment_uuid);
+
+# check output
+run_output_matches( 'sd',
+ [ 'ticket', 'comment', 'show', '--batch', '--id', $comment_id ],
+ [
+ "id: $comment_id ($comment_uuid)",
+ qr/huzzah!/,
+ qr/^created: \d{4}-\d{2}-\d{2}.+$/,
+ qr/^creator: .+ at .+$/,
+ "ticket: $ticket_uuid",
+ ]
+);
Added: sd/trunk/t/scripts/ticket-comment-update-editor.pl
==============================================================================
--- (empty file)
+++ sd/trunk/t/scripts/ticket-comment-update-editor.pl Mon Aug 18 10:18:05 2008
@@ -0,0 +1,8 @@
+#!/usr/bin/perl -i
+
+# perl script to trick Proc::InvokeEditor with for the ticket update command
+
+while (<>) {
+ print "huzzah!";
+}
+
Added: sd/trunk/t/scripts/ticket-create-editor.pl
==============================================================================
--- (empty file)
+++ sd/trunk/t/scripts/ticket-create-editor.pl Mon Aug 18 10:18:05 2008
@@ -0,0 +1,10 @@
+#!/usr/bin/perl -i
+
+# perl script to trick Proc::InvokeEditor with for the ticket create command
+
+while (<>) {
+ s/^summary:.*$/summary: creating tickets with an editor is totally awesome/;
+ print;
+ print "We can create a comment at the same time.\n" if /^===/;
+}
+
Added: sd/trunk/t/scripts/ticket-update-editor.pl
==============================================================================
--- (empty file)
+++ sd/trunk/t/scripts/ticket-update-editor.pl Mon Aug 18 10:18:05 2008
@@ -0,0 +1,11 @@
+#!/usr/bin/perl -i
+
+# perl script to trick Proc::InvokeEditor with for the ticket update command
+
+while (<>) {
+ s/^summary:.*$/summary: summary changed/;
+ s/^owner:.*//;
+ print;
+ print "We can create a comment at the same time.\n" if /^===/;
+}
+
More information about the Bps-public-commit
mailing list