File Coverage

blib/lib/App/Scaffolder/Command.pm
Criterion Covered Total %
statement 90 112 80.3
branch 17 32 53.1
condition 9 17 52.9
subroutine 22 23 95.6
pod 12 12 100.0
total 150 196 76.5


line stmt bran cond sub pod time code
1             package App::Scaffolder::Command;
2             {
3             $App::Scaffolder::Command::VERSION = '0.002000';
4             }
5              
6             # ABSTRACT: Base class for App::Scaffolder commands
7              
8 2     2   194849 use strict;
  2         6  
  2         100  
9 2     2   11 use warnings;
  2         5  
  2         61  
10              
11 2     2   12 use Carp;
  2         4  
  2         254  
12              
13 2     2   1089 use App::Cmd::Setup -command;
  2         76050  
  2         18  
14 2     2   2773 use File::HomeDir;
  2         13603  
  2         149  
15 2     2   14 use File::ShareDir;
  2         5  
  2         73  
16 2     2   11 use Path::Class::Dir;
  2         4  
  2         46  
17 2     2   9 use MRO::Compat;
  2         4  
  2         78  
18 2     2   26 use Config;
  2         4  
  2         70  
19              
20 2     2   1230 use App::Scaffolder::Template;
  2         6  
  2         3644  
