File Coverage

blib/lib/Cog/App.pm
Criterion Covered Total %
statement 33 131 25.1
branch 0 34 0.0
condition 0 15 0.0
subroutine 11 26 42.3
pod 0 14 0.0
total 44 220 20.0


line stmt bran cond sub pod time code
1             package Cog::App;
2 2     2   1741 use Mo qw'build default';
  2         392  
  2         9  
3             extends 'Cog::Base';
4              
5 2     2   2094 use Getopt::Long qw(:config pass_through);
  2         8195  
  2         11  
6 2     2   1250 use IO::All;
  2         8772  
  2         14  
7 2     2   551 use YAML::XS;
  2         1968  
  2         89  
8 2     2   9 use Cwd 'abs_path';
  2         1  
  2         58  
9 2     2   8 use File::Basename;
  2         2  
  2         95  
10 2     2   8 use File::Spec;
  2         1  
  2         257  
11              
12             has Name => sub {
13             my $Name = ref($_[0]);
14             $Name =~ s/::App\b//;
15             return $Name if $Name =~ /^\w+$/;
16             die "Can't determine 'Name' attribute for '${\ref($_[0])}'";
17             };
18              
19             has app_script => basename $0;
20              
21             has app_root => sub {
22             my $root = abs_path(dirname($_[0]->config_file));
23             return $root if -d $root;
24             die "Can't determine 'app_root' for '${\ref($_[0])}'";
25             };
26              
27             has build_root => sub {
28             my $root = $_[0]->app_root;
29             my $dir = basename($root) =~ /^\./ ? 'build' : '.build';
30             File::Spec->catdir($root, $dir);
31             };
32              
33             has webapp_root => sub {
34             my $root = $_[0]->app_root;
35             File::Spec->catdir($root, 'webapp');
36             };
37              
38             has config_file => sub {
39             abs_path($_[0]->app_script . '.yaml');
40             };
41              
42 2     2   283 use constant config_class => 'Cog::Config';
  2         3  
  2         109  
43 2     2   12 use constant maker_class => 'Cog::Maker';
  2         2  
  2         67  
44 2     2   8 use constant webapp_class => '';
  2         2  
  2         66  
45 2     2   7 use constant runner_class => 'Cog::Runner';
  2         2  
  2         2726  
