From 9b53d15cf75e7bb44e8a83e2fb9c83304b01e8f5 Mon Sep 17 00:00:00 2001 From: Andrew Chilton Date: Sat, 19 Apr 2008 21:57:45 +1200 Subject: [PATCH] Added the commands init, add and list --- bin/cil | 218 +++++++++++++++++++++++++++++++++++++---------- lib/CIL/Base.pm | 44 +++++++++- lib/CIL/Issue.pm | 83 +++++++++++++----- 3 files changed, 278 insertions(+), 67 deletions(-) diff --git a/bin/cil b/bin/cil index 860efe9..bc6c9dd 100755 --- a/bin/cil +++ b/bin/cil @@ -6,24 +6,50 @@ use warnings; use Data::Dumper; use CIL::Issue; use Term::CallEditor; +use File::Touch; +use YAML; +use File::Glob ':glob'; +use File::Basename; my $COMMANDS = { + init => 1, + list => 1, add => 1, show => 1, - comment => 1, - update => 1 }; +my $new_issue_text = <<"EOF"; +[Issue] + +Summary = +Status =New +CreatedBy =$ENV{GIT_AUTHOR_NAME} <$ENV{GIT_AUTHOR_EMAIL}> +Labels = +Description = <{$command} ) { usage(); - exit 2; + exit 1; } - if ( $command eq 'show' ) { + if ( $command eq 'init' ) { + my ($path) = @ARGV; + $path ||= '.'; + init($path); + } + elsif ( $command eq 'list' ) { + my ($issue_name) = @ARGV; + list(); + + } + elsif ( $command eq 'show' ) { my ($issue_name) = @ARGV; show($issue_name); @@ -34,24 +60,132 @@ my $COMMANDS = { } +## ---------------------------------------------------------------------------- +# commands + +sub init { + my ($path) = @_; + + # error if $path doesn't exist + unless ( -d $path ) { + fatal("path '$path' doesn't exist"); + } + + # error if issues/ already exists + my $issues_dir = "$path/issues"; + if ( -d $issues_dir ) { + fatal("issues directory '$issues_dir' already exists, not initialising issues"); + } + + # error if .cil already exists + my $config = "$path/.cil"; + if ( -f $config ) { + fatal("config file '$config' already exists, not initialising issues"); + } + + # try to create the issues/ dir + unless ( mkdir $issues_dir ) { + fatal("Couldn't create '$issues_dir' directory: $!"); + } + + # create a .cil file here also + unless ( touch $config ) { + rmdir $issues_dir; + fatal("couldn't create a '$config' file"); + } + + # $path/issues/ and $path/.cil create correctly + msg("initialised empty issue list inside '$path/'"); +} + +sub list { + check_paths(); + + my @issues; + + # find all the issues + my @filenames = ; + foreach my $filename ( sort @filenames ) { + push @issues, CIL::Issue->new_load_issue( basename($filename, '.yaml') ); + } + @issues = sort { $a->Inserted cmp $b->Inserted } @issues; + separator(); + foreach my $issue ( @issues ) { + display_issue_short($issue); + } + separator(); +} + sub show { my ($issue_name) = @_; # firstly, read the issue in - my $issue = CIL::Issue->load_issue('2008-04-17T22:05:02.000Z'); - + my $issue = CIL::Issue->new_load_issue($issue_name); unless ( defined $issue ) { print STDERR "Couldn't load issue '$issue'\n"; return; } + display_issue_full( $issue ); +} + +sub add { + my ($issue_name) = @_; + + # read in the new issue text + my $fh = solicit( $new_issue_text ); + + my $issue; + eval { + $issue = CIL::Issue->new_parse_issue( $fh ); + }; + if ( $@ ) { + fatal("couldn't parse issue: $@"); + } + unless ( defined $issue ) { + fatal("couldn't parse issue (program error)"); + } + + $issue->inserted; + $issue->set_no_update( 'Name', $issue->Inserted ); + $issue->save(); + display_issue_full( $issue ); +} + +## ---------------------------------------------------------------------------- + +sub check_paths { + # make sure an issue directory is available + unless ( -d 'issues' ) { + fatal("couldn't find 'issues' directory"); + } +} + +## ---------------------------------------------------------------------------- +# input/output + +sub display_issue_short { + my ($issue) = @_; + + title( "Issue " . $issue->Name ); + field( 'Summary', $issue->Summary() ); + field( 'Name', $issue->Name() ); + field( 'CreatedBy', $issue->CreatedBy() ); + field( 'Inserted', $issue->Inserted() ); + field( 'Status', $issue->Status() ); + field( 'Labels', $issue->Labels() ); +} + +sub display_issue_full { + my ($issue) = @_; separator(); title('Details'); field( 'Summary', $issue->Summary() ); field( 'Name', $issue->Name() ); + field( 'Status', $issue->Status() ); field( 'CreatedBy', $issue->CreatedBy() ); field( 'Inserted', $issue->Inserted() ); - field( 'Status', $issue->Status() ); + field( 'Updated', $issue->Inserted() ); field( 'Labels', $issue->Labels() ); separator(); text('Description', $issue->Description()); @@ -60,62 +194,60 @@ sub show { separator(); } -sub add { - my ($issue_name) = @_; - my $fh = solicit('FOO: please replace this text'); - die "$Term::CallEditor::errstr\n" unless $fh; - my $text; - $text .= $_ while <$fh>; - separator(); - text('You said:', $text); - separator(); -} - -## ---------------------------------------------------------------------------- - -sub usage { - print <<"END_USAGE"; -Usage: $0 [options] - -Commands: - add - show - comment - update - -See for further information. -Report bugs to . -END_USAGE -} - -sub say { - print $_[0], "\n"; +sub msg { + print ( defined $_[0] ? $_[0] : '' ); + print "\n"; } sub separator { - say('=' x 79); + msg('=' x 79); } sub title { my ($title) = @_; my $msg = "--- $title "; $msg .= '-' x (74 - length($title)); - say($msg); + msg($msg); } sub field { my ($field, $value) = @_; my $msg = "$field"; $msg .= " " x (12 - length($field)); - say("$msg: " . (defined $value ? $value : '') ); + msg("$msg: " . (defined $value ? $value : '') ); } sub text { my ($field, $value) = @_; title($field); - say ""; - say($value); - say ""; + msg ""; + msg($value); + msg ""; +} + +sub fatal { + my ($msg) = @_; + chomp $msg; + print STDERR $msg, "\n"; + exit 2; +} + +## ---------------------------------------------------------------------------- +# program info + +sub usage { + print <<"END_USAGE"; +Usage: $0 [options] + +Commands: + init + add + list + show + +See for further information. +Report bugs to . +END_USAGE } ## ---------------------------------------------------------------------------- diff --git a/lib/CIL/Base.pm b/lib/CIL/Base.pm index a061d19..121d372 100644 --- a/lib/CIL/Base.pm +++ b/lib/CIL/Base.pm @@ -3,19 +3,59 @@ package CIL::Base; use strict; use warnings; +use Carp; use DateTime; use base qw(Class::Accessor); __PACKAGE__->mk_accessors(qw(Description CreatedBy Inserted Updated)); +# override Class::Accessor's set +sub set { + my ($self, $key, $value) = @_; + croak "provide a key name" unless defined $key; + + my $orig = $self->get($key); + + # get out if both are defined and they're the same + if ( defined $orig and defined $value ) { + return if $orig eq $value + } + + # get out if neither are defined + if ( !defined $orig and !defined $value ) { + return; + } + + # since we're actually changing the key, say we updated something + $self->{data}{$key} = $value; + $self->updated; +} + +sub set_no_update { + my ($self, $key, $value) = @_; + croak "provide a key name" unless defined $key; + $self->{data}{$key} = $value; +} + +# override Class::Accessor's get +sub get { + my ($self, $key) = @_; + $self->{data}{$key}; +} + sub inserted { my ($self) = @_; - $self->{Inserted} = DateTime->new()->iso8601; + my $time = time; + $self->{data}{Inserted} = $time; + $self->{data}{Updated} = $time; + $self->{Changed} = '1'; } sub updated { my ($self) = @_; - $self->{Updated} = DateTime->new()->iso8601; + my $time = time; + $self->{data}{Updated} = $time; + $self->{Changed} = '1'; } ## ---------------------------------------------------------------------------- diff --git a/lib/CIL/Issue.pm b/lib/CIL/Issue.pm index 6475983..0fe4c8b 100644 --- a/lib/CIL/Issue.pm +++ b/lib/CIL/Issue.pm @@ -3,54 +3,93 @@ package CIL::Issue; use strict; use warnings; +use Carp; use Data::Dumper; use Config::IniFiles; +use YAML qw(LoadFile DumpFile); use base qw(CIL::Base); __PACKAGE__->mk_accessors(qw(Name Summary Status Labels Comments)); +my @ATTRS = ( qw(Name Summary Description CreatedBy Status Labels Comments) ); + ## ---------------------------------------------------------------------------- -sub load_issue { - my ($self, $name) = @_; - return unless defined $name; +sub new { + my ($proto) = @_; + my $class = ref $proto || $proto; + my $self = {}; + bless $self, $class; + $self->inserted; + return $self; +} + +sub new_load_issue { + my ($class, $name) = @_; - my $filename = "issues/$name.ini"; + unless ( defined $name ) { + croak "provide an issue name to load"; + } + + my $filename = "issues/$name.yaml"; + unless ( -f $filename ) { + croak "filename '$filename' does no exist"; + } - return unless -f $filename; my $issue = CIL::Issue->new(); - $issue->read_issue( $filename ); - $issue->Name( $name ); + $issue->{data} = LoadFile( $filename ); return $issue; -} - -sub read_issue { - my ($self, $filename) = @_; my $cfg = Config::IniFiles->new( -file => $filename ); + unless ( defined $cfg ) { + croak("not a valid inifile"); + } - foreach my $attr ( qw(Summary Description) ) { - $self->{$attr} = $cfg->val( 'Issue', $attr ); + # my $issue = CIL::Issue->new(); + foreach my $attr ( qw(Summary Name Description CreatedBy Status Labels Inserted Updated) ) { + # modify the data directly, otherwise Updated will kick in + $issue->{data}{$attr} = $cfg->val( 'Issue', $attr ); } + $issue->{data}{Comments} = []; + + # set the issue Name + $issue->{data}{Name} = $name; + + return $issue; } -sub reset { - my ($self) = @_; +sub new_parse_issue { + my ($class, $file) = @_; - foreach my $attr ( qw(changed) ) { - delete $self->{$attr}; + # $file may be a string ($filename) or a file handle ($fh) + my $cfg = Config::IniFiles->new( -file => $file ); + + unless ( defined $cfg ) { + croak("not a valid inifile"); + } + + my $issue = CIL::Issue->new(); + foreach my $attr ( qw(Summary Name Description CreatedBy Status Labels Inserted Updated) ) { + # modify the data directly, otherwise Updated will kick in + $issue->set_no_update($attr, $cfg->val( 'Issue', $attr )); } + $issue->set_no_update('Comments', []); + return $issue; } -sub inserted { +sub save { my ($self) = @_; - $self->{data}{inserted} = time; + my $name = $self->Name; + my $filename = "issues/$name.yaml"; + DumpFile($filename, $self->{data}); } -sub updated { +sub reset { my ($self) = @_; - $self->{changed} = '1'; - $self->{data}{updated} = time; + + foreach my $attr ( @ATTRS ) { + delete $self->{$attr}; + } } sub add_comment { -- 2.39.5