diff options
author | Francois Marier <francois@debian.org> | 2010-08-05 20:52:16 -0400 |
---|---|---|
committer | Francois Marier <francois@debian.org> | 2010-08-05 20:52:16 -0400 |
commit | 9fcb3bc29dfd429f521c4e40452197dc364310c3 (patch) | |
tree | d343c4aeb67a1cc4b00dfebf873937aa9cccf12a /lib/CIL/Utils.pm | |
parent | 1515145646c5aa80eb4c298607ea33da731ab586 (diff) |
Imported Upstream version 0.07.00upstream/0.07.00
Diffstat (limited to 'lib/CIL/Utils.pm')
-rw-r--r-- | lib/CIL/Utils.pm | 388 |
1 files changed, 386 insertions, 2 deletions
diff --git a/lib/CIL/Utils.pm b/lib/CIL/Utils.pm index 47f7ada..cad802f 100644 --- a/lib/CIL/Utils.pm +++ b/lib/CIL/Utils.pm @@ -29,11 +29,13 @@ use File::Temp qw(tempfile); use Email::Find; use POSIX qw(getpgrp tcgetpgrp); use Fcntl qw(:DEFAULT :flock); +use Digest::MD5 qw(md5_hex); ## ---------------------------------------------------------------------------- # setup some globals my $editor = $ENV{EDITOR} || 'vi'; +my $y = 'y'; ## ---------------------------------------------------------------------------- @@ -76,7 +78,7 @@ sub parse_from_lines { $data->{$key} = $value; } } - + # 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; @@ -124,6 +126,9 @@ sub write_cil_file { write_file($filename, $lines); } +## ---------------------------------------------------------------------------- +# input + # this method based on Term::CallEditor(v0.11)'s solicit method # original: Copyright 2004 by Jeremy Mates # copied under the terms of the GPL @@ -149,7 +154,8 @@ sub solicit { flock $fh, LOCK_UN; # run the editor - my $status = system($editor, $filename); + my @editor_args = split(/\s+/, $editor); + my $status = system(@editor_args, $filename); # check its return value if ( $status != 0 ) { @@ -183,6 +189,379 @@ sub ensure_interactive { return; } +sub add_issue_loop { + my ($class, $cil, undef, $issue) = @_; + + 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 = $class->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 { + $class->msg($_) foreach @{ $issue->errors }; + $edit = ans('Would you like to re-edit (y/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 = time . $issue->Inserted . $issue->Summary . $issue->Description; + $issue->set_name( substr(md5_hex($unique_str), 0, 8) ); + $issue->save($cil); + + # should probably be run from with $cil + $cil->run_hook('issue_post_save', $issue); + + $class->display_issue($cil, $issue); + + return $issue; +} + +sub add_comment_loop { + my ($class, $cil, undef, $issue, $comment) = @_; + + 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 { + $class->msg($_) foreach @{ $issue->errors }; + $edit = $class->ans('Would you like to re-edit (y/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 = time . $comment->Inserted . $issue->Description; + $comment->set_name( substr(md5_hex($unique_str), 0, 8) ); + + # finally, save it + $comment->save($cil); + + # add the comment to the issue, update it's timestamp and save it out + $issue->add_comment( $comment ); + $issue->save($cil); + $class->display_issue_full($cil, $issue); + + return $comment; +} + +## ---------------------------------------------------------------------------- +# loading + +sub load_issue_fuzzy { + my ($class, $cil, $partial_name) = @_; + + my $issues = $cil->list_issues_fuzzy( $partial_name ); + unless ( defined $issues ) { + $class->fatal("Couldn't find any issues using '$partial_name'"); + } + + if ( @$issues > 1 ) { + $class->fatal('found multiple issues which match that name: ' . join(' ', map { $_->{name} } @$issues)); + } + + my $issue_name = $issues->[0]->{name}; + my $issue = CIL::Issue->new_from_name($cil, $issue_name); + unless ( defined $issue ) { + $class->fatal("Couldn't load issue '$issue_name'"); + } + + return $issue; +} + +sub load_comment_fuzzy { + my ($class, $cil, $partial_name) = @_; + + my $comments = $cil->list_comments_fuzzy( $partial_name ); + unless ( defined $comments ) { + $class->fatal("Couldn't find any comments using '$partial_name'"); + } + + if ( @$comments > 1 ) { + $class->fatal('found multiple comments which match that name: ' . join(' ', map { $_->{name} } @$comments)); + } + + my $comment_name = $comments->[0]->{name}; + my $comment = CIL::comment->new_from_name($cil, $comment_name); + unless ( defined $comment ) { + $class->fatal("Couldn't load comment '$comment_name'"); + } + + return $comment; +} + +sub load_attachment_fuzzy { + my ($class, $cil, $partial_name) = @_; + + my $attachments = $cil->list_attachments_fuzzy( $partial_name ); + unless ( defined $attachments ) { + $class->fatal("Couldn't find any attachments using '$partial_name'"); + } + + if ( @$attachments > 1 ) { + $class->fatal('found multiple attachments which match that name: ' . join(' ', map { $_->{name} } @$attachments)); + } + + my $attachment_name = $attachments->[0]->{name}; + my $attachment = CIL::Attachment->new_from_name($cil, $attachment_name); + unless ( defined $attachment ) { + $class->fatal("Couldn't load attachment '$partial_name'"); + } + + return $attachment; +} + +## ---------------------------------------------------------------------------- +# display + +sub display_issue { + my ($class, $cil, $issue) = @_; + + $class->separator(); + $class->title( 'Issue ' . $issue->name() ); + $class->field( 'Summary', $issue->Summary() ); + $class->field( 'Status', $issue->Status() ); + $class->field( 'CreatedBy', $issue->CreatedBy() ); + $class->field( 'AssignedTo', $issue->AssignedTo() ); + $class->field( 'Label', $_ ) + foreach sort @{$issue->LabelList()}; + $class->field( 'Comment', $_ ) + foreach sort @{$issue->CommentList()}; + $class->field( 'Attachment', $_ ) + foreach sort @{$issue->AttachmentList()}; + $class->field( 'DependsOn', $_ ) + foreach sort @{$issue->DependsOnList()}; + $class->field( 'Precedes', $_ ) + foreach sort @{$issue->PrecedesList()}; + $class->field( 'Inserted', $issue->Inserted() ); + $class->field( 'Updated', $issue->Inserted() ); + $class->text('Description', $issue->Description()); + $class->separator(); +} + +sub display_issue_full { + my ($class, $cil, $issue) = @_; + + $class->separator(); + $class->title( 'Issue ' . $issue->name() ); + $class->field( 'Summary', $issue->Summary() ); + $class->field( 'Status', $issue->Status() ); + $class->field( 'CreatedBy', $issue->CreatedBy() ); + $class->field( 'AssignedTo', $issue->AssignedTo() ); + $class->field( 'Label', $_ ) + foreach sort @{$issue->Label()}; + $class->field( 'DependsOn', $_ ) + foreach sort @{$issue->DependsOnList()}; + $class->field( 'Precedes', $_ ) + foreach sort @{$issue->PrecedesList()}; + $class->field( 'Inserted', $issue->Inserted() ); + $class->field( 'Updated', $issue->Updated() ); + $class->text('Description', $issue->Description()); + + my $comments = $cil->get_comments_for( $issue ); + foreach my $comment ( @$comments ) { + $class->display_comment( $cil, $comment ); + } + + my $attachments = $cil->get_attachments_for( $issue ); + foreach my $attachment ( @$attachments ) { + $class->display_attachment( $cil, $attachment ); + $class->msg(); + } + + $class->separator(); +} + +sub display_comment { + my ($class, $cil, $comment) = @_; + + $class->title( 'Comment ' . $comment->name() ); + $class->field( 'CreatedBy', $comment->CreatedBy() ); + $class->field( 'Inserted', $comment->Inserted() ); + $class->field( 'Updated', $comment->Inserted() ); + $class->text('Description', $comment->Description()); +} + +sub display_attachment { + my ($class, $cil, $attachment) = @_; + + $class->title( 'Attachment ' . $attachment->name() ); + $class->field( 'Filename', $attachment->Filename() ); + $class->field( 'CreatedBy', $attachment->CreatedBy() ); + $class->field( 'Inserted', $attachment->Inserted() ); + $class->field( 'Updated', $attachment->Inserted() ); +} + +sub filter_issues { + my ($class, $cil, $issues, $args) = @_; + + # don't filter if we haven't been given anything + return $issues unless defined $args; + return $issues unless %$args; + + # check that they aren't filtering on both --assigned-to and --is-mine + if ( defined $args->{a} and defined $args->{'is-mine'} ) { + $class->fatal("the --assigned-to and --is-mine filters are mutually exclusive"); + } + + # take a copy of the whole lot first (so we don't destroy the input list) + my @new_issues = @$issues; + + # firstly, get out the Statuses we want + if ( defined $args->{s} ) { + @new_issues = grep { $_->Status eq $args->{s} } @new_issues; + } + + # then see if we want a particular label (could be a bit nicer) + if ( defined $args->{l} ) { + my @tmp; + foreach my $issue ( @new_issues ) { + push @tmp, $issue + if grep { $_ eq $args->{l} } @{$issue->LabelList}; + } + @new_issues = @tmp; + } + + # filter out dependent on open/closed + if ( defined $args->{'is-open'} ) { + # just get the open issues + @new_issues = grep { $_->is_open($cil) } @new_issues; + } + if ( defined $args->{'is-closed'} ) { + # just get the closed issues + @new_issues = grep { $_->is_closed($cil) } @new_issues; + } + + # filter out 'created by' + if ( defined $args->{c} ) { + @new_issues = grep { $args->{c} eq $_->created_by_email } @new_issues; + } + + # filter out 'assigned to' + $args->{a} = $cil->UserEmail + if defined $args->{'is-mine'}; + if ( defined $args->{a} ) { + @new_issues = grep { $args->{a} eq $_->assigned_to_email } @new_issues; + } + + return \@new_issues; +} + +sub separator { + my ($class) = @_; + $class->msg('=' x 79); +} + +sub msg { + my ($class, $msg) = @_; + print ( defined $msg ? $msg : '' ); + print "\n"; +} + +sub display_issue_summary { + my ($class, $issue) = @_; + + my $msg = $issue->name(); + $msg .= " "; + $msg .= $issue->Status(); + $msg .= (' ' x ( 13 - length $issue->Status() )); + $msg .= $issue->Summary(); + + $class->msg($msg); +} + +sub display_issue_headers { + my ($class, $issue) = @_; + + $class->title( 'Issue ' . $issue->name() ); + $class->field( 'Summary', $issue->Summary() ); + $class->field( 'CreatedBy', $issue->CreatedBy() ); + $class->field( 'AssignedTo', $issue->AssignedTo() ); + $class->field( 'Inserted', $issue->Inserted() ); + $class->field( 'Status', $issue->Status() ); + $class->field( 'Labels', join(' ', @{$issue->LabelList()}) ); + $class->field( 'DependsOn', join(' ', @{$issue->DependsOnList()}) ); + $class->field( 'Precedes', join(' ', @{$issue->PrecedesList()}) ); +} + +sub title { + my ($class, $title) = @_; + my $msg = "--- $title "; + $msg .= '-' x (74 - length($title)); + $class->msg($msg); +} + +sub field { + my ($class, $field, $value) = @_; + my $msg = "$field"; + $msg .= " " x (12 - length($field)); + $class->msg("$msg: " . (defined $value ? $value : '') ); +} + +sub text { + my ($class, $field, $value) = @_; + $class->msg(); + $class->msg($value); + $class->msg(); +} + +## ---------------------------------------------------------------------------- +# system + +sub check_paths { + my ($class, $cil) = @_; + + # make sure an issue directory is available + unless ( $cil->dir_exists($cil->IssueDir) ) { + $class->fatal("couldn't find '" . $cil->IssueDir . "' directory"); + } +} + +sub ans { + my ($msg) = @_; + print $msg; + my $ans = <STDIN>; + chomp $ans; + print "\n"; + return $ans; +} + +sub err { + my ($class, $msg) = @_; + print STDERR ( defined $msg ? $msg : '' ); + print STDERR "\n"; +} + +sub fatal { + my ($class, $msg) = @_; + chomp $msg; + print STDERR $msg, "\n"; + exit 2; +} + +## ---------------------------------------------------------------------------- +# helpers + sub extract_email_address { my ($class, $text) = @_; @@ -198,6 +577,11 @@ sub extract_email_address { return $email_address; } +sub user { + my ($class, $cil) = @_; + return $cil->UserName . ' <' . $cil->UserEmail . '>'; +} + ## ---------------------------------------------------------------------------- 1; ## ---------------------------------------------------------------------------- |