[Bps-public-commit] r16153 - in sd/trunk: . lib/App/SD/CLI/Command/Ticket lib/App/SD/CLI/Model
spang at bestpractical.com
spang at bestpractical.com
Mon Sep 29 18:16:23 EDT 2008
Author: spang
Date: Mon Sep 29 18:16:23 2008
New Revision: 16153
Modified:
sd/trunk/ (props changed)
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
Log:
r50154 at loki: spang | 2008-09-28 15:52:20 -0400
revamp sd ticket create to use sections to differentiate editable/uneditable props
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 Sep 29 18:16:23 2008
@@ -9,44 +9,23 @@
# props are specified on the commandline
override run => sub {
my $self = shift;
- my $record = $self->_get_record_object;
my @prop_set = $self->prop_set;
+ my $record = $self->_get_record_object;
# only invoke editor if no props specified on the commandline or edit arg
# specified
if (!@prop_set || $self->has_arg('edit')) {
- 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
- map { $prefill_props{$_} = undef } @props;
- # set default props
- $record->default_props(\%prefill_props);
- if ($self->has_arg('edit')) {
- # override with props specified on the commandline
- map { $prefill_props{$_} = $self->prop($_) if $self->has_prop($_) } @props;
- $self->delete_arg('edit');
- }
- # undef values are noisy later when we want to interpolate the hash
- map { $prefill_props{$_} = '' if !defined($prefill_props{$_}) } @props;
-
- my $footer = comment_separator();
+ my $ticket_string_to_edit = $self->create_record_string();
- my $ticket = $self->get_content( type => 'ticket', default_edit => 1,
- prefill_props => \%prefill_props,
- props_order => \@props,
- footer => $footer,
- );
+ my $ticket = $self->edit_text($ticket_string_to_edit);
die "Aborted.\n"
- if length($ticket) == 0;
+ if $ticket eq $ticket_string_to_edit; # user didn't change anything
- (my $props_ref, my $comment) = $self->parse_record($ticket);
+ (my $props_ref, my $comment) = $self->parse_record_string($ticket);
foreach my $prop (keys %$props_ref) {
- $self->set_prop($prop => $props_ref->{$prop})
- unless $prop =~ /$do_not_edit/; # don't let users create ids
+ $self->set_prop($prop => $props_ref->{$prop});
}
super();
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 Sep 29 18:16:23 2008
@@ -29,18 +29,140 @@
$command->run();
}
+=head2 metadata_separator_text
-=head2 comment_separator
+Returns a string of text that goes in the comment denoting the beginning of
+uneditable ticket metadata in a string representing a ticket.
-Returns a string that separates the prop: value lines from the comment,
-which will be free text to the end of the new ticket. May contain
-arbitrary newlines.
+Uneditable ticket metadata includes things such as ticket id and
+creation date that are useful to display to the user when editing a
+ticket but are automatically assigned by sd and are not intended to
+be changed manually.
=cut
-sub comment_separator { "\n\n=== add new ticket comment below ===\n"; }
+sub metadata_separator_text {
+ 'required ticket metadata (changes here will not be saved)'
+}
+
+=head2 editable_props_separator_text
+
+Returns a string that denotes the text that goes in the comment denoting the
+beginning of prop: value pairs that are updatable in a string representing a
+ticket.
+
+=cut
+
+sub editable_props_separator_text { 'edit ticket details below' }
+
+=head2 comment_separator_text
+
+Returns a string that goes in the comment that separates the prop: value lines
+from the ticket comment in a string representing a ticket. The ticket comment
+will be free text to the end of the new ticket. May contain arbitrary newlines.
+
+=cut
+
+sub comment_separator_text { 'add new ticket comment below' }
+
+=head2 separator_pattern
+
+A pattern that will match on lines that count as section separators
+in tickets represented as strings. Separator string text is remembered
+as C<$1>.
+
+=cut
+
+sub separator_pattern { qr/^=== (.*) ===$/ }
+
+=head2 create_separator $text
+
+Takes a string and returns it in separator form.
+
+=cut
+
+sub create_separator {
+ my $self = shift;
+ my $text = shift;
-=head2 parse_record $str
+ return "=== $text ===";
+}
+
+=head2 comment_pattern
+
+Returns a pattern that will match on lines that count as comments in
+tickets represented as strings.
+
+=cut
+
+sub comment_pattern { qr/^\s*#/ }
+
+=head2 create_record_string
+
+Creates a string representing a new record, prefilling default props
+and props specified on the command line. Intended to be presented to
+the user for editing using L<Prophet::CLI::Command->edit_text>
+and then parsed using L</create_record_string>.
+
+=cut
+
+sub create_record_string {
+ my $self = shift;
+ my $record = $self->_get_record_object;
+
+ my $props_not_to_edit = $record->props_not_to_edit;
+ my (@metadata_order, @editable_order);
+ my (%metadata_props, %editable_props);
+
+ # separate out user-editable props so we can both show all
+ # the props that will be added to the new ticket and prevent
+ # users from being able to break things by changing props
+ # that shouldn't be changed, such as uuid
+ foreach my $prop ($record->props_to_show) {
+ if ($prop =~ $props_not_to_edit) {
+ push @metadata_order, $prop;
+ $metadata_props{$prop} = undef;
+ } else {
+ push @editable_order, $prop;
+ $editable_props{$prop} = undef;
+ }
+ }
+
+ # fill in prop defaults
+ $record->default_props(\%metadata_props);
+ $record->default_props(\%editable_props);
+
+ # fill in props specified on the commandline (overrides defaults)
+ if ($self->has_arg('edit')) {
+ map { $editable_props{$_} = $self->prop($_) if $self->has_prop($_) } @editable_order;
+ $self->delete_arg('edit');
+ }
+
+ # make undef values empty strings to avoid interpolation warnings
+ # (we can't do this earlier because $record->default_props only
+ # overrides undefined props)
+ map { $metadata_props{$_} = '' if !defined($metadata_props{$_}) }
+ @metadata_order;
+ map { $editable_props{$_} = '' if !defined($editable_props{$_}) }
+ @editable_order;
+
+ my $metadata_separator = $self->create_separator(metadata_separator_text());
+ my $editable_separator = $self->create_separator(editable_props_separator_text());
+ my $comment_separator = $self->create_separator(comment_separator_text());
+
+ my $metadata_props_string = join "\n",
+ map { "$_: $metadata_props{$_}" } @metadata_order;
+ my $editable_props_string = join "\n",
+ map { "$_: $editable_props{$_}" } @editable_order;
+
+ # glue all the parts together
+ my $ticket_string = $metadata_separator . "\n\n" . $metadata_props_string
+ . "\n\n" . $editable_separator . "\n\n" .
+ $editable_props_string . "\n\n" . $comment_separator
+ . "\n";
+}
+
+=head2 parse_record_string $str
Takes a string containing a ticket record consisting of prop: value pairs
followed by a separator, followed by an optional comment.
@@ -50,22 +172,35 @@
=cut
-sub parse_record {
+sub parse_record_string {
my $self = shift;
my $ticket = shift;
- my %props;
- my ($new_props, $comment) = split comment_separator(), $ticket;
- my @lines = split "\n", $new_props;
+ my @lines = split "\n", $ticket;
+ my $last_seen_sep = '';
+ my %new_props;
+ my $comment = '';
+
foreach my $line (@lines) {
- # match prop: value pairs. whitespace in between is ignored.
- if ($line =~ m/^([^:]+):\s*(.*)$/) {
- my $prop = $1;
- my $val = $2;
- $props{$prop} = $val unless !($val);
+ if ($line =~ separator_pattern()) {
+ $last_seen_sep = $1;
+ } elsif ($line =~ comment_pattern() or
+ # skip comments and unchangeable props
+ $last_seen_sep eq metadata_separator_text()) {
+ next;
+ } elsif ($last_seen_sep eq editable_props_separator_text()) {
+ # match prop: value pairs. whitespace in between is ignored.
+ if ($line =~ m/^([^:]+):\s*(.*)$/) {
+ my $prop = $1;
+ my $val = $2;
+ $new_props{$prop} = $val unless !($val);
+ }
+ } elsif ($last_seen_sep eq comment_separator_text()) {
+ $comment .= $line;
}
}
- return \%props, $comment;
+
+ return \%new_props, $comment;
}
no Moose::Role;
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 Sep 29 18:16:23 2008
@@ -101,7 +101,7 @@
=cut
-sub props_not_to_edit { qr/^(id|created|creator)$/ }
+sub props_not_to_edit { qr/^(id|creator|created|original_replica)$/ }
=head2 is_overdue [$date]
More information about the Bps-public-commit
mailing list