File: | lib/App/TimeTracker/Proto.pm |
Coverage: | 81.2% |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | package App::TimeTracker::Proto; | ||||||
2 | 3 3 3 | 452626 9 59 | use strict; | ||||
3 | 3 3 3 | 12 6 78 | use warnings; | ||||
4 | 3 3 3 3 3 3 | 115 128 40 15 8 33 | use 5.010; | ||||
5 | |||||||
6 | # ABSTRACT: TimeTracker Proto Class | ||||||
7 | |||||||
8 | 3 3 3 | 595 668472 29 | use Moose; | ||||
9 | 3 3 3 | 16398 280988 33 | use MooseX::Types::Path::Class; | ||||
10 | 3 3 3 | 2155 2992 86 | use File::HomeDir (); | ||||
11 | 3 3 3 | 14 9 177 | use Path::Class; | ||||
12 | 3 3 3 | 902 5179 49 | use Hash::Merge qw(); | ||||
13 | 3 3 3 | 751 12350 30 | use JSON; | ||||
14 | |||||||
15 | has 'home' => ( | ||||||
16 | is => 'ro', | ||||||
17 | isa => 'Path::Class::Dir', | ||||||
18 | lazy_build => 1, | ||||||
19 | ); | ||||||
20 | sub _build_home { | ||||||
21 | 2 | 36 | my $self = shift; | ||||
22 | 2 | 21 | my $home = | ||||
23 | Path::Class::Dir->new( File::HomeDir->my_home, '.TimeTracker' ); | ||||||
24 | 2 | 699 | $home->mkpath unless -d $home; | ||||
25 | 2 | 78 | return $home; | ||||
26 | } | ||||||
27 | |||||||
28 | has 'configfile' => ( | ||||||
29 | is => 'ro', | ||||||
30 | isa => 'Path::Class::File', | ||||||
31 | lazy_build => 1, | ||||||
32 | ); | ||||||
33 | sub _build_configfile { | ||||||
34 | 2 | 52 | my $self = shift; | ||||
35 | 2 | 16 | return $self->home->file('tracker.json'); | ||||
36 | } | ||||||
37 | |||||||
38 | has 'project' => (is=>'rw',isa=>'Str'); | ||||||
39 | |||||||
40 | sub run { | ||||||
41 | 1 | 0 | 200512 | my $self = shift; | |||
42 | |||||||
43 | 1 | 4 | my $config = $self->load_config; | ||||
44 | |||||||
45 | 6 | 25 | my $class = Moose::Meta::Class->create_anon_class( | ||||
46 | superclasses => ['App::TimeTracker'], | ||||||
47 | roles => [ | ||||||
48 | 1 1 | 4 3 | map { 'App::TimeTracker::Command::' . $_ } 'Core', @{ $config->{plugins} } | ||||
49 | ], | ||||||
50 | ); | ||||||
51 | |||||||
52 | 1 | 25740 | my %commands; | ||||
53 | 1 | 20 | foreach my $method ($class->get_all_method_names) { | ||||
54 | 69 | 3282 | next unless $method =~ /^cmd_/; | ||||
55 | 11 | 28 | $method =~ s/^cmd_//; | ||||
56 | 11 | 29 | $commands{$method}=1; | ||||
57 | } | ||||||
58 | 1 | 207 | my $load_attribs_for_command; | ||||
59 | 1 | 4 | foreach (@ARGV) { | ||||
60 | 0 | 0 | if ($commands{$_}) { | ||||
61 | 0 | 0 | $load_attribs_for_command='_load_attribs_'.$_; | ||||
62 | 0 | 0 | last; | ||||
63 | } | ||||||
64 | } | ||||||
65 | 1 | 5 | if ($load_attribs_for_command && $class->has_method($load_attribs_for_command)) { | ||||
66 | 0 | 0 | $class->name->$load_attribs_for_command($class); | ||||
67 | } | ||||||
68 | |||||||
69 | $class->name->new_with_options( { | ||||||
70 | 1 | 11 | home => $self->home, | ||||
71 | config => $config, | ||||||
72 | _currentproject => $self->project, | ||||||
73 | } )->run; | ||||||
74 | } | ||||||
75 | |||||||
76 | sub load_config { | ||||||
77 | 3 | 0 | 189499 | my $self = shift; | |||
78 | |||||||
79 | 3 | 26 | my $all_config = decode_json( $self->configfile->slurp ); | ||||
80 | 3 | 1659 | my %projects; | ||||
81 | 3 3 | 7 13 | foreach my $job (keys %{$all_config->{jobs}}) { | ||||
82 | 6 6 | 14 21 | foreach my $project (keys %{$all_config->{jobs}{$job}{projects}}) { | ||||
83 | 6 | 19 | $projects{$project} = $job; | ||||
84 | } | ||||||
85 | } | ||||||
86 | |||||||
87 | 3 | 8 | my $project; | ||||
88 | 3 | 9 | my @argv = @ARGV; | ||||
89 | 3 | 13 | while (@argv) { # check if project is specified via commandline | ||||
90 | 1 | 3 | my $arg = shift(@argv); | ||||
91 | 1 | 3 | if ($arg eq '--project') { | ||||
92 | 1 | 3 | my $p = shift(@argv); | ||||
93 | 1 | 3 | $project = $p if $projects{$p}; | ||||
94 | 1 | 5 | unless ($project) { | ||||
95 | 0 | 0 | say "Cannot find project $p in config."; | ||||
96 | } | ||||||
97 | } | ||||||
98 | } | ||||||
99 | 3 | 10 | unless ($project) { # try to figure out project via current dir | ||||
100 | 2 | 22 | my $cwd = Path::Class::Dir->new->absolute; | ||||
101 | 2 | 413 | my $regex = join('|',keys %projects); | ||||
102 | 2 | 69 | if ($cwd =~m{/($regex)}) { | ||||
103 | 2 | 70 | $project = $1 if $projects{$1}; | ||||
104 | } | ||||||
105 | } | ||||||
106 | |||||||
107 | 3 | 8 | my $config; | ||||
108 | 3 | 12 | if ($project) { | ||||
109 | 3 | 25 | $self->project($project); | ||||
110 | 3 | 64 | my $job = $projects{$project}; | ||||
111 | # merge project <- job <- global config | ||||||
112 | 3 | 25 | $config = Hash::Merge::merge($all_config->{'jobs'}{$job}{'projects'}{$project},$all_config->{'jobs'}{$job}{'job'}); | ||||
113 | 3 | 1692 | $config = Hash::Merge::merge($config,$all_config->{'global'}); | ||||
114 | } | ||||||
115 | else { | ||||||
116 | 0 | 0 | say "Cannot figure out project. Please check config and/or --project"; | ||||
117 | 0 | 0 | $self->project('_no_project'); | ||||
118 | 0 | 0 | $config = $all_config->{'global'}; | ||||
119 | } | ||||||
120 | |||||||
121 | 3 | 580 | $config->{project2job}=\%projects; | ||||
122 | 3 | 29 | return $config; | ||||
123 | } | ||||||
124 | |||||||
125 | 1; |