File Coverage

lib/App/p5stack.pm
Criterion Covered Total %
statement 75 159 47.1
branch 15 52 28.8
condition 2 3 66.6
subroutine 14 23 60.8
pod 0 2 0.0
total 106 239 44.3


line stmt bran cond sub pod time code
1             package App::p5stack;
2             # ABSTRACT: manage your dependencies and perl requirements locally
3              
4 2     2   25112 use strict;
  2         5  
  2         54  
5 2     2   10 use warnings;
  2         5  
  2         61  
6              
7 2     2   20 use Cwd;
  2         3  
  2         151  
8 2     2   846 use File::Which;
  2         1121  
  2         106  
9 2     2   11 use File::Basename;
  2         3  
  2         160  
10 2     2   838 use File::Spec::Functions;
  2         969  
  2         209  
11 2     2   13 use File::Path qw/make_path/;
  2         4  
  2         137  
12 2     2   2323 use Path::Tiny;
  2         24116  
  2         136  
13 2     2   4529201 use Archive::Tar;
  2         5697801  
  2         139  
14 2     2   2005 use Data::Dumper;
  2         12539  
  2         127  
15 2     2   1384 use YAML;
  2         13548  
  2         3612  
16              
17             sub new {
18 2     2 0 3175 my ($class, @argv) = @_;
19 2         10 my $self = bless {}, $class;
20              
21 2         11 $self->{orig_argv} = [@argv];
22 2 50       14 $self->{command} = @argv ? lc shift @argv : '';
23 2         8 $self->{argv} = [@argv];
24              
25             # handle config
26 2         11 $self->_do_config;
27              
28 2         60 return $self;
29             }
30              
31             sub run {
32 0     0 0 0 my ($self) = @_;
33              
34 0 0       0 if ($self->{command} eq 'setup') { $self->_do_setup; }
  0 0       0  
    0          
    0          
35 0         0 elsif ($self->{command} eq 'perl') { $self->_do_perl; }
36 0         0 elsif ($self->{command} eq 'cpanm') { $self->_do_cpanm; }
37 0         0 elsif ($self->{command} eq 'bin') { $self->_do_bin; }
38 0         0 else { $self->_do_help; }
39             }
40              
41             sub _do_config {
42 2     2   2 my ($self) = @_;
43              
44             # set some defaults
45 2         10 $self->{perl} = 'system';
46 2         16 $self->{deps} = 'dzil';
47 2         5 $self->{skip_install} = 1;
48 2         17 $self->{perls_root} = catfile($ENV{HOME},'.p5stack','perls');
49 2         7 $self->{perl_version} = '5.20.3';
50              
51             # guess stuff from context
52 2 50       48 $self->{deps} = 'cpanfile' if -e 'cpanfile';
53              
54             # read config from file if available
55 2         5 my $file;
56 2 50       17 -e 'p5stack.yml' and $file = 'p5stack.yml';
57 2 50       191 -e "$ENV{HOME}.p5stack/p5stack.yml" and $file = "$ENV{HOME}.p5stack/p5stack.yml"; # FIXME
58 2 100       11 $ENV{P5STACKCFG} and $file = $ENV{P5STACKCFG};
59              
60 2         4 my $config;
61 2 100       7 if ($file) {
62 1         12 my $yaml = path($file)->slurp_utf8;
63 1         2018 $config = Load $yaml;
64             }
65              
66             # FIXME re-factor after logic is more stable
67 2 50       15363 if ( file_name_is_absolute($config->{perl}) ) {
68 0         0 $self->{perl_version} = _get_perl_version($config->{perl});
69 0         0 $self->{perl} = $config->{perl};
70             }
71 2 50       35 if ( $self->{perl} eq 'system' ) {
72 2         13 $self->{perl} = which 'perl';
73 2         285 $self->{perl_version} = _get_perl_version($self->{perl});
74             }
75 2 100 66     77 if ( exists($config->{perl}) and $config->{perl} =~ m/^[\d\.]+$/ ) {
76 1         9 $self->{perl_version} = $config->{perl};
77 1         20 my $perl = catfile($self->{perls_root},$config->{perl},'bin','perl');
78 1         9 $self->{perl} = $perl;
79              
80 1 50       86 $self->{skip_install} = 0 unless -e $perl;
81             }
82 2         15 for (qw/deps/) {
83 2 100       22 $self->{$_} = $config->{$_} if exists $config->{$_};
84             }
85              
86             # set more stuff
87 2         42 $self->{home} = getcwd;
88 2         25 $self->{local_lib} = catfile($self->{home},'.local',$self->{perl_version});
89 2         28 $self->{local_bin} = catfile($self->{home},'.local',$self->{perl_version},'bin');
90 2         17 $self->{Ilib} = catfile($self->{home},'.local',$self->{perl_version},'lib','perl5');
91 2         39 $self->{log_file} = catfile($ENV{HOME},'.p5stack','p5stack-setup.log');
92             }
93              
94             sub _do_setup {
95 0     0   0 my ($self) = @_;
96              
97 0         0 _log('Hammering setup ...');
98 0         0 _log("Tail ".catfile('$HOME','.p5stack','p5stack-setup.log')." to follow the process ...");
99              
100 0         0 $self->_do_install_perl_release;
101              
102 0         0 system "curl -s -L https://cpanmin.us | $self->{perl} - -l $self->{local_lib} --reinstall --no-sudo App::cpanminus local::lib > $self->{log_file} 2>&1";
103              
104 0         0 _log("Getting dependencies info using '$self->{deps}' ...");
105 0         0 _log('Installing dependencies ...');
106 0         0 my $cpanm = $self->_get_cpanm;
107              
108 0 0       0 if ($self->{deps} eq 'dzil') {
109 0         0 my $dzil = which 'dzil';
110 0 0       0 $self->_do_cpanm("Dist::Zilla") unless $dzil;
111              
112 0 0       0 unless (-e catfile($self->{home},'dist.ini')) {
113 0         0 _log('Configuration is set to use "dzil" to gather dependencies information, but no "dist.ini" file was found in current directory.. exiting.');
114 0         0 exit;
115             }
116 0         0 system "$dzil listdeps | $cpanm --no-sudo -l $self->{local_lib}";
117             }
118 0 0       0 if ($self->{deps} eq 'cpanfile') {
119 0 0       0 unless (-e catfile($self->{home},'cpanfile')) {
120 0         0 _log('Configuration is set to use "cpanfile" to gather dependencies information, but no "cpanfile" file was found in current directory.. exiting.');
121 0         0 exit;
122             }
123 0         0 $self->_do_cpanm("--installdeps .");
124             }
125              
126 0         0 print "[p5stack] Setup done, use 'p5stack perl' to run your application.\n";
127             }
128              
129             sub _get_cpanm {
130 0     0   0 my ($self) = @_;
131              
132 0         0 my $cpanm = catfile($self->{local_lib}, 'bin', 'cpanm');
133 0 0       0 $cpanm = which 'cpanm' unless $cpanm; # FIXME default to system?
134              
135 0         0 return $cpanm;
136             }
137              
138             sub _do_install_perl_release {
139 0     0   0 my ($self) = @_;
140              
141 0 0       0 if (-e $self->{perl}) {
142 0         0 _log("Found $self->{perl_version} release using it.");
143 0         0 return;
144             }
145              
146 0         0 my $curl = which 'curl'; # TODO failsafe to wget ?
147 0         0 my $file = join '', 'perl-', $self->{perl_version}, '.tar.gz';
148 0         0 my $dest = catfile($self->{perls_root}, $file);
149 0         0 my $url = join '', 'http://www.cpan.org/src/5.0/', $file;
150              
151 0         0 _log("Downloading $self->{perl_version} release ...");
152 0 0       0 make_path(dirname($dest)) unless -e dirname($dest);
153 0 0       0 system "$curl -s -o $dest $url" unless -e $dest;
154              
155 0         0 my $curr = getcwd;
156 0         0 chdir $self->{perls_root};
157              
158 0         0 _log("Extracting $self->{perl_version} release ...");
159 0         0 Archive::Tar->extract_archive($file);
160              
161 0         0 chdir catfile($self->{perls_root}, "perl-$self->{perl_version}");
162            
163 0         0 _log("Configuring $self->{perl_version} release ...");
164 0         0 my $prefix = catfile($self->{perls_root}, $self->{perl_version});
165 0         0 system "sh Configure -de -Dprefix=$prefix > $self->{log_file} 2>&1";
166              
167 0         0 _log("Building $self->{perl_version} release ...");
168 0         0 system "make >> $self->{log_file} 2>&1";
169              
170 0         0 _log("Testing $self->{perl_version} release ...");
171 0         0 system "make test >> $self->{log_file} 2>&1";
172              
173 0         0 _log("Installing $self->{perl_version} release ...");
174 0         0 system "make install >> $self->{log_file} 2>&1";
175              
176             }
177              
178             sub _do_perl {
179 0     0   0 my ($self) = @_;
180              
181             my $run = join(' ',$self->{perl}, "-I $self->{Ilib}",
182 0         0 "-Mlocal::lib", @{$self->{argv}});
  0         0  
183              
184 0         0 system $run;
185             }
186              
187             sub _do_cpanm {
188 0     0   0 my ($self, @args) = @_;
189 0 0       0 @args = @{$self->{argv}} unless @args;
  0         0  
190              
191 0         0 my $cpanm = $self->_get_cpanm;
192 0         0 my $log = "";
193 0 0       0 $log = ">> $self->{log_file} 2>&1" if $self->{command} eq 'setup';
194 0         0 my $run = join ' ', $cpanm, "--no-sudo", "-L $self->{local_lib}", @args, $log;
195              
196 0         0 system $run;
197             }
198              
199             sub _do_bin {
200 0     0   0 my ($self) = @_;
201              
202 0         0 my @argv = @{ $self->{argv} };
  0         0  
203 0         0 my $bin = catfile($self->{local_bin}, shift @argv);
204 0         0 my @env = ("PERL5LIB=$self->{Ilib}", "PATH=$self->{local_bin}:\$PATH");
205 0         0 my $run = join ' ', @env, $bin, @argv;
206              
207 0         0 system $run;
208             }
209              
210             sub _get_perl_version {
211 2     2   5 my ($perl) = @_;
212              
213 2         24844 my $version = `$perl -e 'print \$^V'`;
214 2         86 $version =~ s/^v//;
215              
216 2         61 return $version;
217             }
218              
219             sub _log {
220 0     0     my ($msg) = @_;
221              
222             # FIXME smaller timestamp
223 0           my $now = localtime;
224 0           $now =~ s/\s\d+$//;
225 0           $now =~ s/^\w+/-/;
226              
227 0           print "[p5stack $now] $msg\n";
228             }
229              
230             sub _do_help {
231 0     0     print "Usage:\n",
232             " \$ p5stack setup # setup env in current directory\n",
233             " \$ p5stack perl [args] # run a program\n",
234             " \$ p5stack bin [args] # execute a installed bin file\n",
235             " \$ p5stack cpanm [args] # execute local env cpanm\n";
236             }
237              
238             1;
239              
240             __END__