Git-IssueManager/lib/Git/IssueManager/Issue.pm

571 lines
12 KiB
Perl

package Git::IssueManager::Issue;
#ABSTRACT: class representing an Issue
use Moose;
use File::Basename;
=head1 DESCRIPTION
B<Git::IssueManager::Issue> represents an issue within the Git::IssueManager module. Issues can be
added, removed, modified and listed.
Make sure that you understand all the attributes before adding issues to your repository.
=cut
=attr subject
The subject/ title of the issue
At most 50 chars allowed.
=cut
has 'subject' => (is => 'rw', isa => 'Str', required => 1, trigger => sub {
my ($self, $new, $old) = @_;
die("subject exceeds 50 chars") unless length($new) < 51;
}
);
=attr priority
The priority of the issue. Possible values are:
=over
=item I<urgent> - the most highes level of priority
=item I<high>
=item I<medium>
=item I<low>
=back
The default value is B<low>.
=cut
has 'priority' => (is => 'rw', isa => 'Str', default => 'low', trigger => sub {
my ($self, $new, $old) = @_;
die("unknown value (" . $new . ")") unless lc($new) eq "urgent" || lc($new) eq "high" ||
lc($new) eq "medium" || lc($new) eq "low";
});
=attr severity
The severity of the issue. Possible values are:
=over
=item I<critical>
=item I<high>
=item I<medium>
=item I<low>
=back
The default value is B<low>
=cut
has 'severity' => (is => 'rw', isa => 'Str', default => 'low',trigger => sub {
my ($self, $new, $old) = @_;
die("unknown value (" . $new . ")") unless lc($new) eq "critical" || lc($new) eq "high" ||
lc($new) eq "medium" || lc($new) eq "low";
});
=attr type
The type of the issue. Possible values are:
=over
=item I<bug> - a problem within the code, preventing the correct working of the software
=item I<security-bug> - a security related problem within the code, preventing the correct working of the software
=item I<improvement> - an enhancement to an already existing feature
=item I<feature> - a completly new feature
=item I<task> - a simple task, which should be done (please use rarely)
=back
The default values is B<bug>.
=cut
has 'type' => (is => 'rw', isa => 'Str', default => 'bug', trigger => sub {
my ($self, $new, $old) = @_;
die("unknown value (" . $new . ")") unless lc($new) eq "bug" || lc($new) eq "security-bug" ||
lc($new) eq "improvement" || lc($new) eq "feature" ||
lc($new) eq "task";
});
=attr status
The status of the issue. Possible values are:
=over
=item I<open> - nothing has been done yet
=item I<assigned> - the issue has been assigned to a developer
=item I<inprogess> - somebody is working on the issue
=item I<closed> - the issue is closed
=back
The default value is B<open>.
=cut
has 'status' => (is => 'rw', isa => 'Str', default => 'open', trigger => sub {
my ($self, $new, $old) = @_;
die("unknown value (" . $new . ")") unless lc($new) eq "open" || lc($new) eq "assigned" ||
lc($new) eq "inprogress" || lc($new) eq "closed";
});
=attr substatus
A substatus to the actual status. Possible values are:
=over
=item I<none> - there is no substatus
=item I<fixed> - the bug was fixed
=item I<wontfix> - the issue has been closed but it will never be fixed
=back
The default value is B<none>.
=cut
has 'substatus' => (is => 'rw', isa => 'Str', default => 'none', trigger => sub {
my ($self, $new, $old) = @_;
die("unknown value (" . $new . ")") unless lc($new) eq "none" || lc($new) eq "fixed" ||
lc($new) eq "wontfix";
});
=attr comment
A comment to the current status of the issue.
Only Plain Text is allowed.
Default value is the empty string.
=cut
has 'comment' => (is => 'rw', isa=>'Str', default => "");
=attr description
The full description of the issue.
Only Plain Text and Markdown are allowed.
B<no HTML>
The default value is the empty string.
=cut
has 'description' => (is => 'rw', isa => 'Str', default => "");
=attr tags
An arrayref of tags/ keywords for better identifying the issue.
Maximum length of one tag is B<20> characters.
Maximum number of tags is B<10>.
=cut
has 'tags' => (is => 'rw', isa => 'ArrayRef[Str]', default => sub {return[];});
=attr attachments
An arrayref of files attached to this issue, for example documentation or text files presenting
error messages, screenshots, etc.
=cut
has 'attachements' => (is => 'rw', isa=> 'ArrayRef[Str]', default => sub{return [];});
=attr author
The author of the issue, can be the name or an anomynized nickname
=cut
has 'author' => (is=> 'rw', isa => 'Str', default => "");
=attr author_email
The authors email for sending status changes of the issue
=cut
has 'author_email' => (is => 'rw', isa => 'Str', default => "");
=attr worker
The persons name working on solving the issue
=cut
has 'worker' => (is => 'rw', isa => 'Str', default => "");
=attr worker_email
The email address of the person working on this issue
=cut
has 'worker_email' => ( is => 'rw', isa => 'Str', default =>"");
=attr creation_date
A datetime object representing the date/time the issue was created
=cut
has 'creation_date' => (is => 'rw', isa=>'DateTime',default => sub{return DateTime->now();});
=attr closed_date
A datetime object representing the date/time the issue was closed, only valid if status is closed
=cut
has 'closed_date' => (is => 'rw', isa=>'DateTime',default => sub{return DateTime->now();});
=attr last_change_date
A datetime object representing the date/time the issue was last modified
=cut
has 'last_change_date' => (is => 'rw', isa=>'DateTime',default => sub{return DateTime->now();});
=attr id
id of the issue
=cut
has 'id' => (is => 'rw', isa => 'Str', default => "");
=attr estimated_time
The estimated time for solving this issue in B<Minutes>
Default value is B<0>, meaning no estimate set.
=cut
has 'estimated_time' => (is => 'rw', isa => 'Num', default => 0, trigger => sub {
my ($self, $new, $old) = @_;
die("unknown value (" . $new . ")") unless $new > 0;
});
=attr working_time
The current time in B<Minutes> already spent on this issue
The default value is B<0>.
=cut
has 'working_time' => (is => 'rw', isa=>'Num', default => 0, trigger => sub {
my ($self, $new, $old) = @_;
die("unknown value (" . $new . ")") unless $new > 0;
});
=method addTag
add another tag to the issue.
B<Example:>
$issue->addTag("File");
=over
=item B<1. Parameter:> Tag to add to the issue
=back
=cut
sub addTag
{
my $self = shift;
my $tag = shift;
die("no tag given") unless defined($tag);
die("too many tags") unless @{$self->tags}<11;
die("tag exceeds 20 chars") unless length($tag) < 21;
push (@{$self->tags}, $tag);
}
=method delTag
del a tag from the issue
B<Example:>
$issue->delTag("File");
=over
=item B<1. Parameter> Tag to remove from issue
=back
=cut
sub delTag
{
my $self = shift;
my $tag = shift;
die("no tag given") unless defined($tag);
my $i = 0;
for my $t (@{$self->tags})
{
if ($t eq $tag)
{
last;
}
$i++;
}
splice(@{$self->tags},$i,1);
}
=method addAttachment
Add another attachment to the issue.
B<Example:>
$issue->addAttachement("/tmp/test.txt");
=over
=item B<1. Parameter> path to the attachment to add
=back
Make sure the attachment exist at the given path and stays there until the issue has been
added.
=cut
sub addAttachement
{
my $self = shift;
my $attachment = shift;
die("no attachment given") unless defined($attachment);
die("file does not exist") unless -e $attachment;
push (@{$self->attachements}, $attachment);
}
=method delAttachement
Remove an attachment from the issue.
B<Example:>
$issue->delAttachement("/tmp/test");
=over
=item B<1. Parameter> Attachment path to remove from issue
=back
=cut
sub delAttachment
{
my $self = shift;
my $attachment = shift;
die("no attachment given") unless defined($attachment);
my $i = 0;
for my $a (@{$self->attachments})
{
if ($a eq $attachment)
{
last;
}
$i++;
}
splice(@{$self->attachments},$i,1);
}
=method _createAttachmentTree - internal method, do not call directly
creates a git repository tree object from the attachment array and return the hash of the object
=over
=item B<1. Parameter> reference to a Git::RepositoryHL object
=back
=cut
sub _createAttachmentTree
{
my $self = shift;
my $repository = shift;
my @tree;
for my $a (@{$self->attachments})
{
my $hash = $repository->createFileObjectFromFile($a);
my $t = {
ref => $hash,
path => fileparse($a),
mode => "100644",
type => "blob"
};
push(@tree, $t);
}
return $repository->createTree(\@tree);
}
=method createIssue
Creates the issue inside the given git repository and commits these changes to the issues branch
=over
=item B<1. Parameter> reference to a Git::RepositoryHL object
=back
=cut
sub createIssue
{
my $self = shift;
my $repository = shift;
my @tree;
die("No Git::RepositoryHL object given") unless ref($repository) eq "Git::RepositoryHL";
my $subject = {
path => "subject",
ref => $repository->createFileObject($self->subject),
type => "blob",
mode => "100644"
};
push(@tree, $subject);
my $priority = {
path => "priority",
ref => $repository->createFileObject($self->priority),
type => "blob",
mode => "100644"
};
push(@tree, $priority);
my $severity = {
path => "severity",
ref => $repository->createFileObject($self->severity),
type => "blob",
mode => "100644"
};
push(@tree, $severity);
my $type = {
path => "type",
ref => $repository->createFileObject($self->type),
type => "blob",
mode => "100644"
};
push(@tree, $type);
my $substatus = {
path => "substatus",
ref => $repository->createFileObject($self->substatus),
type => "blob",
mode => "100644"
};
my $comment = {
path => "comment",
ref => $repository->createFileObject($self->comment),
type => "blob",
mode => "100644"
};
push(@tree, $comment);
my $description = {
path => "description",
ref => $repository->createFileObject($self->description),
type => "blob",
mode => "100644"
};
push(@tree, $description);
my $worker = {
path => "worker",
ref => $repository->createFileObject($self->worker . "<" . $self->worker_email . ">"),
type => "blob",
mode => "100644"
};
push(@tree, $worker);
my $estimated = {
path => "estimated",
ref => $repository->createFileObject($self->estimated_time),
type => "blob",
mode => "100644"
};
push(@tree, $estimated);
my $working_time = {
path => "working",
ref => $repository->createFileObject($self->working_time),
type => "blob",
mode => "100644"
};
push(@tree, $working_time);
my $tags = {
path => "tags",
ref => $repository->createFileObject(join "\n", @{$self->tags}),
type => "blob",
mode => "100644"
};
push(@tree, $tags);
if (@{$self->attachements} > 0)
{
my $attachments={
path => "attachments",
ref => $self->_createAttachmentTree($repository),
type => "tree",
mode => "040000"
};
push(@tree, $attachments);
}
return $repository->createTree(\@tree);
}
1;