21              
22              
23             sub opt_spec {
24 5     5 1 191279 my ($class, $app) = @_;
25             return (
26 5         91 [ 'list|l' => 'List the search path and the available templates' ],
27             [ 'template|t=s' => 'Name of the template that should be used' ],
28             [ 'target=s' => 'Target directory where output should go - '
29             . 'defaults to current directory, but commands may override this' ],
30             [ 'create-template-dir' => 'Create directory for custom user templates' ],
31             [ 'overwrite' => 'Overwrite existing files', { default => 0 }],
32             [ 'quiet' => 'Do not print the list of created files' ],
33             [], ['Command-specific options:'],
34             $class->get_options($app),
35             )
36             }
37              
38             sub validate_args {
39 5     5 1 10166 my ($self, $opt, $args) = @_;
40              
41 5         47 $self->next::method($opt, $args);
42 5 50 33     2208 unless ($self->contains_base_args($opt) || $opt->template()) {
43 0         0 $self->usage_error("Parameter 'template' required");
44             }
45 5         181 return;
46             }
47              
48              
49              
50             sub contains_base_args {
51 5     5 1 14 my ($self, $opt) = @_;
52 5   33     19 return $opt->list() || $opt->create_template_dir();
53             }
54              
55              
56             sub get_options {
57 5     5 1 12 my ($class, $app) = @_;
58 5         41 return ();
59             }
60              
61              
62              
63             sub get_template_dirs {
64 9     9 1 2166 my ($self) = @_;
65              
66 9         31 my @dirs;
67 9         38 my $command_name = $self->command_names();
68 9         149 my $user_template_dir = $self->_get_user_template_dir($command_name);
69 9 50       25 if ($user_template_dir) {
70 0         0 push @dirs, $user_template_dir;
71             }
72 9         38 push @dirs, $self->get_extra_template_dirs($command_name);
73 9         46 my $command_dir = Path::Class::Dir->new(
74             File::ShareDir::dist_dir($self->get_dist_name())
75             )->subdir($command_name);
76 9 50       2266 if (-d $command_dir) {
77 9         428 push @dirs, $command_dir;
78             }
79              
80 9         42 return @dirs;
81             }
82              
83             sub _get_user_template_dir {
84 9     9   20 my ($self, $command, $create) = @_;
85 9 50       46 my $my_dist_data = File::HomeDir->my_dist_data(
86             $self->get_dist_name(),
87             $create ? { create => 1} : ()
88             );
89 9 50       1256 if ($my_dist_data) {
90 0         0 my $my_command_dir = Path::Class::Dir->new($my_dist_data)->subdir($command);
91 0 0       0 if (-d $my_command_dir) {
    0          
92 0         0 return $my_command_dir;
93             }
94             elsif ($create) {
95 0 0       0 $my_command_dir->mkpath()
96             or confess("Unable to create template dir $my_command_dir");
97 0         0 return $my_command_dir
98             }
99             }
100 9         20 return;
101             }
102              
103              
104              
105             sub get_extra_template_dirs {
106 12     12 1 6018 my ($self, $command) = @_;
107              
108 12 100 66     75 if (! defined $command || $command eq '') {
109 1         17 croak("Required 'command' parameter not passed or empty");
110             }
111              
112 11         26 my $scaffolder_template_path = $ENV{SCAFFOLDER_TEMPLATE_PATH};
113 11         15 my @extra_template_dirs;
114 11 100 66     64 if (defined $scaffolder_template_path && $scaffolder_template_path ne '') {
115 4         450 push @extra_template_dirs, grep { -d $_ } map {
  4         301  
116 3         49 Path::Class::Dir->new($_)->subdir($command)
117             } split(/$Config::Config{path_sep}/x, $scaffolder_template_path);
118             }
119              
120 11         184 return @extra_template_dirs;
121             }
122              
123              
124              
125             sub get_templates {
126 7     7 1 1052 my ($self) = @_;
127              
128 7         15 my $template = {};
129 7         37 for my $dir ($self->get_template_dirs()) {
130 7         34 for my $template_dir (grep { $_->is_dir() } $dir->children()) {
  7         4060  
131 7         62 my $name = $template_dir->dir_list(-1, 1);
132 7 50       149 if (exists $template->{$name}) {
133 0         0 $template->{$name}->add_path_entry($template_dir);
134             }
135             else {
136 7         91 $template->{$name} = App::Scaffolder::Template->new({
137             name => $name,
138             path => [ $template_dir ],
139             });
140             }
141             }
142             }
143 7         33 return $template;
144             }
145              
146              
147              
148             sub get_template {
149 7     7 1 1677 my ($self, $name) = @_;
150              
151 7 100 66     49 if (! defined $name || $name eq '') {
152 1         17 croak("Required 'name' parameter not passed or empty");
153             }
154              
155 6         42 my $template = $self->get_templates();
156 6 50       38 unless (exists $template->{$name}) {
157 0         0 croak("No template called '$name' found");
158             }
159 6         39 return $template->{$name}
160             }
161              
162              
163              
164             sub get_target {
165 5     5 1 8 my ($self, $opt) = @_;
166 5   50     23 return Path::Class::Dir->new($opt->target() || '.');
167             }
168              
169              
170              
171             sub get_variables {
172 5     5 1 321 my ($self, $opt) = @_;
173 5         21 return {};
174             }
175              
176              
177              
178             sub get_dist_name {
179 0     0 1 0 confess("get_dist_name must be implemented by scaffolder commands");
180             }
181              
182              
183              
184             sub execute {
185 5     5 1 37 my ($self, $opt, $args) = @_;
186              
187 5 50       40 if ($opt->list()) {
188 0         0 print "Template search path for ".$self->command_names().":\n ";
189 0         0 print join "\n ", $self->get_template_dirs();
190 0         0 print "\nAvailable templates for ".$self->command_names().":\n ";
191 0         0 print join "\n ", sort keys %{$self->get_templates()};
  0         0  
192 0         0 print "\n";
193 0         0 return;
194             }
195 5 50       39 if ($opt->create_template_dir()) {
196 0         0 $self->_get_user_template_dir($self->command_names(), 1);
197 0         0 print "Template search path after creating template dir for "
198             .$self->command_names().":\n ";
199 0         0 print join "\n ", $self->get_template_dirs();
200 0         0 print "\n";
201 0         0 return;
202             }
203              
204 5         38 my @files = $self->get_template($opt->template())->process({
205             target => $self->get_target($opt),
206             variables => $self->get_variables($opt),
207             overwrite => $opt->overwrite(),
208             });
209 4 100       97 unless ($opt->quiet()) {
210 3         48 print join("\n", sort @files) . "\n";
211             }
212              
213 4         396 return;
214             }
215              
216             1;
217              
218              
219             __END__