File Coverage

blib/lib/Setup/Project.pm
Criterion Covered Total %
statement 18 20 90.0
branch n/a
condition n/a
subroutine 7 7 100.0
pod n/a
total 25 27 92.5


line stmt bran cond sub pod time code
1             package Setup::Project;
2 1     1   763 use 5.008001;
  1         3  
3 1     1   5 use strict;
  1         2  
  1         21  
4 1     1   12 use warnings;
  1         2  
  1         32  
5 1     1   5 use File::Basename qw(dirname);
  1         2  
  1         73  
6 1     1   5 use File::Path qw(mkpath);
  1         2  
  1         53  
7 1     1   807 use File::Find::Rule;
  1         8666  
  1         9  
8 1     1   491 use File::Slurp qw(write_file);
  0            
  0            
9             use File::Spec::Functions qw(catfile rel2abs);
10             use Text::Xslate ();
11             use IO::Prompt::Simple qw(prompt);
12             use Setup::Project::Functions;
13             use Module::CPANfile;
14              
15             use Class::Accessor::Lite (
16             rw => [qw/dry_run force_run/],
17             ro => [qw/xslate/]
18             );
19              
20             our $VERSION = "0.01";
21              
22             sub new {
23             my ($class, %args) = @_;
24              
25             my $write_dir = rel2abs($args{write_dir} || '.');
26             my $tmpl_dir = $args{tmpl_dir};
27              
28             my $xslate = Text::Xslate->new(
29             syntax => 'Kolon',
30             type => 'text',
31             tag_start => '<%',
32             tag_end => '%>',
33             line_start => '%%',
34             cache => 0,
35             path => [ $tmpl_dir ],
36             module => [
37             'Text::Xslate::Bridge::Star',
38             ],
39             function => {
40             syntax => sub { "<% $_[0] %>" },
41             }
42             );
43              
44             my $self = bless {
45             file_vars => {},
46             filename_vars => {},
47             dry_run => 0,
48             tmpl_dir => $tmpl_dir,
49             write_dir => $write_dir,
50             xslate => $xslate,
51             force_run => 0,
52             }, $class;
53              
54             }
55              
56             sub safely_run {
57             my ($self, $code) = @_;
58             my $stored = $self->dry_run;
59             $self->dry_run(1);
60             $code->();
61              
62             unless ( prompt "Do you want to do?" => { yn => 1, default => 'n' } ) {
63             $self->infof('abort');
64             return;
65             }
66              
67             $self->dry_run(0);
68             $code->();
69             $self->dry_run($stored);
70             }
71              
72             sub file_vars {
73             my ($self, %args) = @_;
74             $self->{file_vars} = {
75             time => date(),
76             %args,
77             };
78             }
79              
80             sub filename_vars {
81             my ($self, %args) = @_;
82             $self->{filename_vars} = {
83             %args,
84             };
85             }
86              
87             sub run_cmd {
88             my ($self, @args) = @_;
89             $self->infof('[%s] %s', $self->{write_dir}, join q{ }, @args);
90             return if $self->dry_run;
91             chdir $self->{write_dir};
92             !system @args or die "command failed: $?";
93             }
94              
95             sub infof {
96             my ($self, @args) = @_;
97             print "[dry-run] " if $self->dry_run;
98             @args==1 ? print(@args) : printf(@args);
99             print "\n";
100             }
101              
102             sub chmod_recursive {
103             my ($self, $mode, $path) = @_;
104              
105             $path = $self->_to_dst_file($path);
106              
107             if ($self->dry_run) {
108             $self->infof("chmod_recursive $path");
109             return;
110             }
111              
112             File::Find::find(sub {
113             my $name = $File::Find::name;
114             return unless -f $name;
115             $self->infof("chmod $mode $name");
116             return if $self->dry_run;
117             chmod oct($mode), $name;
118             }, $path);
119             }
120              
121             sub render_file {
122             my ($self, $src_filename) = @_;
123             my $content = $self->_render_content($src_filename);
124             my $dst_filename = $self->_to_dst_file($src_filename);
125             $self->_write_file($dst_filename, $content);
126             }
127              
128             sub render_all_files {
129             my $self = shift;
130             my $dir = $self->{tmpl_dir};
131              
132             my @files = File::Find::Rule->file()->in($dir);
133             for my $file (@files) {
134             $file =~ s|$dir/||g;
135             $self->render_file($file);
136             }
137             }
138              
139             sub cpanfile {
140             my ($self, $filename, $args) = @_;
141              
142              
143             my $dst_cpanfile = $self->_to_dst_file($filename);
144             my $cpanfile;
145             if ( -f $dst_cpanfile ) {
146             $cpanfile = Module::CPANfile->load($dst_cpanfile);
147             } else {
148             $cpanfile = Module::CPANfile->from_prereqs();
149             }
150              
151             my $prereqs = $cpanfile->{_prereqs};
152             for my $phase (qw/runtime configure build test develop/) {
153              
154             while (my($module, $version) = each %{ $args->{$phase} }) {
155             $prereqs->add_prereq(
156             phase => $phase,
157             type => 'requires',
158             module => $module,
159             requirement => Module::CPANfile::Requirement->new(name => $module, version => $version),
160             );
161             }
162             }
163              
164             if (!$self->dry_run && -f $filename && !$self->force_run) {
165             unless ( prompt "Do you want to concat? : $filename" => { yn => 1, default => 'n' } ) {
166             return;
167             }
168             }
169             $self->_mkdir(dirname($dst_cpanfile));
170             $self->_write($dst_cpanfile, $cpanfile->to_string);
171             }
172              
173             sub _write_file {
174             my ($self, $filename, $content, $input_mode) = @_;
175              
176             if (!$self->dry_run && -f $filename && !$self->force_run) {
177             unless ( prompt "Do you want to override? : $filename" => { yn => 1, default => 'n' } ) {
178             return;
179             }
180             }
181              
182             $self->_mkdir(dirname($filename));
183             $self->_write($filename, $content, $input_mode);
184              
185             }
186              
187             sub _to_dst_file {
188             my ($self, $filename) = @_;
189             my $dst_filename = $self->_render_filename($filename);
190             my $abs_dst_filename = catfile($self->{write_dir}, $dst_filename);
191             return $abs_dst_filename;
192             }
193              
194             sub _render_filename {
195             my ($self, $filename) = @_;
196              
197             my $dst_filename = $filename;
198             for my $key (keys %{$self->{filename_vars}}) {
199             my $value = $self->{filename_vars}->{$key};
200             $dst_filename =~ s|$key|$value|g;
201             }
202              
203             return $dst_filename;
204             }
205              
206             sub _render_content {
207             my ($self, $filename, $params) = @_;
208             my $content = $self->xslate->render($filename, {
209             %{ $self->{file_vars} },
210             });
211             return $content;
212             }
213              
214             sub _write {
215             my ($self, $filename, $content) = @_;
216             return unless $filename;
217              
218             $self->infof("writing $filename");
219             return if $self->dry_run;
220              
221             write_file($filename, {binmode => ':utf8'}, $content);
222             }
223              
224             sub _mkdir {
225             my ($self, $dirname) = @_;
226             return unless $dirname;
227              
228             #$self->infof("mkdir -p $dirname");
229             return if $self->dry_run;
230              
231             File::Path::make_path($dirname) if $dirname;
232             }
233              
234             1;
235             __END__