From 2245ad12cefdec60520ecab72f35bcdf14908259 Mon Sep 17 00:00:00 2001 From: Andrew Chilton Date: Fri, 27 Jun 2008 00:17:00 +1200 Subject: [PATCH] Added re-editing of issues/comments and checking against config (#6baa8555). --- .cil | 30 ++++++++++ bin/cil | 126 +++++++++++++++++++++++++++++------------- issues/c_4edba98c.cil | 16 ++++++ issues/i_02ee35bd.cil | 4 +- issues/i_5c88cb30.cil | 6 +- issues/i_6baa8555.cil | 7 ++- issues/i_85eceee9.cil | 4 +- issues/i_98203ce8.cil | 2 +- issues/i_99d9dd74.cil | 4 +- issues/i_b19d5ada.cil | 4 +- issues/i_cbb43db9.cil | 4 +- issues/i_fb79b2e8.cil | 6 +- lib/CIL.pm | 46 ++++++++++++++- lib/CIL/Base.pm | 41 +++++++++++++- lib/CIL/Comment.pm | 8 +++ lib/CIL/Issue.pm | 36 ++++++++++-- lib/CIL/Utils.pm | 7 ++- 17 files changed, 282 insertions(+), 69 deletions(-) create mode 100644 issues/c_4edba98c.cil diff --git a/.cil b/.cil index e69de29..c1fef1f 100644 --- a/.cil +++ b/.cil @@ -0,0 +1,30 @@ +StatusStrict: 1 +StatusAllowedList: New +StatusAllowedList: InProgress +StatusAllowedList: Fixed +StatusAllowedList: OnHold +StatusAllowedList: Duplicate +StatusAllowedList: Finished +StatusOpenList: New +StatusOpenList: InProgress +StatusOpenList: Fixed +StatusClosedList: OnHold +StatusClosedList: Duplicate +StatusClosedList: Finished +LabelStrict: 1 +LabelAllowedList: Release-v0.1.0 +LabelAllowedList: Release-v0.2.0 +LabelAllowedList: Release-v0.2.1 +LabelAllowedList: Type-Enhancement +LabelAllowedList: Type-Defect +LabelAllowedList: Type-Task +LabelAllowedList: Type-Patch +LabelAllowedList: Type-Other +LabelAllowedList: Milestone-v0.1 +LabelAllowedList: Milestone-v0.2 +LabelAllowedList: Milestone-v0.3 +LabelAllowedList: Milestone-Future +LabelAllowedList: Priority-Critical +LabelAllowedList: Priority-High +LabelAllowedList: Priority-Medium +LabelAllowedList: Priority-Low diff --git a/bin/cil b/bin/cil index c8f9bac..eb06385 100755 --- a/bin/cil +++ b/bin/cil @@ -34,6 +34,8 @@ use CIL::Attachment; ## ---------------------------------------------------------------------------- # constants +my $y = 'y'; + use constant VERSION => '0.2.1'; my @IN_OPTS = ( @@ -58,22 +60,6 @@ my %BOOLEAN_ARGS = ( my $gan = $ENV{GIT_AUTHOR_NAME} || 'Your Name'; my $gae = $ENV{GIT_AUTHOR_EMAIL} || 'you@example.org'; -my $new_issue_text = <<"EOF"; -Summary : -Status : New -CreatedBy : $gan <$gae> -AssignedTo : $gan <$gae> -Label : - -Description... -EOF - -my $add_comment_text = <<"EOF"; -CreatedBy : $gan <$gae> - -Description... -EOF - ## ---------------------------------------------------------------------------- # main program @@ -102,6 +88,7 @@ EOF } my $cil = CIL->new(); + $cil->read_config_file( '.cil' ); &{"cmd_$command"}($cil, $args, @ARGV); } @@ -229,11 +216,37 @@ sub cmd_status { sub cmd_add { my ($cil, undef, $issue_name) = @_; - # read in the new issue text CIL::Utils->ensure_interactive(); - my $fh = CIL::Utils->solicit( $new_issue_text ); - my $issue = CIL::Issue->new_from_fh( 'tmp', $fh ); + my $issue = CIL::Issue->new('tmpname'); + $issue->Status('New'); + $issue->CreatedBy("$gan <$gae>"); + $issue->AssignedTo("$gan <$gae>"); + $issue->Description("Description ..."); + + my $edit = $y; + + # keep going until we get a valid issue or we want to quit + while ( $edit eq $y ) { + # read in the new issue text + my $fh = CIL::Utils->solicit( $issue->as_output ); + $issue = CIL::Issue->new_from_fh( 'tmp', $fh ); + + # check if the issue is valid + if ( $issue->is_valid($cil) ) { + $edit = 'n'; + } + else { + print $issue->error(), "\n"; + print 'Would you like to re-edit (y/n): '; + $edit = ; + chomp $edit; + print "\n"; + } + } + + # if the issue is still invalid, they quit without correcting it + return unless $issue->is_valid( $cil ); # we've got the issue, so let's name it my $unique_str = $issue->Inserted . $issue->Summary . $issue->Description; @@ -250,20 +263,35 @@ sub cmd_edit { fatal("Couldn't load issue '$issue_name'"); } - # create the ini file, then edit it - my $edit_issue_text = $issue->as_output; - - # read in the new issue text CIL::Utils->ensure_interactive(); - my $fh = CIL::Utils->solicit( join('', @$edit_issue_text) ); - my $issue_edited = CIL::Issue->new_from_fh( $issue->name, $fh ); - unless ( defined $issue_edited ) { - fatal("couldn't create issue (program error)"); + my $edit = $y; + + # keep going until we get a valid issue or we want to quit + while ( $edit eq $y ) { + # read in the new issue text + my $fh = CIL::Utils->solicit( $issue->as_output ); + $issue = CIL::Issue->new_from_fh( $issue->name, $fh ); + + # check if the issue is valid + if ( $issue->is_valid($cil) ) { + $edit = 'n'; + } + else { + print $issue->error(), "\n"; + print 'Would you like to re-edit (y/n): '; + $edit = ; + chomp $edit; + print "\n"; + } } - $issue_edited->save($cil); - display_issue($cil, $issue_edited); + # if the issue is still invalid, they quit without correcting it + return unless $issue->is_valid( $cil ); + + # save it + $issue->save($cil); + display_issue($cil, $issue); } sub cmd_comment { @@ -274,21 +302,43 @@ sub cmd_comment { fatal("couldn't load issue '$issue_name'"); } - # read in the new issue text CIL::Utils->ensure_interactive(); - my $fh = CIL::Utils->solicit( $add_comment_text ); - my $comment = CIL::Comment->new_from_fh( 'tmp', $fh ); - unless ( defined $comment ) { - fatal("could not create new comment"); + # create the new comment + my $comment = CIL::Comment->new('tmpname'); + $comment->Issue( $issue->name ); + $comment->CreatedBy("$gan <$gae>"); + $comment->Description("Description ..."); + + my $edit = $y; + + # keep going until we get a valid issue or we want to quit + while ( $edit eq $y ) { + # read in the new comment text + my $fh = CIL::Utils->solicit( $comment->as_output ); + $comment = CIL::Comment->new_from_fh( 'tmp', $fh ); + + # check if the comment is valid + if ( $comment->is_valid($cil) ) { + $edit = 'n'; + } + else { + print $comment->error(), "\n"; + print 'Would you like to re-edit (y/n): '; + $edit = ; + chomp $edit; + print "\n"; + } } + # if the comment is still invalid, they quit without correcting it + return unless $comment->is_valid( $cil ); + # we've got the comment, so let's name it my $unique_str = $comment->Inserted . $issue->Description; $comment->set_name( substr(md5_hex($unique_str), 0, 8) ); - # finally, tell it who it's parent is and then save - $comment->Issue( $issue->name ); + # finally, save it $comment->save($cil); # add the comment to the issue, update it's timestamp and save it out @@ -368,8 +418,8 @@ sub check_paths { my ($cil) = @_; # make sure an issue directory is available - unless ( -d $cil->issue_dir ) { - fatal("couldn't find '" . $cil->issue_dir . "' directory"); + unless ( -d $cil->IssueDir ) { + fatal("couldn't find '" . $cil->IssueDir . "' directory"); } } diff --git a/issues/c_4edba98c.cil b/issues/c_4edba98c.cil new file mode 100644 index 0000000..c58c7ed --- /dev/null +++ b/issues/c_4edba98c.cil @@ -0,0 +1,16 @@ +Issue: 6baa8555 +CreatedBy: Andrew Chilton +Inserted: 2008-06-26T12:11:09 +Updated: 2008-06-26T12:12:41 + +Added the following options: + +* StatusStrict +* StatusAllowedList +* StatusOpenList +* StatusClosedList + +* LabelStrict +* LabelAllowedList + +The lists are only checked if the strict variables are on. diff --git a/issues/i_02ee35bd.cil b/issues/i_02ee35bd.cil index 21546ec..85596e3 100644 --- a/issues/i_02ee35bd.cil +++ b/issues/i_02ee35bd.cil @@ -2,11 +2,11 @@ Summary: Labels should be allowed to have a 'required' set Status: New CreatedBy: Andrew Chilton AssignedTo: Andrew Chilton -Label: Release-v0.1 Label: Priority-Medium +Label: Release-v0.1.0 Label: Type-Enhancement Inserted: 2008-05-05T12:53:38 -Updated: 2008-06-21T10:50:05 +Updated: 2008-06-26T11:53:27 In the .cil config file, there should a field which determines a 'required' set of labels. diff --git a/issues/i_5c88cb30.cil b/issues/i_5c88cb30.cil index b9707c2..a5b2670 100644 --- a/issues/i_5c88cb30.cil +++ b/issues/i_5c88cb30.cil @@ -1,15 +1,15 @@ Summary: Options for issues names needs to be added -Status: WontFix +Status: OnHold CreatedBy: Andrew Chilton AssignedTo: Andrew Chilton Label: Milestone-v0.2 Label: Priority-Low -Label: Release-v0.1 +Label: Release-v0.1.0 Label: Type-Enhancement Comment: d8dd779f Comment: feb65ae7 Inserted: 2008-05-05T12:33:19 -Updated: 2008-06-23T12:36:04 +Updated: 2008-06-26T12:10:32 When issues are created, they are given the epoch as it's name. Instead of just using the epoch, the user should be able to configure diff --git a/issues/i_6baa8555.cil b/issues/i_6baa8555.cil index 5352e93..701e18e 100644 --- a/issues/i_6baa8555.cil +++ b/issues/i_6baa8555.cil @@ -1,12 +1,13 @@ Summary: Do checking on input fields after adding or editing issue -Status: New +Status: InProgress CreatedBy: Andrew Chilton AssignedTo: Andrew Chilton Label: Priority-Medium -Label: Release-v0.1 +Label: Release-v0.1.0 Label: Type-Enhancement +Comment: 4edba98c Inserted: 2008-05-05T12:46:58 -Updated: 2008-06-21T10:59:52 +Updated: 2008-06-26T12:12:41 For example, if there is a config item in .cil called 'allowed_statuses', all input values in the 'Status' field should be diff --git a/issues/i_85eceee9.cil b/issues/i_85eceee9.cil index 22b7212..6c9d53a 100644 --- a/issues/i_85eceee9.cil +++ b/issues/i_85eceee9.cil @@ -3,11 +3,11 @@ Status: InProgress CreatedBy: Andrew Chilton AssignedTo: Andrew Chilton Label: Milestone-v0.3 -Label: Release-v0.2 +Label: Release-v0.2.0 Label: Type-Enhancement Comment: 7eb313cd Inserted: 2008-06-23T12:05:33 -Updated: 2008-06-23T12:08:05 +Updated: 2008-06-26T11:54:29 The ability to filter on various things would be nice. For example using these list commands, though summary should work the same way: diff --git a/issues/i_98203ce8.cil b/issues/i_98203ce8.cil index 5e34f51..f913c1f 100644 --- a/issues/i_98203ce8.cil +++ b/issues/i_98203ce8.cil @@ -6,7 +6,7 @@ Label: Milestone-Future Label: Release-v0.2.1 Label: Type-Enhancement Inserted: 2008-06-23T12:20:45 -Updated: 2008-06-23T12:20:45 +Updated: 2008-06-26T11:54:39 Some sort of indexing and search should be added to cil so that it is easier to find issues in amongst a long list of them. diff --git a/issues/i_99d9dd74.cil b/issues/i_99d9dd74.cil index c793311..b1ece8e 100644 --- a/issues/i_99d9dd74.cil +++ b/issues/i_99d9dd74.cil @@ -2,11 +2,11 @@ Summary: Add a filter '--grep=regex' Status: New CreatedBy: Andrew Chilton AssignedTo: Andrew Chilton -Label: Milestone-v0.3.0 +Label: Milestone-v0.3 Label: Release-v0.2.1 Label: Type-Enhancement Inserted: 2008-06-24T12:16:57 -Updated: 2008-06-24T12:16:57 +Updated: 2008-06-26T11:54:57 Having a 'grep' filter would be quite powerful. It could be used in the 'list' and 'summary' commands. It would be good if it accepts Perl regexes and might diff --git a/issues/i_b19d5ada.cil b/issues/i_b19d5ada.cil index 22de0b0..b1bf2ea 100644 --- a/issues/i_b19d5ada.cil +++ b/issues/i_b19d5ada.cil @@ -2,11 +2,11 @@ Summary: Add a 'cil check-in-git' command Status: New CreatedBy: Andrew Chilton AssignedTo: Andrew Chilton -Label: Mileston-v0.3.0 +Label: Milestone-v0.3 Label: Release-v0.2.1 Label: Type-Enhancement Inserted: 2008-06-24T03:24:14 -Updated: 2008-06-24T03:24:14 +Updated: 2008-06-26T11:55:28 The ability to check whether issues/comments/attachments are tracked by Git is important. Or indeed any VCS system. diff --git a/issues/i_cbb43db9.cil b/issues/i_cbb43db9.cil index 3490199..61123ef 100644 --- a/issues/i_cbb43db9.cil +++ b/issues/i_cbb43db9.cil @@ -3,11 +3,11 @@ Status: Finished CreatedBy: Andrew Chilton AssignedTo: Andrew Chilton Label: Priority-Medium -Label: Release-v0.1 +Label: Release-v0.1.0 Label: Type-Enhancement Comment: 2b92ef13 Inserted: 2008-05-05T12:20:28 -Updated: 2008-06-22T03:54:13 +Updated: 2008-06-26T11:55:42 'cil' currently has no way of adding attachments to issues. diff --git a/issues/i_fb79b2e8.cil b/issues/i_fb79b2e8.cil index b218517..e865d07 100644 --- a/issues/i_fb79b2e8.cil +++ b/issues/i_fb79b2e8.cil @@ -2,12 +2,12 @@ Summary: Ability to set Issue Status' from the command line Status: Finished CreatedBy: Andrew Chilton AssignedTo: Andrew Chilton -Label: Mileston-v0.2 -Label: Release-v0.1 +Label: Milestone-v0.2 +Label: Release-v0.1.0 Label: Type-Enhancement Comment: 792a4acf Inserted: 2008-06-22T04:00:20 -Updated: 2008-06-22T04:02:46 +Updated: 2008-06-26T11:56:03 The ability to do something like the following would be good. diff --git a/lib/CIL.pm b/lib/CIL.pm index b85f2fb..2a4f9d5 100644 --- a/lib/CIL.pm +++ b/lib/CIL.pm @@ -26,12 +26,20 @@ use warnings; use File::Glob qw(:glob); use base qw(Class::Accessor); -__PACKAGE__->mk_accessors(qw(issue_dir)); +__PACKAGE__->mk_accessors(qw( + IssueDir + StatusStrict StatusAllowed StatusOpen StatusClosed + LabelStrict LabelAllowed +)); my $defaults = { - issue_dir => 'issues', + IssueDir => 'issues', # the dir to save the issues in + StatusStrict => 0, # whether to complain if a status is invalid + LabelStrict => 0, # whether to complain if a label is invalid }; +my @config_hashes = qw(StatusAllowed StatusOpen StatusClosed LabelAllowed); + ## ---------------------------------------------------------------------------- sub new { @@ -53,7 +61,7 @@ sub new { sub list_issues { my ($self) = @_; - my $globpath = $self->issue_dir . "/i_*.cil"; + my $globpath = $self->IssueDir . "/i_*.cil"; my @filenames = bsd_glob($globpath); my @issues; @@ -109,6 +117,38 @@ sub get_attachments_for { return \@attachments; } +sub read_config_file { + my ( $self, $filename ) = @_; + + my $cfg = CIL::Utils->parse_cil_file( $filename ); + + # set some defaults if we don't have any of these + foreach my $key ( keys %$defaults ) { + $cfg->{$key} ||= $defaults->{$key}; + } + + # for some things, make a hash out of them + foreach my $hash_name ( @config_hashes ) { + my $h = {}; + foreach my $thing ( @{$cfg->{"${hash_name}List"}} ) { + $h->{$thing} = 1; + } + $cfg->{$hash_name} = $h; + undef $cfg->{"${hash_name}List"}; + } + + # set each config item + $self->IssueDir( $cfg->{IssueDir} ); + + $self->StatusStrict( $cfg->{StatusStrict} ); + $self->StatusAllowed( $cfg->{StatusAllowed} ); + $self->StatusOpen( $cfg->{StatusOpen} ); + $self->StatusClosed( $cfg->{StatusClosed} ); + + $self->LabelStrict( $cfg->{LabelStrict} ); + $self->LabelAllowed( $cfg->{LabelAllowed} ); +} + ## ---------------------------------------------------------------------------- 1; ## ---------------------------------------------------------------------------- diff --git a/lib/CIL/Base.pm b/lib/CIL/Base.pm index feb7dfc..681a544 100644 --- a/lib/CIL/Base.pm +++ b/lib/CIL/Base.pm @@ -25,6 +25,7 @@ use strict; use warnings; use Carp; use DateTime; +use CIL::Utils; use base qw(Class::Accessor); __PACKAGE__->mk_accessors(qw(CreatedBy Inserted Updated)); @@ -87,6 +88,30 @@ sub new_from_fh { return $class->new_from_data( $name, $data ); } +sub set_data { + my ($self, $data) = @_; + + # loop through all the allowed fields + my $fields = $self->fields(); + my $array_fields = $self->array_fields(); + + # save each field + foreach my $field ( @$fields ) { + next unless defined $data->{$field}; + + # make it an array if it should be one + if ( exists $array_fields->{$field} and ref $data->{$field} ne 'ARRAY' ) { + $data->{$field} = [ $data->{$field} ]; + } + + # modify the data directly, otherwise Updated will kick in + $self->set_no_update($field, $data->{$field}); + } + $self->set_no_update('Changed', 1); + + $self->{data} = $data; +} + sub save { my ($self, $cil) = @_; @@ -96,12 +121,18 @@ sub save { CIL::Utils->write_cil_file( $filename, $self->{data}, @$fields ); } +sub as_output { + my ($self) = @_; + my $fields = $self->fields(); + return CIL::Utils->format_data_as_output( $self->{data}, @$fields ); +} + sub create_filename { my ($class, $cil, $name) = @_; # create the filename from it's parts my $prefix = $class->prefix(); - my $issue_dir = $cil->issue_dir; + my $issue_dir = $cil->IssueDir; my $filename = "${issue_dir}/${prefix}_${name}.cil"; return $filename; @@ -184,6 +215,14 @@ sub name { return $self->{name}; } +sub error { + my $self = shift; + if( @_ ) { + $self->{error} = $_[0]; + } + return $self->{error}; +} + ## ---------------------------------------------------------------------------- 1; ## ---------------------------------------------------------------------------- diff --git a/lib/CIL/Comment.pm b/lib/CIL/Comment.pm index 9d0398c..362f094 100644 --- a/lib/CIL/Comment.pm +++ b/lib/CIL/Comment.pm @@ -75,6 +75,14 @@ sub last_field { return 'Description'; } +sub is_valid { + # ToDo: + # * check that the issue is valid + # * Inserted and Updated are valid + # * Description has something in it + return 1; +} + ## ---------------------------------------------------------------------------- 1; ## ---------------------------------------------------------------------------- diff --git a/lib/CIL/Issue.pm b/lib/CIL/Issue.pm index 13f3435..6683860 100644 --- a/lib/CIL/Issue.pm +++ b/lib/CIL/Issue.pm @@ -90,6 +90,37 @@ sub last_field { return 'Description'; } +sub is_valid { + my ($self, $cil) = @_; + + # issues should have a Summary + unless ( defined defined $self->Summary and length $self->Summary ) { + $self->error( 'You must provide a summary.' ); + return; + } + + # see if we only allow certain Statuses + if ( $cil->StatusStrict ) { + unless ( exists $cil->StatusAllowed()->{$self->Status} ) { + $self->error( "You have 'StatusStrict' turned on but this status (" . $self->Status . ") is not in the 'StatusAllowedList'" ); + return; + } + } + + # see if we only allow certain Labels + if ( $cil->LabelStrict ) { + my @labels = @{$self->Labels}; + foreach my $label ( @labels ) { + unless ( exists $cil->LabelAllowed()->{$label} ) { + $self->error( "You have 'LabelStrict' turned on but this label ($label) is not in the 'LabelAllowedList'" ); + return; + } + } + } + + return 1; +} + sub add_label { my ($self, $label) = @_; @@ -124,11 +155,6 @@ sub add_attachment { $self->flag_as_updated(); } -sub as_output { - my ($self) = @_; - return CIL::Utils->format_data_as_output( $self->{data}, @FIELDS ); -} - sub Labels { my ($self) = @_; return $self->{data}{Label}; diff --git a/lib/CIL/Utils.pm b/lib/CIL/Utils.pm index a0e165c..fa43d2e 100644 --- a/lib/CIL/Utils.pm +++ b/lib/CIL/Utils.pm @@ -76,8 +76,9 @@ sub parse_from_lines { } } - # now read everything that's left into the $last_field field - $data->{$last_field} = join("\n", @lines); + # now read everything that's left into the $last_field field (if there is one) + $data->{$last_field} = join("\n", @lines) + if defined $last_field; return $data; } @@ -128,6 +129,8 @@ sub write_cil_file { sub solicit { my ($class, $message) = @_; + $message = join('', @$message) if ref $message eq 'ARRAY'; + # when calling this, assume we're already interactive File::Temp->safe_level(File::Temp::HIGH); -- 2.39.5