summaryrefslogtreecommitdiff
path: root/lib/CIL/Command
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CIL/Command')
-rw-r--r--lib/CIL/Command/Add.pm65
-rw-r--r--lib/CIL/Command/Am.pm140
-rw-r--r--lib/CIL/Command/Attach.pm88
-rw-r--r--lib/CIL/Command/Comment.pm63
-rw-r--r--lib/CIL/Command/DependsOn.pm61
-rw-r--r--lib/CIL/Command/Edit.pm84
-rw-r--r--lib/CIL/Command/Extract.pm45
-rw-r--r--lib/CIL/Command/Fsck.pm185
-rw-r--r--lib/CIL/Command/Init.pm108
-rw-r--r--lib/CIL/Command/Label.pm82
-rw-r--r--lib/CIL/Command/List.pm55
-rw-r--r--lib/CIL/Command/Precedes.pm62
-rw-r--r--lib/CIL/Command/Show.pm42
-rw-r--r--lib/CIL/Command/Status.pm71
-rw-r--r--lib/CIL/Command/Steal.pm59
-rw-r--r--lib/CIL/Command/Summary.pm55
-rw-r--r--lib/CIL/Command/Track.pm51
-rw-r--r--lib/CIL/Command/Work.pm64
18 files changed, 1380 insertions, 0 deletions
diff --git a/lib/CIL/Command/Add.pm b/lib/CIL/Command/Add.pm
new file mode 100644
index 0000000..76b1785
--- /dev/null
+++ b/lib/CIL/Command/Add.pm
@@ -0,0 +1,65 @@
+## ----------------------------------------------------------------------------
+# cil is a Command line Issue List
+# Copyright (C) 2008 Andrew Chilton
+#
+# This file is part of 'cil'.
+#
+# cil is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+## ----------------------------------------------------------------------------
+
+package CIL::Command::Add;
+
+use strict;
+use warnings;
+
+use base qw(CIL::Command);
+
+## ----------------------------------------------------------------------------
+
+sub name { 'add' }
+
+sub run {
+ my ($self, $cil, $args, @argv) = @_;
+
+ CIL::Utils->ensure_interactive();
+
+ my $user = CIL::Utils->user($cil);
+
+ my $issue = CIL::Issue->new('tmpname');
+ $issue->Summary( join ' ', @argv );
+ $issue->Status($cil->DefaultNewStatus);
+ $issue->CreatedBy( $user );
+ $issue->AssignedTo( $user )
+ if ( $args->{mine} or $cil->AutoAssignSelf );
+ $issue->Description("Description ...");
+
+ $issue = CIL::Utils->add_issue_loop($cil, undef, $issue);
+
+ if ( $cil->UseGit ) {
+ # if we want to add or commit this issue
+ if ( $args->{add} or $args->{commit} ) {
+ $cil->git->add( $cil, $issue );
+ }
+
+ # if we want to commit this issue
+ if ( $args->{commit} ) {
+ $cil->git->commit( $cil, 'New Issue', $issue );
+ }
+ }
+}
+
+1;
+
+## ----------------------------------------------------------------------------
diff --git a/lib/CIL/Command/Am.pm b/lib/CIL/Command/Am.pm
new file mode 100644
index 0000000..5b763ea
--- /dev/null
+++ b/lib/CIL/Command/Am.pm
@@ -0,0 +1,140 @@
+## ----------------------------------------------------------------------------
+# cil is a Command line Issue List
+# Copyright (C) 2008 Andrew Chilton
+#
+# This file is part of 'cil'.
+#
+# cil is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+## ----------------------------------------------------------------------------
+
+package CIL::Command::Am;
+
+use strict;
+use warnings;
+
+use File::Slurp qw(read_file write_file);
+use Email::Date qw(find_date);
+use base qw(CIL::Command);
+
+## ----------------------------------------------------------------------------
+
+sub name { 'am' }
+
+sub run {
+ my ($self, $cil, $args, $email_filename) = @_;
+
+ unless ( -r $email_filename ) {
+ CIL::Utils::fatal("couldn't load email '$email_filename'");
+ }
+
+ my $msg_text = read_file($email_filename);
+
+ my $email = Email::Simple->new($msg_text);
+ unless ( defined $email ) {
+ CIL::Utils::fatal("email file '$email_filename' didn't look like an email");
+ }
+
+ # extract some fields
+ my $subject = $email->header('Subject');
+ my $from = $email->header('From');
+ my $date = find_date($email)->datetime;
+ my $body = $email->body;
+
+ # see if we can find any issue names in either the subject or the body
+ my @issue_names;
+ foreach my $text ( $subject, $body ) {
+ my @new = ( $text =~ /\b\#?([0-9a-f]{8})\b/gxms );
+ push @issue_names, @new;
+ }
+
+ CIL::Utils->msg("Found possible issue names in email: ", ( join(' ', @issue_names) || '[none]' ));
+
+ my %issue;
+ foreach ( @issue_names ) {
+ my $i = eval { CIL::Issue->new_from_name($cil, $_) };
+ next unless defined $i;
+
+ $issue{$i->name} = $i;
+ }
+
+ if ( keys %issue ) {
+ CIL::Utils->msg( "Found actual issues: " . (join(' ', keys %issue)) );
+
+ # create the new comment
+ my $comment = CIL::Comment->new('tmpname');
+ $comment->Issue( '...' );
+ $comment->CreatedBy( $from );
+ $comment->Inserted( $date );
+ # $comment->Updated( $date );
+ $comment->Description( $body );
+
+ # display
+ CIL::Utils->display_comment($cil, $comment);
+
+ # found at least one issue, so this might be a comment
+ my $issue;
+ if ( keys %issue == 1 ) {
+ $issue = (values %issue)[0];
+ }
+ else {
+ if ( $args->{batch} ) {
+ CIL::Utils->fatal('Cannot add to an existing message (in batch mode) when there are multiple matched messages!');
+ }
+ my $ans = CIL::Utils::ans('To which issue would you like to add this comment: ');
+
+ # ToDo: decide whether we let them choose an arbitrary issue, for
+ # now quit unless they choose one from the list
+ return unless exists $issue{$ans};
+
+ # got a valid issue_name, so set the parent name
+ $issue = $issue{$ans};
+ }
+
+ # set the parent issue
+ $comment->Issue( $issue->name );
+
+ CIL::Utils->add_comment_loop($cil, undef, $issue, $comment);
+ }
+ else {
+ CIL::Utils->msg("Couldn't find reference to any issues in the email.");
+
+ # no issue found so make up the issue first
+ my $issue = CIL::Issue->new('tmpname');
+ $issue->Summary( $subject );
+ $issue->Status($cil->DefaultNewStatus);
+ $issue->CreatedBy( $from );
+ $issue->AssignedTo( CIL::Utils->user($cil) );
+ $issue->Inserted( $date );
+ $issue->Updated( $date );
+ $issue->Description( $body );
+
+ # display
+ CIL::Utils->display_issue_full($cil, $issue);
+
+ # then ask if the user would like to add it
+ CIL::Utils->msg("Couldn't find any likely issues, so this might be a new one.");
+ if ( $args->{batch} ) {
+ CIL::Utils->msg('Running in batch mode, so just adding mail as a new issue');
+ } else {
+ my $ans = CIL::Utils::ans('Would you like to add this message as an issue shown above (y/n): ');
+ return unless $ans eq 'y';
+ }
+
+ CIL::Utils->add_issue_loop($cil, undef, $issue);
+ }
+}
+
+1;
+## ----------------------------------------------------------------------------
diff --git a/lib/CIL/Command/Attach.pm b/lib/CIL/Command/Attach.pm
new file mode 100644
index 0000000..f114614
--- /dev/null
+++ b/lib/CIL/Command/Attach.pm
@@ -0,0 +1,88 @@
+## ----------------------------------------------------------------------------
+# cil is a Command line Issue List
+# Copyright (C) 2008 Andrew Chilton
+#
+# This file is part of 'cil'.
+#
+# cil is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+## ----------------------------------------------------------------------------
+
+package CIL::Command::Attach;
+
+use strict;
+use warnings;
+
+use base qw(CIL::Command);
+use File::Basename;
+use File::Slurp;
+use Digest::MD5 qw(md5_hex);
+
+## ----------------------------------------------------------------------------
+
+sub name { 'attach' }
+
+sub run {
+ my ($self, $cil, undef, $issue_name, $filename) = @_;
+
+ my $issue = CIL::Utils->load_issue_fuzzy( $cil, $issue_name );
+
+ # check to see if the file exists
+ unless ( -r $filename ) {
+ $cil->fatal("couldn't read file '$filename'");
+ }
+
+ my $basename = basename( $filename );
+ my $user = CIL::Utils->user($cil);
+
+ my $add_attachment_text = <<"EOF";
+Filename : $basename
+CreatedBy : $user
+
+File goes here ... this will be overwritten.
+EOF
+
+ # read in the new issue text
+ CIL::Utils->ensure_interactive();
+ my $fh = CIL::Utils->solicit( $add_attachment_text );
+
+ my $attachment = CIL::Attachment->new_from_fh( 'tmp', $fh );
+ unless ( defined $attachment ) {
+ $cil->fatal("could not create new attachment");
+ }
+
+ # now add the file itself
+ my $contents = read_file( $filename );
+ $attachment->set_file_contents( $contents );
+
+ # set the size
+ my ($size) = (stat($filename))[7];
+ $attachment->Size( $size );
+
+ # we've got the attachment, so let's name it
+ my $unique_str = time . $attachment->Inserted . $attachment->File;
+ $attachment->set_name( substr(md5_hex($unique_str), 0, 8) );
+
+ # finally, tell it who it's parent is and then save
+ $attachment->Issue( $issue->name );
+ $attachment->save($cil);
+
+ # add the comment to the issue, update it's timestamp and save it out
+ $issue->add_attachment( $attachment );
+ $issue->save($cil);
+ CIL::Utils->display_issue_full($cil, $issue);
+}
+
+1;
+## ----------------------------------------------------------------------------
diff --git a/lib/CIL/Command/Comment.pm b/lib/CIL/Command/Comment.pm
new file mode 100644
index 0000000..0942982
--- /dev/null
+++ b/lib/CIL/Command/Comment.pm
@@ -0,0 +1,63 @@
+## ----------------------------------------------------------------------------
+# cil is a Command line Issue List
+# Copyright (C) 2008 Andrew Chilton
+#
+# This file is part of 'cil'.
+#
+# cil is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+## ----------------------------------------------------------------------------
+
+package CIL::Command::Comment;
+
+use strict;
+use warnings;
+
+use base qw(CIL::Command);
+
+## ----------------------------------------------------------------------------
+
+sub name { 'comment' }
+
+sub run {
+ my ($self, $cil, $args, $issue_name) = @_;
+
+ my $issue = CIL::Utils->load_issue_fuzzy( $cil, $issue_name );
+
+ CIL::Utils->ensure_interactive();
+
+ # create the new comment
+ my $comment = CIL::Comment->new('tmpname');
+ $comment->Issue( $issue->name );
+ $comment->CreatedBy( CIL::Utils->user($cil) );
+ $comment->Description("Description ...");
+
+ $comment = CIL::Utils->add_comment_loop($cil, undef, $issue, $comment);
+
+ if ( $cil->UseGit ) {
+ # if we want to add or commit this comment
+ if ( $args->{add} or $args->{commit} ) {
+ $cil->git->add( $cil, $issue );
+ $cil->git->add( $cil, $comment );
+ }
+
+ # if we want to commit this comment
+ if ( $args->{commit} ) {
+ $cil->git->commit( $cil, 'New Comment', $issue, $comment );
+ }
+ }
+}
+
+1;
+## ----------------------------------------------------------------------------
diff --git a/lib/CIL/Command/DependsOn.pm b/lib/CIL/Command/DependsOn.pm
new file mode 100644
index 0000000..1df5f19
--- /dev/null
+++ b/lib/CIL/Command/DependsOn.pm
@@ -0,0 +1,61 @@
+## ----------------------------------------------------------------------------
+# cil is a Command line Issue List
+# Copyright (C) 2008 Andrew Chilton
+#
+# This file is part of 'cil'.
+#
+# cil is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+## ----------------------------------------------------------------------------
+
+package CIL::Command::DependsOn;
+
+use strict;
+use warnings;
+
+use base qw(CIL::Command);
+
+## ----------------------------------------------------------------------------
+
+sub name { 'depends-on' }
+
+sub run {
+ my ($self, $cil, $args, $issue_name, $depends_name) = @_;
+
+ my $issue = CIL::Utils->load_issue_fuzzy($cil, $issue_name);
+ my $depends = CIL::Utils->load_issue_fuzzy($cil, $depends_name);
+
+ $issue->add_depends_on( $depends->name );
+ $depends->add_precedes( $issue->name );
+
+ $issue->save($cil);
+ $depends->save($cil);
+
+ if ( $cil->UseGit ) {
+ # if we want to add or commit this change
+ if ( $args->{add} or $args->{commit} ) {
+ $cil->git->add( $cil, $issue );
+ $cil->git->add( $cil, $depends );
+ }
+
+ # if we want to commit this change
+ if ( $args->{commit} ) {
+ my $message = 'Issue ' . $issue->name . ' has a new dependent ' . $depends->name;
+ $cil->git->commit_multiple( $cil, $message, $issue, $depends );
+ }
+ }
+}
+
+1;
+## ----------------------------------------------------------------------------
diff --git a/lib/CIL/Command/Edit.pm b/lib/CIL/Command/Edit.pm
new file mode 100644
index 0000000..2f7a7e0
--- /dev/null
+++ b/lib/CIL/Command/Edit.pm
@@ -0,0 +1,84 @@
+## ----------------------------------------------------------------------------
+# cil is a Command line Issue List
+# Copyright (C) 2008 Andrew Chilton
+#
+# This file is part of 'cil'.
+#
+# cil is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+## ----------------------------------------------------------------------------
+
+package CIL::Command::Edit;
+
+use strict;
+use warnings;
+
+use base qw(CIL::Command);
+
+## ----------------------------------------------------------------------------
+
+my $y = 'y';
+
+## ----------------------------------------------------------------------------
+
+sub name { 'edit' }
+
+sub run {
+ my ($self, $cil, $args, $issue_name) = @_;
+
+ my $issue = CIL::Utils->load_issue_fuzzy( $cil, $issue_name );
+
+ CIL::Utils->ensure_interactive();
+
+ 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 {
+ CIL::Utils->msg($_) foreach @{ $issue->errors };
+ $edit = CIL::Utils::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 );
+
+ # save it
+ $issue->save($cil);
+
+ if ( $cil->UseGit ) {
+ # if we want to add or commit this issue
+ if ( $args->{add} or $args->{commit} ) {
+ $cil->git->add( $cil, $issue );
+ }
+
+ # if we want to commit this issue
+ if ( $args->{commit} ) {
+ $cil->git->commit( $cil, 'Issue Edited', $issue );
+ }
+ }
+
+ CIL::Utils->display_issue($cil, $issue);
+}
+
+1;
+## ----------------------------------------------------------------------------
diff --git a/lib/CIL/Command/Extract.pm b/lib/CIL/Command/Extract.pm
new file mode 100644
index 0000000..03df451
--- /dev/null
+++ b/lib/CIL/Command/Extract.pm
@@ -0,0 +1,45 @@
+## ----------------------------------------------------------------------------
+# cil is a Command line Issue List
+# Copyright (C) 2008 Andrew Chilton
+#
+# This file is part of 'cil'.
+#
+# cil is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+## ----------------------------------------------------------------------------
+
+package CIL::Command::Extract;
+
+use strict;
+use warnings;
+
+use base qw(CIL::Command);
+use File::Slurp qw(write_file);
+
+## ----------------------------------------------------------------------------
+
+sub name { 'extract' }
+
+sub run {
+ my ($self, $cil, $args, $attachment_name) = @_;
+
+ my $attachment = CIL::Utils->load_attachment_fuzzy($cil, $attachment_name);
+
+ my $filename = $args->{f} || $attachment->Filename();
+ write_file( $filename, $attachment->as_binary );
+}
+
+1;
+
+## ----------------------------------------------------------------------------
diff --git a/lib/CIL/Command/Fsck.pm b/lib/CIL/Command/Fsck.pm
new file mode 100644
index 0000000..2c48b36
--- /dev/null
+++ b/lib/CIL/Command/Fsck.pm
@@ -0,0 +1,185 @@
+## ----------------------------------------------------------------------------
+# cil is a Command line Issue List
+# Copyright (C) 2008 Andrew Chilton
+#
+# This file is part of 'cil'.
+#
+# cil is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+## ----------------------------------------------------------------------------
+
+package CIL::Command::Fsck;
+
+use strict;
+use warnings;
+
+use base qw(CIL::Command);
+
+## ----------------------------------------------------------------------------
+
+sub name { 'fsck' }
+
+sub run {
+ my ($self, $cil, $args) = @_;
+
+
+ # this looks at all the issues it can find and checks for:
+ # * validity
+ # * all the comments are there
+ # * all the attachments are there
+ # then it checks each individual comment/attachment for:
+ # * ToDo: validity
+ # * it's parent exists
+
+ # find all the issues, comments and attachments
+ my $issues = $cil->get_issues();
+ my $issue = {};
+ foreach my $i ( @$issues ) {
+ $issue->{$i->name} = $i;
+ }
+ my $comments = $cil->get_comments();
+ my $comment = {};
+ foreach my $c ( @$comments ) {
+ $comment->{$c->name} = $c;
+ }
+ my $attachments = $cil->get_attachments();
+ my $attachment = {};
+ foreach my $a ( @$attachments ) {
+ $attachment->{$a->name} = $a;
+ }
+
+ # ------
+ # issues
+ my $errors = {};
+ if ( @$issues ) {
+ foreach my $i ( sort { $a->Inserted cmp $b->Inserted } @$issues ) {
+ my $name = $i->name;
+
+ unless ( $i->is_valid($cil) ) {
+ foreach ( @{ $i->errors } ) {
+ push @{$errors->{$name}}, $_;
+ }
+ }
+
+ # check that all it's comments are there and that they have this parent
+ my $comments = $i->CommentList;
+ foreach my $c ( @$comments ) {
+ # see if this comment exists at all
+ if ( exists $comment->{$c} ) {
+ # check the parent is this issue
+ push @{$errors->{$name}}, "comment '$c' is listed under issue '" . $i->name . "' but does not reciprocate"
+ unless $comment->{$c}->Issue eq $i->name;
+ }
+ else {
+ push @{$errors->{$name}}, "comment '$c' listed in issue '" . $i->name . "' does not exist";
+ }
+ }
+
+ # check that all it's attachments are there and that they have this parent
+ my $attachments = $i->AttachmentList;
+ foreach my $a ( @$attachments ) {
+ # see if this attachment exists at all
+ if ( exists $attachment->{$a} ) {
+ # check the parent is this issue
+ push @{$errors->{$name}}, "attachment '$a' is listed under issue '" . $i->name . "' but does not reciprocate"
+ unless $attachment->{$a}->Issue eq $i->name;
+ }
+ else {
+ push @{$errors->{$name}}, "attachment '$a' listed in issue '" . $i->name . "' does not exist";
+ }
+ }
+
+ # check that all it's 'DependsOn' are there and that they have this under 'Precedes'
+ my $depends_on = $i->DependsOnList;
+ foreach my $d ( @$depends_on ) {
+ # see if this issue exists at all
+ if ( exists $issue->{$d} ) {
+ # check the 'Precedes' is this issue
+ my %precedes = map { $_ => 1 } @{$issue->{$d}->PrecedesList};
+ push @{$errors->{$name}}, "issue '$d' should precede '" . $i->name . "' but doesn't"
+ unless exists $precedes{$i->name};
+ }
+ else {
+ push @{$errors->{$name}}, "issue '$d' listed as a dependency of issue '" . $i->name . "' does not exist";
+ }
+ }
+
+ # check that all it's 'Precedes' are there and that they have this under 'DependsOn'
+ my $precedes = $i->PrecedesList;
+ foreach my $p ( @$precedes ) {
+ # see if this issue exists at all
+ if ( exists $issue->{$p} ) {
+ # check the 'DependsOn' is this issue
+ my %depends_on = map { $_ => 1 } @{$issue->{$p}->DependsOnList};
+ push @{$errors->{$name}}, "issue '$p' should depend on '" . $i->name . "' but doesn't"
+ unless exists $depends_on{$i->name};
+ }
+ else {
+ push @{$errors->{$name}}, "issue '$p' listed as preceding issue '" . $i->name . "' does not exist";
+ }
+ }
+ }
+ }
+ print_fsck_errors('Issue', $errors);
+
+ # --------
+ # comments
+ $errors = {};
+ # loop through all the comments
+ if ( @$comments ) {
+ # check that their parent issues exist
+ foreach my $c ( sort { $a->Inserted cmp $b->Inserted } @$comments ) {
+ # check that the parent of each comment exists
+ unless ( exists $issue->{$c->Issue} ) {
+ push @{$errors->{$c->name}}, "comment '" . $c->name . "' refers to issue '" . $c->Issue . "' but issue does not exist";
+ }
+ }
+ }
+ print_fsck_errors('Comment', $errors);
+
+ # -----------
+ # attachments
+ $errors = {};
+ # loop through all the attachments
+ if ( @$attachments ) {
+ # check that their parent issues exist
+ foreach my $a ( sort { $a->Inserted cmp $b->Inserted } @$attachments ) {
+ # check that the parent of each attachment exists
+ unless ( exists $issue->{$a->Issue} ) {
+ push @{$errors->{$a->name}}, "attachment '" . $a->name . "' refers to issue '" . $a->Issue . "' but issue does not exist";
+ }
+ }
+ }
+ print_fsck_errors('Attachment', $errors);
+
+ # ------------
+ # nothing left
+ CIL::Utils->separator();
+}
+
+sub print_fsck_errors {
+ my ($entity, $errors) = @_;
+ return unless keys %$errors;
+
+ CIL::Utils->separator();
+ foreach my $issue_name ( keys %$errors ) {
+ CIL::Utils->title( "$entity $issue_name ");
+ foreach my $error ( @{$errors->{$issue_name}} ) {
+ CIL::Utils->msg("* $error");
+ }
+ }
+}
+
+1;
+## ----------------------------------------------------------------------------
diff --git a/lib/CIL/Command/Init.pm b/lib/CIL/Command/Init.pm
new file mode 100644
index 0000000..1bf92d5
--- /dev/null
+++ b/lib/CIL/Command/Init.pm
@@ -0,0 +1,108 @@
+## ----------------------------------------------------------------------------
+# cil is a Command line Issue List
+# Copyright (C) 2008 Andrew Chilton
+#
+# This file is part of 'cil'.
+#
+# cil is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+## ----------------------------------------------------------------------------
+
+package CIL::Command::Init;
+
+use strict;
+use warnings;
+use File::Slurp qw(read_file write_file);
+
+use base qw(CIL::Command);
+
+## ----------------------------------------------------------------------------
+
+sub name { 'init' }
+
+sub run {
+ my ($self, $cil, $args) = @_;
+
+ my $path = $args->{p} || '.'; # default path is right here
+
+ # error if $path doesn't exist
+ unless ( -d $path ) {
+ CIL::Utils->fatal("path '$path' doesn't exist");
+ }
+
+ # error if issues/ already exists
+ my $issues_dir = "$path/issues";
+ if ( -d $issues_dir ) {
+ CIL::Utils->fatal("issues directory '$issues_dir' already exists, not initialising issues");
+ }
+
+ # error if .cil already exists
+ my $config = "$path/.cil";
+ if ( -f $config ) {
+ CIL::Utils->fatal("config file '$config' already exists, not initialising issues");
+ }
+
+ # try to create the issues/ dir
+ unless ( mkdir $issues_dir ) {
+ CIL::Utils->fatal("Couldn't create '$issues_dir' directory: $!");
+ }
+
+ # are we in a Git repository?
+ my $use_git = 0;
+ if ( -d '.git' ) {
+ CIL::Utils->msg( 'git repository detected, setting to use it' );
+ $use_git = 1;
+ }
+
+ # create a .cil file here also
+ if ( $args->{bare} ) {
+ unless ( touch $config ) {
+ rmdir $issues_dir;
+ CIL::Utils->fatal("couldn't create a '$config' file");
+ }
+ }
+ else {
+ # write a default .cil file
+ write_file($config, <<"CONFIG");
+UseGit: $use_git
+StatusStrict: 1
+StatusOpenList: New
+StatusOpenList: InProgress
+StatusClosedList: Finished
+DefaultNewStatus: New
+LabelStrict: 1
+LabelAllowedList: Type-Enhancement
+LabelAllowedList: Type-Defect
+LabelAllowedList: Priority-High
+LabelAllowedList: Priority-Medium
+LabelAllowedList: Priority-Low
+CONFIG
+ }
+
+ # add a README.txt so people know what this is about
+ unless ( -f "$issues_dir/README.txt" ) {
+ write_file("$issues_dir/README.txt", <<'README');
+This directory is used by CIL to track issues and feature requests.
+
+The home page for CIL is at http://www.chilts.org/projects/cil/
+README
+ }
+
+ # $path/issues/ and $path/.cil create correctly
+ CIL::Utils->msg("initialised empty issue list inside '$path/'");
+}
+
+1;
+
+## ----------------------------------------------------------------------------
diff --git a/lib/CIL/Command/Label.pm b/lib/CIL/Command/Label.pm
new file mode 100644
index 0000000..d8da2c8
--- /dev/null
+++ b/lib/CIL/Command/Label.pm
@@ -0,0 +1,82 @@
+## ----------------------------------------------------------------------------
+# cil is a Command line Issue List
+# Copyright (C) 2008 Andrew Chilton
+#
+# This file is part of 'cil'.
+#
+# cil is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+## ----------------------------------------------------------------------------
+
+package CIL::Command::Label;
+
+use strict;
+use warnings;
+
+use base qw(CIL::Command);
+
+## ----------------------------------------------------------------------------
+
+sub name { 'label' }
+
+sub run {
+ my ($self, $cil, $args, $label, @issue_names) = @_;
+
+ unless ( defined $label ) {
+ CIL::Utils->fatal("provide a valid label to add to this issue");
+ }
+
+ my @issues;
+
+ # for every issue
+ foreach my $issue_name ( @issue_names ) {
+ # firstly, read the issue in
+ my $issue = CIL::Utils->load_issue_fuzzy( $cil, $issue_name );
+
+ # decide whether we are adding or removing this label
+ if ( $args->{remove} ) {
+ $issue->remove_label( $label );
+ }
+ else {
+ $issue->add_label( $label );
+ }
+
+ # save
+ $issue->save($cil);
+
+ if ( $cil->UseGit ) {
+ # if we want to add or commit this issue
+ if ( $args->{add} or $args->{commit} ) {
+ $cil->git->add( $cil, $issue );
+ }
+ }
+
+ push @issues, $issue;
+ }
+
+ if ( $cil->UseGit ) {
+ # if we want to commit these issues
+ if ( $args->{commit} ) {
+ if ( $args->{remove} ) {
+ $cil->git->commit_multiple( $cil, "Removed label '$label'", @issues );
+ }
+ else {
+ $cil->git->commit_multiple( $cil, "Added label '$label'", @issues );
+ }
+ }
+ }
+}
+
+1;
+## ----------------------------------------------------------------------------
diff --git a/lib/CIL/Command/List.pm b/lib/CIL/Command/List.pm
new file mode 100644
index 0000000..cdb5b03
--- /dev/null
+++ b/lib/CIL/Command/List.pm
@@ -0,0 +1,55 @@
+## ----------------------------------------------------------------------------
+# cil is a Command line Issue List
+# Copyright (C) 2008 Andrew Chilton
+#
+# This file is part of 'cil'.
+#
+# cil is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+## ----------------------------------------------------------------------------
+
+package CIL::Command::List;
+
+use strict;
+use warnings;
+
+use base qw(CIL::Command);
+
+## ----------------------------------------------------------------------------
+
+sub name { 'list' }
+
+sub run {
+ my ($self, $cil, $args) = @_;
+
+ CIL::Utils->check_paths($cil);
+
+ # find all the issues
+ my $issues = $cil->get_issues();
+ $issues = CIL::Utils->filter_issues( $cil, $issues, $args );
+ if ( @$issues ) {
+ foreach my $issue ( sort { $a->Inserted cmp $b->Inserted } @$issues ) {
+ CIL::Utils->separator();
+ CIL::Utils->display_issue_headers($issue);
+ }
+ CIL::Utils->separator();
+ }
+ else {
+ CIL::Utils->msg('no issues found');
+ }
+}
+
+1;
+
+## ----------------------------------------------------------------------------
diff --git a/lib/CIL/Command/Precedes.pm b/lib/CIL/Command/Precedes.pm
new file mode 100644
index 0000000..0fdf12e
--- /dev/null
+++ b/lib/CIL/Command/Precedes.pm
@@ -0,0 +1,62 @@
+## ----------------------------------------------------------------------------
+# cil is a Command line Issue List
+# Copyright (C) 2008 Andrew Chilton
+#
+# This file is part of 'cil'.
+#
+# cil is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+## ----------------------------------------------------------------------------
+
+package CIL::Command::Precedes;
+
+use strict;
+use warnings;
+
+use base qw(CIL::Command);
+
+## ----------------------------------------------------------------------------
+
+sub name { 'precedes' }
+
+sub run {
+ my ($self, $cil, $args, $issue_name, $precedes_name) = @_;
+
+ my $issue = CIL::Utils->load_issue_fuzzy($cil, $issue_name);
+ my $precedes = CIL::Utils->load_issue_fuzzy($cil, $precedes_name);
+
+ $issue->add_precedes( $precedes->name );
+ $precedes->add_depends_on( $issue->name );
+
+ $issue->save($cil);
+ $precedes->save($cil);
+
+ if ( $cil->UseGit ) {
+ # if we want to add or commit this change
+ if ( $args->{add} or $args->{commit} ) {
+ $cil->git->add( $cil, $issue );
+ $cil->git->add( $cil, $precedes );
+ }
+
+ # if we want to commit this change
+ if ( $args->{commit} ) {
+ my $message = 'Issue ' . $issue->name . ' precedes ' . $precedes->name;
+ $cil->git->commit_multiple( $cil, $message, $issue, $precedes );
+ }
+ }
+}
+
+1;
+
+## ----------------------------------------------------------------------------
diff --git a/lib/CIL/Command/Show.pm b/lib/CIL/Command/Show.pm
new file mode 100644
index 0000000..865fa3a
--- /dev/null
+++ b/lib/CIL/Command/Show.pm
@@ -0,0 +1,42 @@
+## ----------------------------------------------------------------------------
+# cil is a Command line Issue List
+# Copyright (C) 2008 Andrew Chilton
+#
+# This file is part of 'cil'.
+#
+# cil is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+## ----------------------------------------------------------------------------
+
+package CIL::Command::Show;
+
+use strict;
+use warnings;
+
+use base qw(CIL::Command);
+
+## ----------------------------------------------------------------------------
+
+sub name { 'show' }
+
+sub run {
+ my ($self, $cil, undef, $issue_name) = @_;
+
+ # firstly, read the issue in
+ my $issue = CIL::Utils->load_issue_fuzzy( $cil, $issue_name );
+ CIL::Utils->display_issue_full($cil, $issue);
+}
+
+1;
+## ----------------------------------------------------------------------------
diff --git a/lib/CIL/Command/Status.pm b/lib/CIL/Command/Status.pm
new file mode 100644
index 0000000..b74f2ae
--- /dev/null
+++ b/lib/CIL/Command/Status.pm
@@ -0,0 +1,71 @@
+## ----------------------------------------------------------------------------
+# cil is a Command line Issue List
+# Copyright (C) 2008 Andrew Chilton
+#
+# This file is part of 'cil'.
+#
+# cil is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+## ----------------------------------------------------------------------------
+
+package CIL::Command::Status;
+
+use strict;
+use warnings;
+
+use base qw(CIL::Command);
+
+## ----------------------------------------------------------------------------
+
+sub name { 'status' }
+
+sub run {
+ my ($self, $cil, $args, $status, @issue_names) = @_;
+
+ unless ( defined $status ) {
+ CIL::Utils->fatal("provide a valid status to set this issue to");
+ }
+
+ my @issues;
+
+ # for every issue, read it it and set the Status
+ foreach my $issue_name ( @issue_names ) {
+ # firstly, read the issue in
+ my $issue = CIL::Utils->load_issue_fuzzy( $cil, $issue_name );
+
+ # set the label for this issue
+ $issue->Status( $status );
+ $issue->save($cil);
+
+ # if we want to add or commit this issue
+ if ( $cil->UseGit ) {
+ if ( $args->{add} or $args->{commit} ) {
+ $cil->git->add( $cil, $issue );
+ }
+ }
+
+ push @issues, $issue;
+ }
+
+ if ( $cil->UseGit ) {
+ # if we want to commit these issues
+ if ( $args->{commit} ) {
+ my $message = "Status changed to '$status'";
+ $cil->git->commit_multiple( $cil, $message, @issues );
+ }
+ }
+}
+
+1;
+## ----------------------------------------------------------------------------
diff --git a/lib/CIL/Command/Steal.pm b/lib/CIL/Command/Steal.pm
new file mode 100644
index 0000000..641c5ae
--- /dev/null
+++ b/lib/CIL/Command/Steal.pm
@@ -0,0 +1,59 @@
+## ----------------------------------------------------------------------------
+# cil is a Command line Issue List
+# Copyright (C) 2008 Andrew Chilton
+#
+# This file is part of 'cil'.
+#
+# cil is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+## ----------------------------------------------------------------------------
+
+package CIL::Command::Steal;
+
+use strict;
+use warnings;
+
+use base qw(CIL::Command);
+
+## ----------------------------------------------------------------------------
+
+sub name { 'steal' }
+
+sub run {
+ my ($self, $cil, $args, $issue_name) = @_;
+
+ # firstly, read the issue in
+ my $issue = CIL::Utils->load_issue_fuzzy( $cil, $issue_name );
+
+ # set the AssignedTo for this issue to you (because you're stealing it)
+ $issue->AssignedTo( CIL::Utils->user($cil) );
+ $issue->save($cil);
+
+ if ( $cil->UseGit ) {
+ # if we want to add or commit this issue
+ if ( $args->{add} or $args->{commit} ) {
+ $cil->git->add( $cil, $issue );
+ }
+
+ # if we want to commit this issue
+ if ( $args->{commit} ) {
+ $cil->git->commit( $cil, 'Issue Stolen', $issue );
+ }
+ }
+
+ CIL::Utils->display_issue_full($cil, $issue);
+}
+
+1;
+## ----------------------------------------------------------------------------
diff --git a/lib/CIL/Command/Summary.pm b/lib/CIL/Command/Summary.pm
new file mode 100644
index 0000000..f5a3ab6
--- /dev/null
+++ b/lib/CIL/Command/Summary.pm
@@ -0,0 +1,55 @@
+## ----------------------------------------------------------------------------
+# cil is a Command line Issue List
+# Copyright (C) 2008 Andrew Chilton
+#
+# This file is part of 'cil'.
+#
+# cil is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+## ----------------------------------------------------------------------------
+
+package CIL::Command::Summary;
+
+use strict;
+use warnings;
+
+use base qw(CIL::Command);
+
+## ----------------------------------------------------------------------------
+
+sub name { 'summary' }
+
+sub run {
+ my ($self, $cil, $args) = @_;
+
+ CIL::Utils->check_paths($cil);
+
+ # find all the issues
+ my $issues = $cil->get_issues();
+ $issues = CIL::Utils->filter_issues( $cil, $issues, $args );
+ if ( @$issues ) {
+ CIL::Utils->separator();
+ foreach my $issue ( @$issues ) {
+ CIL::Utils->display_issue_summary($issue);
+ }
+ CIL::Utils->separator();
+ }
+ else {
+ CIL::Utils->msg('no issues found');
+ }
+}
+
+1;
+
+## ----------------------------------------------------------------------------
diff --git a/lib/CIL/Command/Track.pm b/lib/CIL/Command/Track.pm
new file mode 100644
index 0000000..ce2f879
--- /dev/null
+++ b/lib/CIL/Command/Track.pm
@@ -0,0 +1,51 @@
+## ----------------------------------------------------------------------------
+# cil is a Command line Issue List
+# Copyright (C) 2008 Andrew Chilton
+#
+# This file is part of 'cil'.
+#
+# cil is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+## ----------------------------------------------------------------------------
+
+package CIL::Command::Track;
+
+use strict;
+use warnings;
+
+use base qw(CIL::Command);
+
+## ----------------------------------------------------------------------------
+
+sub name { 'track' }
+
+sub run {
+ my ($self, $cil, undef, $issue_name) = @_;
+
+ CIL::Utils->fatal("to use this feature the 'UseGit' option in your .cil file should be set")
+ unless $cil->UseGit;
+
+ my $issue = CIL::Utils->load_issue_fuzzy($cil, $issue_name);
+
+ # add the issue to Git
+ my $issue_dir = $cil->IssueDir();
+ my @files;
+ push @files, "$issue_dir/i_" . $issue->name . '.cil';
+ push @files, map { "$issue_dir/c_${_}.cil" } @{ $issue->CommentList };
+ push @files, map { "$issue_dir/a_${_}.cil" } @{ $issue->AttachmentList };
+ CIL::Utils->msg("git add @files");
+}
+
+1;
+## ----------------------------------------------------------------------------
diff --git a/lib/CIL/Command/Work.pm b/lib/CIL/Command/Work.pm
new file mode 100644
index 0000000..83f8d7c
--- /dev/null
+++ b/lib/CIL/Command/Work.pm
@@ -0,0 +1,64 @@
+## ----------------------------------------------------------------------------
+# cil is a Command line Issue List
+# Copyright (C) 2008 Andrew Chilton
+#
+# This file is part of 'cil'.
+#
+# cil is free software: you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation, either version 3 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program. If not, see <http://www.gnu.org/licenses/>.
+#
+## ----------------------------------------------------------------------------
+
+package CIL::Command::Work;
+
+use strict;
+use warnings;
+use File::Slurp qw(read_file write_file);
+
+use base qw(CIL::Command);
+
+## ----------------------------------------------------------------------------
+
+sub name { 'work' }
+
+sub run {
+ my ($self, $cil, $args, $issue_name) = @_;
+
+ CIL::Utils->fatal("to use this feature the 'UseGit' option in your .cil file should be set")
+ unless $cil->UseGit;
+
+ # firstly, read the issue in
+ my $issue = CIL::Utils->load_issue_fuzzy( $cil, $issue_name );
+
+ # right, got it's name, let's see if there is a branch for it
+ my @branches = $cil->git->branches();
+ my $branch = {};
+ foreach ( @branches ) {
+ $branch->{substr $_, 2} = 1;
+ }
+ if ( exists $branch->{$issue->name} ) {
+ $cil->git->switch_to_branch( $issue->name );
+ }
+ else {
+ $cil->git->create_branch( $issue->name );
+ }
+
+ # now that we've switched branches, load the issue in again (just in case)
+ $issue = CIL::Utils->load_issue_fuzzy( $cil, $issue_name );
+ $issue->Status( 'InProgress' );
+ $issue->save($cil);
+}
+
+1;
+
+## ----------------------------------------------------------------------------