diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/CIL.pm | 100 | ||||
-rw-r--r-- | lib/CIL/Base.pm | 47 | ||||
-rw-r--r-- | lib/CIL/Comment.pm | 8 | ||||
-rw-r--r-- | lib/CIL/Issue.pm | 63 | ||||
-rw-r--r-- | lib/CIL/Utils.pm | 23 |
5 files changed, 224 insertions, 17 deletions
@@ -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 { @@ -50,21 +58,39 @@ sub new { return $self; } -sub list_issues { - my ($self) = @_; +sub list_entities { + my ($self, $prefix) = @_; - my $globpath = $self->issue_dir . "/i_*.cil"; + my $globpath = $self->IssueDir . "/${prefix}_*.cil"; my @filenames = bsd_glob($globpath); - my @issues; + my @entities; foreach my $filename ( sort @filenames ) { - my ($name) = $filename =~ m{/i_(.*)\.cil$}xms; - push @issues, { + my ($name) = $filename =~ m{/${prefix}_(.*)\.cil$}xms; + push @entities, { name => $name, filename => $filename, }; } - return \@issues; + return \@entities; +} + +sub list_issues { + my ($self) = @_; + + return $self->list_entities('i'); +} + +sub list_comments { + my ($self) = @_; + + return $self->list_entities('c'); +} + +sub list_attachments { + my ($self) = @_; + + return $self->list_entities('a'); } sub get_issues { @@ -79,6 +105,30 @@ sub get_issues { return \@issues; } +sub get_comments { + my ($self) = @_; + + my $comment_list = $self->list_comments(); + + my @comments; + foreach my $comment ( @$comment_list ) { + push @comments, CIL::Comment->new_from_name( $self, $comment->{name} ); + } + return \@comments; +} + +sub get_attachments { + my ($self) = @_; + + my $attachment_list = $self->list_attachments(); + + my @attachments; + foreach my $attachment ( @$attachment_list ) { + push @attachments, CIL::Attachment->new_from_name( $self, $attachment->{name} ); + } + return \@attachments; +} + sub get_comments_for { my ($self, $issue) = @_; @@ -109,6 +159,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 ed5c3a8..f9b932f 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; @@ -125,7 +156,7 @@ sub set { # finish if both are defined and they're the same if ( defined $orig and defined $value ) { - return if eval { $orig eq $value }; + return if $orig eq $value; } # finish if neither are defined @@ -147,7 +178,7 @@ sub set_no_update { sub set_inserted_now { my ($self) = @_; - my $time = DateTime->now; + my $time = DateTime->now->iso8601; $self->{data}{Inserted} = $time; $self->{data}{Updated} = $time; $self->{Changed} = 1; @@ -155,7 +186,7 @@ sub set_inserted_now { sub set_updated_now { my ($self) = @_; - my $time = DateTime->now; + my $time = DateTime->now->iso8601; $self->{data}{Updated} = $time; $self->{Changed} = 1; } @@ -184,6 +215,14 @@ sub name { return $self->{name}; } +sub errors { + my $self = shift; + if( @_ ) { + $self->{errors} = $_[0]; + } + return $self->{errors}; +} + ## ---------------------------------------------------------------------------- 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 0dfaf53..d44626e 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) = @_; + + my @errors; + + # issues should have a Summary + unless ( defined defined $self->Summary and length $self->Summary ) { + push @errors, 'Issue does not have a summary'; + } + + # see if we only allow certain Statuses + if ( $cil->StatusStrict ) { + unless ( exists $cil->StatusAllowed()->{$self->Status} ) { + push @errors, "StatusStrict is turned on but this issue has an invalid status '" . $self->Status . "'"; + } + } + + # see if we only allow certain Labels + if ( $cil->LabelStrict ) { + my @labels = @{$self->Labels}; + foreach my $label ( @labels ) { + unless ( exists $cil->LabelAllowed()->{$label} ) { + push @errors, "LabelStrict is turned on but this issue has an invalid label '$label'"; + } + } + } + + $self->errors( \@errors ); + return @errors ? 0 : 1; +} + sub add_label { my ($self, $label) = @_; @@ -124,9 +155,9 @@ sub add_attachment { $self->flag_as_updated(); } -sub as_output { +sub Labels { my ($self) = @_; - return CIL::Utils->format_data_as_output( $self->{data}, @FIELDS ); + return $self->{data}{Label}; } sub Comments { @@ -139,6 +170,34 @@ sub Attachments { return $self->{data}{Attachment}; } +sub is_open { + my ($self, $cil) = @_; + + # check against the list of Open Statuses + my $open = $cil->StatusOpen(); + return exists $open->{$self->Status}; +} + +sub is_closed { + my ($self, $cil) = @_; + + # check against the list of Closed Statuses + my $closed = $cil->StatusClosed(); + return exists $closed->{$self->Status}; +} + +sub assigned_to_email { + my ($self) = @_; + + return CIL::Utils->extract_email_address( $self->AssignedTo ); +} + +sub created_by_email { + my ($self) = @_; + + return CIL::Utils->extract_email_address( $self->CreatedBy ); +} + ## ---------------------------------------------------------------------------- 1; ## ---------------------------------------------------------------------------- diff --git a/lib/CIL/Utils.pm b/lib/CIL/Utils.pm index a0e165c..e9611cf 100644 --- a/lib/CIL/Utils.pm +++ b/lib/CIL/Utils.pm @@ -26,6 +26,7 @@ use warnings; use Carp; use File::Slurp; use File::Temp qw(tempfile); +use Email::Find; use POSIX qw(getpgrp tcgetpgrp); use Fcntl qw(:DEFAULT :flock); @@ -76,8 +77,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 +130,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); @@ -179,6 +183,21 @@ sub ensure_interactive { return; } +sub extract_email_address { + my ($class, $text) = @_; + + my $email_address; + my $num_found = find_emails( + $text, + sub { + my ($mail_address, $text_email) = @_; + $email_address = $text_email; + } + ); + + return $email_address; +} + ## ---------------------------------------------------------------------------- 1; ## ---------------------------------------------------------------------------- |