package Git::IssueManager; #ABSTRACT: Module for managing issues in a git branch within your repository use Moose; use MooseX::Privacy; use DateTime; use DateTime::TimeZone; use Data::Dumper; use Git::LowLevel; =attr gitcmd the path to the git command, default is using your path =cut has 'gitcmd' => (is => 'ro', isa => 'Str', default=>"git"); =attr repository Git::Repository object on which to do the issue management =cut has 'repository' => (is =>'rw', isa => 'Git::LowLevel'); =attr _open B =cut has '_open' => (is => 'rw', isa => 'Git::LowLevel::Tree', traits => [qw/Private/]); =attr _assigned B =cut has '_assigned' => (is => 'rw', isa => 'Git::LowLevel::Tree', traits => [qw/Private/]); =attr _inprogress B =cut has '_inprogress' => (is => 'rw', isa => 'Git::LowLevel::Tree', traits => [qw/Private/]); =attr _closed B =cut has '_closed' => (is => 'rw', isa => 'Git::LowLevel::Tree', traits => [qw/Private/]); =attr _root B =cut has '_root' => (is => 'rw', isa => 'Git::LowLevel::Tree', traits => [qw/Private/]); =method ready validates if everything is in place for issue management =cut sub ready { my $self = shift; my $ref = $self->repository->getReference('refs/heads/issues'); return 0 unless $ref->exist; my $version = $ref->find('.version'); return 0 unless defined($version) && ref($version) eq "Git::LowLevel::Blob"; my $tag = $ref->find('.tag'); return 0 unless defined($tag) && ref($tag) eq "Git::LowLevel::Blob"; return 1; } =method version returns the version number of the issue system within the issue branch =cut sub version { my $self = shift; return unless $self->ready(); my $ref = $self->repository->getReference('refs/heads/issues'); my $version = $ref->find(".version"); return $version->content; } =method tag returns the issue tag to prepend in front of all issue ids =cut sub tag { my $self = shift; return unless $self->ready(); my $ref = $self->repository->getReference('refs/heads/issues'); my $tag = $ref->find(".tag"); return $tag->content; } =method init initialize the repository for managing issues =cut sub init { my $self = shift; my $issue_tag = shift; return unless ! $self->ready(); die("no issue tag given") unless defined($issue_tag) && length($issue_tag) > 0; my $ref = $self->repository->getReference('refs/heads/issues'); my $root = $ref->getTree(); my $version = $root->newBlob(); $version->path(".version"); $version->_content("0.1"); $root->add($version); my $tag = $root->newBlob(); $tag->path(".tag"); $tag->_content($issue_tag); $root->add($tag); $ref->commit("initialized issue manager"); } =method add add an issue to the repository first paramter is an GitIssueManager::Issue object =cut sub add { my $self = shift; my $issue = shift; die("IssueManager not initialized") unless $self->ready(); die("no issue given") unless defined($issue) && ref($issue) eq "Git::IssueManager::Issue"; my $ref = $self->repository->getReference('refs/heads/issues'); my $root = $ref->getTree(); my $issueTree=$issue->createIssue($self->repository); my $base=$root->find($issue->status); if (!defined($base)) { $base = $root->newTree(); $base->path($issue->status); $root->add($base); } $base->add($issueTree); $ref->commit("added issue " . $issue->subject); } =method parseIssue parsed the given Git::LowLevel::Tree object as an Issue =cut sub parseIssue { my $self = shift; my $d = shift; my $tag = shift; my $subject = $d->mypath(); my $description = $d->find("description"); my $priority = $d->find("priority"); my $severity = $d->find("severity"); my $type = $d->find("type"); my $worker = $d->find("worker"); my $substatus = $d->find("substatus"); my $comment = $d->find("comment"); my $estimated = $d->find("estimated"); my $working = $d->find("working"); my $tags = $d->find("tags"); my $id = $tag . "-" . substr($d->hash(),0,8); my $cd = $d->timestamp_added(); my $ld = $d->timestamp_last(); my $author = $d->committer(); # check for required attributes die("description not available for issue " . $id) unless defined($description); die("priority not available for issue " . $id) unless defined($priority); die("severity not available for issue " . $id) unless defined($severity); die("type not available for issue " . $id) unless defined($type); my $tz=DateTime::TimeZone->new( name => 'local' ); my $issue = Git::IssueManager::Issue->new(subject => $subject); $issue->description($description->content()); $issue->priority($priority->content()); $issue->severity($severity->content()); $issue->type($type->content()); $issue->id($id); $issue->creation_date(DateTime->from_epoch( epoch =>$cd, time_zone=>$tz)); $issue->last_change_date(DateTime->from_epoch( epoch =>$ld, time_zone=>$tz)); if (defined($worker)) { $worker->content()=~/^(.*)\<(.*)\>$/; $issue->worker($1); $issue->worker_email($2); } if (defined($author)) { $author=~/^(.*)\<(.*)\>$/; $issue->author($1); $issue->author_email($2); } return $issue; } sub list { my $self = shift; my @issues; die("IssueManager not initialized") unless $self->ready(); my $ref = $self->repository->getReference('refs/heads/issues'); my $root = $ref->getTree(); my $open = $ref->find("open"); my $closed = $ref->find("closed"); my $assigned = $ref->find("assigned"); my $inprogress = $ref->find("inprogess"); my $tag = $ref->find(".tag")->content(); my @all; # merge all issues into one array if (defined($open)) { push(@all,$open->get()); } if (defined($closed)) { push(@all,$closed->get()); } if (defined($assigned)) { push(@all,$assigned->get()); } if (defined($inprogress)) { push(@all,$inprogress->get()); } for my $d (@all) { my $issue = $self->parseIssue($d,$tag); push(@issues,$issue); } return @issues; } sub delete { my $self = shift; my $id = shift; die("IssueManager not initialized") unless $self->ready(); my $ref = $self->repository->getReference('refs/heads/issues'); my $root = $ref->getTree(); } 1;