46              
47 0     0 0   sub plugins { [] };
48              
49             has action => ();
50             has time => time();
51              
52             # If we use the generic 'bin/cog' script, we need to determine which Cog
53             # application class we are representing.
54             sub get_app_class {
55 0     0 0   my ($class, @argv) = @_;
56 0           my $app_class;
57 0           @ARGV = @argv;
58 0           Getopt::Long::GetOptions(
59             'app=s' => \$app_class,
60             );
61 0   0       $app_class ||= $ENV{COG_APP} || $class;
      0        
62 0 0         unless ($app_class->can('new')) {
63 0 0         eval "use $app_class; 1"
64             or die $@;
65             }
66 0 0 0       die "$app_class is not a Cog::App application"
67             unless $app_class->isa('Cog::App') and
68             $app_class ne 'Cog::App';
69              
70 0           return $app_class;
71             }
72              
73             sub BUILD {
74 0     0 0   my ($self) = @_;
75              
76 0           my $config_class = $self->config_class;
77 0 0         eval "require $config_class"
78             unless UNIVERSAL::can($config_class, 'new');
79              
80 0           my $config_file = $self->config_file;
81              
82 0 0         my $hash = $config_class->flatten_namespace(
83             -e $config_file ? YAML::XS::LoadFile($config_file) : {}
84             );
85 0   0       my $app_class = $hash->{app_class} ||= ref($self);
86 0 0         if ($app_class ne ref($self)) {
87 0 0         eval "require $app_class; 1" or die $@;
88 0           $self = $_[0] = $app_class->new();
89             }
90              
91 0           $Cog::Base::initialize->(
92             $self,
93             $config_class->new(
94             %$hash,
95             app => $self,
96             cli_args => [@ARGV],
97             ),
98             );
99             }
100              
101             sub run {
102 0     0 0   my $self = shift;
103              
104 0           $self->parse_command_args;
105              
106 0           my $action = $self->action;
107 0           my $method = "handle_$action";
108              
109 0 0         my $function = $self->can($method)
110             or die "'$action' is an invalid action\n";
111              
112 0 0         if ($action ne 'init') {
113 0 0         die "Can't determine 'config_file' for '${\ref($_[0])}'"
  0            
114             unless $self->config_file;
115 0           $self->_chdir_root();
116             }
117              
118 0           $function->($self);
119              
120 0           return 0;
121             }
122              
123             sub parse_command_args {
124 0     0 0   my $self = shift;
125 0           my $argv = $self->config->cli_args;
126 0           my $script = $self->app_script;
127 0           $script =~ s!.*/!!;
128 0           my $action = '';
129 0 0 0       if ($script =~ /^(pre-commit|post-commit)$/) {
    0          
    0          
130 0           $script =~ s/-/_/;
131 0           $self->action($script);
132             }
133             elsif (@$argv and $argv->[0] =~ /^[\w\-]+$/) {
134 0           $action = shift @$argv;
135 0           $action =~ s/-/_/g;
136             }
137             elsif (not @$argv) {
138 0           $action = 'help';
139             }
140             else {
141 0           die "Invalid cog command. Can't parse these arguments: '@_'";
142             }
143 0           $self->action($action);
144             }
145              
146             #-----------------------------------------------------------------------------
147             sub handle_help {
148 0     0 0   my $self = shift;
149 0           print $self->usage;
150             }
151              
152             sub usage {
153 0     0 0   my $self = shift;
154 0           my $Name = $self->Name;
155 0           my $name = $self->app_script;
156 0           $name =~ s!.*/!!;
157 0           return <<"...";
158             Usage: $name <command>
159              
160             Commands:
161             init - Make current directory into a $Name app
162             update - Update the app with the latest assets
163             make - Prepare the app content for the web
164             start - Start the local app server
165             stop - Stop the server
166              
167             ...
168             }
169              
170             sub handle_init {
171 0     0 0   my $self = shift;
172 0           my $root = $self->app_root;
173 0 0         die "Can't init. Cog environment already exists.\n"
174             if $self->config->is_init;
175 0           my $share = $self->config->find_share_dir($self);
176              
177 0           my $config_file = $self->config_file;
178 0 0         if (not -e $config_file) {
179 0           require Template::Toolkit::Simple;
180 0           my $data = +{%$self};
181 0           $data->{app_class} = ref($self);
182 0           my $config = Template::Toolkit::Simple::tt()
183             ->path(["$share/template/"])
184             ->data($data)
185             ->post_chomp
186             ->render('config.yaml');
187 0           io($config_file)->print($config);
188             }
189              
190 0           $self->_chdir_root;
191              
192 0           my $Name = $self->Name;
193 0           my $name = $self->app_script;
194 0           $name =~ s!.*/!!;
195              
196 0           print <<"...";
197              
198             $Name was successfully initialized in:
199              
200             $root
201              
202             The next step is to edit:
203              
204             $config_file
205              
206             Then run:
207              
208             $name update
209              
210             ...
211             }
212              
213             sub handle_update {
214 0     0 0   my $self = shift;
215 0           my $root = $self->app_root;
216              
217 0           $self->maker->make_assets();
218              
219 0           my $Name = $self->Name;
220 0           my $name = $self->app_script;
221 0           $name =~ s!.*/!!;
222              
223 0           print <<"...";
224             $Name was successfully updated in the $root/ subdirectory.
225              
226             Now run:
227              
228             $name make
229              
230             ...
231             }
232              
233             sub handle_make {
234 0     0 0   my $self = shift;
235 0           $self->maker->make;
236 0           my $Name = $self->Name;
237 0           my $name = $self->app_script;
238 0           $name =~ s!.*/!!;
239 0           print <<"...";
240              
241             $Name is up to date and ready to use.
242             To start the web server, run this command:
243              
244             $name start
245              
246             ...
247              
248             }
249              
250             sub handle_start {
251 0     0 0   my $self = shift;
252 0           my $Name = $self->Name;
253 0           print <<"...";
254             $Name web server is starting up...
255              
256             ...
257 0           my @args = @{$self->config->cli_args};
  0            
258 0 0         unshift @args, ('-p' => $self->config->server_port)
259             if $self->config->server_port;
260 0           $self->runner->run(@args);
261             }
262              
263             sub handle_stop {
264 0     0 0   die 'TODO';
265             }
266              
267             sub handle_edit {
268 0     0 0   die 'TODO';
269             }
270              
271             sub handle_clean {
272 0     0 0   my $self = shift;
273 0           $self->maker->make_clean;
274 0           my $Name = $self->Name;
275 0           my $name = $self->app_script;
276 0           $name =~ s!.*/!!;
277 0           print <<"...";
278              
279             $Name is clean. To rebuild, run this command:
280              
281             $name update
282              
283             ...
284              
285             }
286              
287             # Put the App in the context of its defined root directory.
288             sub _chdir_root {
289 0     0     my $self = shift;
290 0           my $app_root = $self->app_root;
291 0 0         chdir $app_root
292             or die "Can't chdir into $app_root";
293             }
294              
295             1;